This is an automated email from the ASF dual-hosted git repository.
hansva pushed a commit to branch main
in repository https://gitbox.apache.org/repos/asf/hop.git
The following commit(s) were added to refs/heads/main by this push:
new b6b0b62adb multiway merge UI fixes and XML cleanup, fixes #6356 (#6360)
b6b0b62adb is described below
commit b6b0b62adb59ee9a7f6b5e96150345953e9fa697
Author: Hans Van Akelyen <[email protected]>
AuthorDate: Tue Jan 13 14:05:19 2026 +0100
multiway merge UI fixes and XML cleanup, fixes #6356 (#6360)
---
.../transforms/multimerge/MultiMergeJoin.java | 33 ++---
.../multimerge/MultiMergeJoinDialog.java | 86 +++++++-----
.../transforms/multimerge/MultiMergeJoinMeta.java | 148 +++++----------------
3 files changed, 102 insertions(+), 165 deletions(-)
diff --git
a/plugins/transforms/multimerge/src/main/java/org/apache/hop/pipeline/transforms/multimerge/MultiMergeJoin.java
b/plugins/transforms/multimerge/src/main/java/org/apache/hop/pipeline/transforms/multimerge/MultiMergeJoin.java
index a61b6885ca..0f39e5a62f 100644
---
a/plugins/transforms/multimerge/src/main/java/org/apache/hop/pipeline/transforms/multimerge/MultiMergeJoin.java
+++
b/plugins/transforms/multimerge/src/main/java/org/apache/hop/pipeline/transforms/multimerge/MultiMergeJoin.java
@@ -76,11 +76,11 @@ public class MultiMergeJoin extends
BaseTransform<MultiMergeJoinMeta, MultiMerge
TransformMeta fromTransformMeta;
ArrayList<String> inputTransformNameList = new ArrayList<>();
- String[] inputTransformNames = meta.getInputTransforms();
+ List<String> inputTransformNames = meta.getInputTransforms();
String inputTransformName;
for (int i = 0; i < infoStreams.size(); i++) {
- inputTransformName = inputTransformNames[i];
+ inputTransformName = inputTransformNames.get(i);
stream = infoStreams.get(i);
fromTransformMeta = stream.getTransformMeta();
if (fromTransformMeta == null) {
@@ -136,8 +136,8 @@ public class MultiMergeJoin extends
BaseTransform<MultiMergeJoinMeta, MultiMerge
IRowMeta rowMeta;
data.outputRowMeta = new RowMeta();
- for (int i = 0, j = 0; i < inputTransformNames.length; i++) {
- inputTransformName = inputTransformNames[i];
+ for (int i = 0, j = 0; i < inputTransformNames.size(); i++) {
+ inputTransformName = inputTransformNames.get(i);
if (!inputTransformNameList.contains(inputTransformName)) {
// ignore transform with disabled hop.
continue;
@@ -168,7 +168,7 @@ public class MultiMergeJoin extends
BaseTransform<MultiMergeJoinMeta, MultiMerge
queueEntry.row = row;
rowMeta = rowSet.getRowMeta();
- keyField = meta.getKeyFields()[i];
+ keyField = meta.getKeyFields().get(i);
String[] keyFieldParts = keyField.split(",");
String keyFieldPart;
data.keyNrs[j] = new int[keyFieldParts.length];
@@ -209,13 +209,14 @@ public class MultiMergeJoin extends
BaseTransform<MultiMergeJoinMeta, MultiMerge
}
if (isRowLevel()) {
- String metaString =
- BaseMessages.getString(
- PKG, "MultiMergeJoin.Log.DataInfo",
data.metas[0].getString(data.rows[0]) + "");
+ StringBuilder metaString =
+ new StringBuilder(
+ BaseMessages.getString(
+ PKG, "MultiMergeJoin.Log.DataInfo",
data.metas[0].getString(data.rows[0])));
for (int i = 1; i < data.metas.length; i++) {
- metaString += data.metas[i].getString(data.rows[i]);
+ metaString.append(data.metas[i].getString(data.rows[i]));
}
- logRowlevel(metaString);
+ logRowlevel(metaString.toString());
}
/*
@@ -396,12 +397,12 @@ public class MultiMergeJoin extends
BaseTransform<MultiMergeJoinMeta, MultiMerge
if (super.init()) {
ITransformIOMeta transformIOMeta = meta.getTransformIOMeta();
- String[] inputTransformNames = meta.getInputTransforms();
+ List<String> inputTransformNames = meta.getInputTransforms();
String inputTransformName;
List<IStream> infoStreams = transformIOMeta.getInfoStreams();
IStream stream;
for (int i = 0; i < infoStreams.size(); i++) {
- inputTransformName = inputTransformNames[i];
+ inputTransformName = inputTransformNames.get(i);
stream = infoStreams.get(i);
if (stream.getTransformMeta() == null) {
logError(
@@ -437,9 +438,9 @@ public class MultiMergeJoin extends
BaseTransform<MultiMergeJoinMeta, MultiMerge
protected boolean isInputLayoutValid(IRowMeta[] rows) {
if (rows != null) {
// Compare the key types
- String[] keyFields = meta.getKeyFields();
+ List<String> keyFields = meta.getKeyFields();
// check 1 : keys are configured for each stream
- if (rows.length != keyFields.length) {
+ if (rows.length != keyFields.size()) {
logError("keys are not configured for all the streams ");
return false;
}
@@ -447,8 +448,8 @@ public class MultiMergeJoin extends
BaseTransform<MultiMergeJoinMeta, MultiMerge
int prevCount = 0;
List<String[]> keyList = new ArrayList<>();
- for (int i = 0; i < keyFields.length; i++) {
- String[] keys = keyFields[i].split(",");
+ for (int i = 0; i < keyFields.size(); i++) {
+ String[] keys = keyFields.get(i).split(",");
keyList.add(keys);
int count = keys.length;
if (i != 0 && prevCount != count) {
diff --git
a/plugins/transforms/multimerge/src/main/java/org/apache/hop/pipeline/transforms/multimerge/MultiMergeJoinDialog.java
b/plugins/transforms/multimerge/src/main/java/org/apache/hop/pipeline/transforms/multimerge/MultiMergeJoinDialog.java
index 24d1e74280..eccf4f5335 100644
---
a/plugins/transforms/multimerge/src/main/java/org/apache/hop/pipeline/transforms/multimerge/MultiMergeJoinDialog.java
+++
b/plugins/transforms/multimerge/src/main/java/org/apache/hop/pipeline/transforms/multimerge/MultiMergeJoinDialog.java
@@ -72,6 +72,7 @@ public class MultiMergeJoinDialog extends BaseTransformDialog
{
private final int middle = props.getMiddlePct();
private final MultiMergeJoinMeta joinMeta;
+ private String[] allInputTransforms;
public MultiMergeJoinDialog(
Shell parent,
@@ -81,14 +82,20 @@ public class MultiMergeJoinDialog extends
BaseTransformDialog {
super(parent, variables, transformMeta, pipelineMeta);
joinMeta = transformMeta;
- String[] inputTransformNames = getInputTransformNames();
- wInputTransformArray = new CCombo[inputTransformNames.length];
- keyValTextBox = new Text[inputTransformNames.length];
+ allInputTransforms = getInputTransformNames();
+ int numInputs =
+ Math.max(
+ 2,
+ joinMeta.getInputTransforms() != null
+ ? joinMeta.getInputTransforms().size()
+ : pipelineMeta.getPrevTransformNames(transformName).length);
+
+ wInputTransformArray = new CCombo[numInputs];
+ keyValTextBox = new Text[numInputs];
}
private String[] getInputTransformNames() {
ArrayList<String> nameList = new ArrayList<>();
-
String[] prevTransformNames =
pipelineMeta.getPrevTransformNames(transformName);
if (prevTransformNames != null) {
String prevTransformName;
@@ -100,8 +107,6 @@ public class MultiMergeJoinDialog extends
BaseTransformDialog {
nameList.add(prevTransformName);
}
}
-
- joinMeta.setInputTransforms(nameList.toArray(new String[0]));
return nameList.toArray(new String[0]);
}
@@ -177,7 +182,7 @@ public class MultiMergeJoinDialog extends
BaseTransformDialog {
/**
* Create widgets for join type selection
*
- * @param lsMod
+ * @param lsMod the modify listener
*/
private void createJoinTypeWidget(final ModifyListener lsMod) {
Label joinTypeLabel = new Label(shell, SWT.RIGHT);
@@ -193,7 +198,7 @@ public class MultiMergeJoinDialog extends
BaseTransformDialog {
fdlType.top = new FormAttachment(wTransformName, margin * 3);
}
joinTypeLabel.setLayoutData(fdlType);
- joinTypeCombo = new CCombo(shell, SWT.BORDER);
+ joinTypeCombo = new CCombo(shell, SWT.SINGLE | SWT.READ_ONLY | SWT.BORDER);
PropsUi.setLook(joinTypeCombo);
joinTypeCombo.setItems(MultiMergeJoinMeta.joinTypes);
@@ -209,12 +214,11 @@ public class MultiMergeJoinDialog extends
BaseTransformDialog {
/**
* create widgets for input stream and join keys
*
- * @param lsMod
+ * @param lsMod the modify listener
*/
private void createInputStreamWidgets(final ModifyListener lsMod) {
- // Get the previous transforms ...
- String[] inputTransforms = getInputTransformNames();
- for (int index = 0; index < inputTransforms.length; index++) {
+ String[] inputTransforms = allInputTransforms;
+ for (int index = 0; index < wInputTransformArray.length; index++) {
Label wlTransform;
FormData fdlTransform;
FormData fdTransform1;
@@ -239,6 +243,7 @@ public class MultiMergeJoinDialog extends
BaseTransformDialog {
wInputTransformArray[index].setItems(inputTransforms);
wInputTransformArray[index].addModifyListener(lsMod);
+
fdTransform1 = new FormData();
fdTransform1.left = new FormAttachment(wlTransform, margin);
fdTransform1.top = new FormAttachment(wlTransform, 0, SWT.CENTER);
@@ -278,8 +283,8 @@ public class MultiMergeJoinDialog extends
BaseTransformDialog {
/**
* "Configure join key" shell
*
- * @param keyValTextBox
- * @param lsMod
+ * @param keyValTextBox the text widget that needs to be added
+ * @param lsMod modify listener
*/
private void configureKeys(
final Text keyValTextBox, final int inputStreamIndex, ModifyListener
lsMod) {
@@ -365,13 +370,12 @@ public class MultiMergeJoinDialog extends
BaseTransformDialog {
getKeyButton.setLayoutData(fdbKeys);
getKeyButton.addListener(
SWT.Selection,
- e -> {
- BaseTransformDialog.getFieldsFromPrevious(
- prev, wKeys, 1, new int[] {1}, new int[] {}, -1, -1, null);
- });
+ e ->
+ BaseTransformDialog.getFieldsFromPrevious(
+ prev, wKeys, 1, new int[] {1}, new int[] {}, -1, -1, null));
Listener onOk =
- (e) -> {
+ e -> {
int nrKeys = wKeys.nrNonEmpty();
StringBuilder sb = new StringBuilder();
for (int i = 0; i < nrKeys; i++) {
@@ -414,17 +418,34 @@ public class MultiMergeJoinDialog extends
BaseTransformDialog {
/** Copy information from the meta-data input to the dialog fields. */
public void getData() {
- String[] inputTransformNames = joinMeta.getInputTransforms();
+ List<String> inputTransformNames = joinMeta.getInputTransforms();
if (inputTransformNames != null) {
String inputTransformName;
- String[] keyFields = joinMeta.getKeyFields();
+ List<String> keyFields = joinMeta.getKeyFields();
String keyField;
- for (int i = 0; i < inputTransformNames.length; i++) {
- inputTransformName = Const.NVL(inputTransformNames[i], "");
- wInputTransformArray[i].setText(inputTransformName);
- keyField = Const.NVL(i < keyFields.length ? keyFields[i] : null, "");
- keyValTextBox[i].setText(keyField);
+ // Create a set of available transforms for quick lookup
+ List<String> availableTransforms =
java.util.Arrays.asList(allInputTransforms);
+
+ // Load transforms from metadata, but only if they still exist in the
pipeline
+ int widgetIndex = 0;
+ for (int i = 0;
+ i < inputTransformNames.size() && widgetIndex <
wInputTransformArray.length;
+ i++) {
+ inputTransformName = Const.NVL(inputTransformNames.get(i), "");
+
+ // Skip transforms that no longer exist in the pipeline
+ if (!Utils.isEmpty(inputTransformName)
+ && !availableTransforms.contains(inputTransformName)) {
+ continue;
+ }
+
+ wInputTransformArray[widgetIndex].setText(inputTransformName);
+
+ keyField = Const.NVL(i < keyFields.size() ? keyFields.get(i) : null,
"");
+ keyValTextBox[widgetIndex].setText(keyField);
+
+ widgetIndex++;
}
String joinType = joinMeta.getJoinType();
@@ -434,6 +455,7 @@ public class MultiMergeJoinDialog extends
BaseTransformDialog {
joinTypeCombo.setText(MultiMergeJoinMeta.joinTypes[0]);
}
}
+
wTransformName.selectAll();
wTransformName.setFocus();
}
@@ -447,7 +469,7 @@ public class MultiMergeJoinDialog extends
BaseTransformDialog {
/**
* Get the meta data
*
- * @param meta
+ * @param meta metadata to fetch information from
*/
private void getMeta(MultiMergeJoinMeta meta) {
ITransformIOMeta transformIOMeta = meta.getTransformIOMeta();
@@ -476,19 +498,17 @@ public class MultiMergeJoinDialog extends
BaseTransformDialog {
}
}
+ // Save the input transforms and key fields in the order they appear in
the UI
+ meta.setInputTransforms(inputTransformNameList);
+ meta.setKeyFields(keyList);
+
int inputTransformCount = inputTransformNameList.size();
- meta.allocateInputTransforms(inputTransformCount);
- meta.allocateKeys(inputTransformCount);
- String[] inputTransforms = meta.getInputTransforms();
- String[] keyFields = meta.getKeyFields();
infoStreams = transformIOMeta.getInfoStreams();
for (int i = 0; i < inputTransformCount; i++) {
inputTransformName = inputTransformNameList.get(i);
- inputTransforms[i] = inputTransformName;
stream = infoStreams.get(i);
stream.setTransformMeta(pipelineMeta.findTransform(inputTransformName));
- keyFields[i] = keyList.get(i);
}
meta.setJoinType(joinTypeCombo.getText());
diff --git
a/plugins/transforms/multimerge/src/main/java/org/apache/hop/pipeline/transforms/multimerge/MultiMergeJoinMeta.java
b/plugins/transforms/multimerge/src/main/java/org/apache/hop/pipeline/transforms/multimerge/MultiMergeJoinMeta.java
index f929ff3159..79b3e3c6ec 100644
---
a/plugins/transforms/multimerge/src/main/java/org/apache/hop/pipeline/transforms/multimerge/MultiMergeJoinMeta.java
+++
b/plugins/transforms/multimerge/src/main/java/org/apache/hop/pipeline/transforms/multimerge/MultiMergeJoinMeta.java
@@ -18,19 +18,18 @@
package org.apache.hop.pipeline.transforms.multimerge;
import java.util.List;
-import org.apache.commons.lang.ArrayUtils;
+import lombok.Getter;
+import lombok.Setter;
import org.apache.hop.core.CheckResult;
-import org.apache.hop.core.Const;
import org.apache.hop.core.ICheckResult;
import org.apache.hop.core.annotations.Transform;
import org.apache.hop.core.exception.HopTransformException;
import org.apache.hop.core.exception.HopXmlException;
-import org.apache.hop.core.injection.Injection;
-import org.apache.hop.core.injection.InjectionSupported;
import org.apache.hop.core.row.IRowMeta;
import org.apache.hop.core.variables.IVariables;
import org.apache.hop.core.xml.XmlHandler;
import org.apache.hop.i18n.BaseMessages;
+import org.apache.hop.metadata.api.HopMetadataProperty;
import org.apache.hop.metadata.api.IHopMetadataProvider;
import org.apache.hop.pipeline.PipelineMeta;
import org.apache.hop.pipeline.transform.BaseTransformMeta;
@@ -41,7 +40,6 @@ import org.apache.hop.pipeline.transform.stream.Stream;
import org.apache.hop.pipeline.transform.stream.StreamIcon;
import org.w3c.dom.Node;
-@InjectionSupported(localizationPrefix = "MultiMergeJoin.Injection.")
@Transform(
id = "MultiwayMergeJoin",
image = "multimergejoin.svg",
@@ -50,54 +48,27 @@ import org.w3c.dom.Node;
categoryDescription =
"i18n:org.apache.hop.pipeline.transform:BaseTransform.Category.Joins",
keywords = "i18n::MultiMergeJoinMeta.keyword",
documentationUrl = "/pipeline/transforms/multimerge.html")
+@Getter
+@Setter
public class MultiMergeJoinMeta extends BaseTransformMeta<MultiMergeJoin,
MultiMergeJoinData> {
private static final Class<?> PKG = MultiMergeJoinMeta.class;
public static final String[] joinTypes = {"INNER", "FULL OUTER"};
public static final boolean[] optionals = {false, true};
- @Injection(name = "JOIN_TYPE")
+ @HopMetadataProperty(key = "join_type", injectionKey = "JOIN_TYPE")
private String joinType;
/** comma separated key values for each stream */
- @Injection(name = "KEY_FIELDS")
- private String[] keyFields;
+ @HopMetadataProperty(key = "key", groupKey = "keys", injectionKey =
"JOIN_TYPE")
+ private List<String> keyFields;
/** input stream names */
- @Injection(name = "INPUT_TRANSFORMS")
- private String[] inputTransforms;
-
- /**
- * The supported join types are INNER, LEFT OUTER, RIGHT OUTER and FULL OUTER
- *
- * @return The type of join
- */
- public String getJoinType() {
- return joinType;
- }
-
- /**
- * Sets the type of join
- *
- * @param joinType The type of join, e.g. INNER/FULL OUTER
- */
- public void setJoinType(String joinType) {
- this.joinType = joinType;
- }
-
- /**
- * @return Returns the keyFields1.
- */
- public String[] getKeyFields() {
- return keyFields;
- }
-
- /**
- * @param keyFields The keyFields1 to set.
- */
- public void setKeyFields(String[] keyFields) {
- this.keyFields = keyFields;
- }
+ @HopMetadataProperty(
+ key = "transform",
+ groupKey = "transforms",
+ injectionKey = "INPUT_TRANSFORMS")
+ private List<String> inputTransforms;
@Override
public boolean excludeFromRowLayoutVerification() {
@@ -108,76 +79,36 @@ public class MultiMergeJoinMeta extends
BaseTransformMeta<MultiMergeJoin, MultiM
super(); // allocate BaseTransformMeta
}
+ /**
+ * keep loadXml to load old style xml information for the transform
+ *
+ * @deprecated
+ * @param transformNode the XML node from the pipeline
+ * @param metadataProvider metadata provider to resolve things
+ * @throws HopXmlException when we can't read the XML correctly
+ */
@Override
+ @Deprecated(since = "2.17")
public void loadXml(Node transformNode, IHopMetadataProvider
metadataProvider)
throws HopXmlException {
+ super.loadXml(transformNode, metadataProvider);
+ // keep for backwards compatibility
readData(transformNode);
}
- public void allocateKeys(int nrKeys) {
- keyFields = new String[nrKeys];
- }
-
- @Override
- public Object clone() {
- MultiMergeJoinMeta retval = (MultiMergeJoinMeta) super.clone();
- int nrKeys = keyFields == null ? 0 : keyFields.length;
- int nrTransforms = inputTransforms == null ? 0 : inputTransforms.length;
- retval.allocateKeys(nrKeys);
- retval.allocateInputTransforms(nrTransforms);
- System.arraycopy(keyFields, 0, retval.keyFields, 0, nrKeys);
- System.arraycopy(inputTransforms, 0, retval.inputTransforms, 0,
nrTransforms);
- return retval;
- }
-
- @Override
- public String getXml() {
- StringBuilder retval = new StringBuilder();
-
- String[] inputTransformsNames =
- inputTransforms != null ? inputTransforms :
ArrayUtils.EMPTY_STRING_ARRAY;
- retval.append(" ").append(XmlHandler.addTagValue("join_type",
getJoinType()));
- for (int i = 0; i < inputTransformsNames.length; i++) {
- retval
- .append(" ")
- .append(XmlHandler.addTagValue("transform" + i,
inputTransformsNames[i]));
- }
-
- retval
- .append(" ")
- .append(XmlHandler.addTagValue("number_input",
inputTransformsNames.length));
- retval.append(" ").append(XmlHandler.openTag("keys")).append(Const.CR);
- for (String keyField : keyFields) {
- retval.append(" ").append(XmlHandler.addTagValue("key", keyField));
- }
- retval.append(" ").append(XmlHandler.closeTag("keys")).append(Const.CR);
-
- return retval.toString();
- }
-
private void readData(Node transformNode) throws HopXmlException {
try {
+ String numInputStreamsStr = XmlHandler.getTagValue(transformNode,
"number_input");
- Node keysNode = XmlHandler.getSubNode(transformNode, "keys");
-
- int nrKeys = XmlHandler.countNodes(keysNode, "key");
-
- allocateKeys(nrKeys);
-
- for (int i = 0; i < nrKeys; i++) {
- Node keynode = XmlHandler.getSubNodeByNr(keysNode, "key", i);
- keyFields[i] = XmlHandler.getNodeValue(keynode);
+ // Skip if number_input doesn't exist (null or empty)
+ if (numInputStreamsStr == null || numInputStreamsStr.trim().isEmpty()) {
+ return;
}
- int nInputStreams =
Integer.parseInt(XmlHandler.getTagValue(transformNode, "number_input"));
-
- allocateInputTransforms(nInputStreams);
-
+ int nInputStreams = Integer.parseInt(numInputStreamsStr);
for (int i = 0; i < nInputStreams; i++) {
- inputTransforms[i] = XmlHandler.getTagValue(transformNode, "transform"
+ i);
+ inputTransforms.add(XmlHandler.getTagValue(transformNode, "transform"
+ i));
}
-
- joinType = XmlHandler.getTagValue(transformNode, "join_type");
} catch (Exception e) {
throw new HopXmlException(
BaseMessages.getString(PKG,
"MultiMergeJoinMeta.Exception.UnableToLoadTransformMeta"), e);
@@ -187,16 +118,14 @@ public class MultiMergeJoinMeta extends
BaseTransformMeta<MultiMergeJoin, MultiM
@Override
public void setDefault() {
joinType = joinTypes[0];
- allocateKeys(0);
- allocateInputTransforms(0);
}
@Override
public void searchInfoAndTargetTransforms(List<TransformMeta> transforms) {
ITransformIOMeta ioMeta = getTransformIOMeta();
ioMeta.getInfoStreams().clear();
- for (int i = 0; i < inputTransforms.length; i++) {
- String inputTransformName = inputTransforms[i];
+ for (int i = 0; i < inputTransforms.size(); i++) {
+ String inputTransformName = inputTransforms.get(i);
if (i >= ioMeta.getInfoStreams().size()) {
ioMeta.addStream(
new Stream(
@@ -255,23 +184,10 @@ public class MultiMergeJoinMeta extends
BaseTransformMeta<MultiMergeJoin, MultiM
for (int i = 0; i < r.size(); i++) {
r.getValueMeta(i).setOrigin(name);
}
- return;
}
@Override
public void resetTransformIoMeta() {
// Don't reset!
}
-
- public void setInputTransforms(String[] inputTransforms) {
- this.inputTransforms = inputTransforms;
- }
-
- public String[] getInputTransforms() {
- return inputTransforms;
- }
-
- public void allocateInputTransforms(int count) {
- inputTransforms = new String[count];
- }
}