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 b5da4239e4 issue #1925 (Get rows from result XML cleanup) (#6795)
b5da4239e4 is described below

commit b5da4239e4f3c6d6ec9fece6a9b4eb08b311cf18
Author: Matt Casters <[email protected]>
AuthorDate: Tue Mar 17 09:26:38 2026 +0100

    issue #1925 (Get rows from result XML cleanup) (#6795)
---
 .../mdi/datasets/golden-rows-from-result.csv       |   5 +
 .../mdi/files/get-rows-from-result.xml             |  46 +++++
 .../metadata/dataset/golden-rows-from-result.json  |  40 +++++
 .../0041-rows-from-result-validate UNIT.json       |  40 +++++
 .../rowsfromresult/RowsFromResultDialog.java       |  35 ++--
 .../rowsfromresult/RowsFromResultMeta.java         | 186 +++++++--------------
 .../messages/messages_en_US.properties             |   6 +
 .../rowsfromresult/RowsFromResultMetaTest.java     | 138 ++++++++-------
 .../src/test/resources/transform.xml               |  46 +++++
 9 files changed, 341 insertions(+), 201 deletions(-)

diff --git a/integration-tests/mdi/datasets/golden-rows-from-result.csv 
b/integration-tests/mdi/datasets/golden-rows-from-result.csv
new file mode 100644
index 0000000000..c3bfbdadf3
--- /dev/null
+++ b/integration-tests/mdi/datasets/golden-rows-from-result.csv
@@ -0,0 +1,5 @@
+name,type,length,precision
+field1,String,100,-1
+field2,Date,-1,-1
+field3,Integer,7,-1
+field4,Number,9,2
diff --git a/integration-tests/mdi/files/get-rows-from-result.xml 
b/integration-tests/mdi/files/get-rows-from-result.xml
new file mode 100644
index 0000000000..7a79ddec53
--- /dev/null
+++ b/integration-tests/mdi/files/get-rows-from-result.xml
@@ -0,0 +1,46 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+  ~ Licensed to the Apache Software Foundation (ASF) under one or more
+  ~ contributor license agreements.  See the NOTICE file distributed with
+  ~ this work for additional information regarding copyright ownership.
+  ~ The ASF licenses this file to You under the Apache License, Version 2.0
+  ~ (the "License"); you may not use this file except in compliance with
+  ~ the License.  You may obtain a copy of the License at
+  ~
+  ~       http://www.apache.org/licenses/LICENSE-2.0
+  ~
+  ~ Unless required by applicable law or agreed to in writing, software
+  ~ distributed under the License is distributed on an "AS IS" BASIS,
+  ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+  ~ See the License for the specific language governing permissions and
+  ~ limitations under the License.
+  -->
+
+<transform>
+    <fields>
+        <field>
+            <name>field1</name>
+            <type>String</type>
+            <length>100</length>
+            <precision>-1</precision>
+        </field>
+        <field>
+            <name>field2</name>
+            <type>Date</type>
+            <length>-1</length>
+            <precision>-1</precision>
+        </field>
+        <field>
+            <name>field3</name>
+            <type>Integer</type>
+            <length>7</length>
+            <precision>-1</precision>
+        </field>
+        <field>
+            <name>field4</name>
+            <type>Number</type>
+            <length>9</length>
+            <precision>2</precision>
+        </field>
+    </fields>
+</transform>
diff --git 
a/integration-tests/mdi/metadata/dataset/golden-rows-from-result.json 
b/integration-tests/mdi/metadata/dataset/golden-rows-from-result.json
new file mode 100644
index 0000000000..9fc21e7817
--- /dev/null
+++ b/integration-tests/mdi/metadata/dataset/golden-rows-from-result.json
@@ -0,0 +1,40 @@
+{
+  "base_filename": "golden-rows-from-result.csv",
+  "name": "golden-rows-from-result",
+  "description": "",
+  "dataset_fields": [
+    {
+      "field_comment": "",
+      "field_length": -1,
+      "field_type": 2,
+      "field_precision": -1,
+      "field_name": "name",
+      "field_format": ""
+    },
+    {
+      "field_comment": "",
+      "field_length": -1,
+      "field_type": 2,
+      "field_precision": -1,
+      "field_name": "type",
+      "field_format": ""
+    },
+    {
+      "field_comment": "",
+      "field_length": -1,
+      "field_type": 5,
+      "field_precision": 0,
+      "field_name": "length",
+      "field_format": "####0;-####0"
+    },
+    {
+      "field_comment": "",
+      "field_length": -1,
+      "field_type": 5,
+      "field_precision": 0,
+      "field_name": "precision",
+      "field_format": "####0;-####0"
+    }
+  ],
+  "folder_name": ""
+}
\ No newline at end of file
diff --git 
a/integration-tests/mdi/metadata/unit-test/0041-rows-from-result-validate 
UNIT.json 
b/integration-tests/mdi/metadata/unit-test/0041-rows-from-result-validate 
UNIT.json
new file mode 100644
index 0000000000..19ab0c2eb5
--- /dev/null
+++ b/integration-tests/mdi/metadata/unit-test/0041-rows-from-result-validate 
UNIT.json 
@@ -0,0 +1,40 @@
+{
+  "database_replacements": [],
+  "autoOpening": true,
+  "description": "",
+  "persist_filename": "",
+  "test_type": "UNIT_TEST",
+  "variableValues": [],
+  "basePath": "${HOP_UNIT_TESTS_FOLDER}",
+  "golden_data_sets": [
+    {
+      "field_mappings": [
+        {
+          "transform_field": "name",
+          "data_set_field": "name"
+        },
+        {
+          "transform_field": "type",
+          "data_set_field": "type"
+        },
+        {
+          "transform_field": "length",
+          "data_set_field": "length"
+        },
+        {
+          "transform_field": "precision",
+          "data_set_field": "precision"
+        }
+      ],
+      "field_order": [
+        "name"
+      ],
+      "data_set_name": "golden-rows-from-result",
+      "transform_name": "Validate"
+    }
+  ],
+  "input_data_sets": [],
+  "name": "0041-rows-from-result-validate UNIT",
+  "trans_test_tweaks": [],
+  "pipeline_filename": 
"/home/matt.casters/Projects/demo/0041-rows-from-result-validate.hpl"
+}
\ No newline at end of file
diff --git 
a/plugins/transforms/rowsfromresult/src/main/java/org/apache/hop/pipeline/transforms/rowsfromresult/RowsFromResultDialog.java
 
b/plugins/transforms/rowsfromresult/src/main/java/org/apache/hop/pipeline/transforms/rowsfromresult/RowsFromResultDialog.java
index 638f30b500..fa848c1fb1 100644
--- 
a/plugins/transforms/rowsfromresult/src/main/java/org/apache/hop/pipeline/transforms/rowsfromresult/RowsFromResultDialog.java
+++ 
b/plugins/transforms/rowsfromresult/src/main/java/org/apache/hop/pipeline/transforms/rowsfromresult/RowsFromResultDialog.java
@@ -69,9 +69,9 @@ public class RowsFromResultDialog extends BaseTransformDialog 
{
     fdlFields.top = new FormAttachment(wSpacer, margin);
     wlFields.setLayoutData(fdlFields);
 
-    final int FieldsRows = input.getFieldname().length;
+    final int FieldsRows = input.getResultFields().size();
 
-    ColumnInfo[] colinf =
+    ColumnInfo[] columnInfos =
         new ColumnInfo[] {
           new ColumnInfo(
               BaseMessages.getString(PKG, 
"RowsFromResultDialog.ColumnInfo.Fieldname"),
@@ -96,7 +96,7 @@ public class RowsFromResultDialog extends BaseTransformDialog 
{
             variables,
             shell,
             SWT.BORDER | SWT.FULL_SELECTION | SWT.MULTI,
-            colinf,
+            columnInfos,
             FieldsRows,
             lsMod,
             props);
@@ -122,12 +122,13 @@ public class RowsFromResultDialog extends 
BaseTransformDialog {
 
   /** Copy information from the meta-data input to the dialog fields. */
   public void getData() {
-    for (int i = 0; i < input.getFieldname().length; i++) {
+    for (int i = 0; i < input.getResultFields().size(); i++) {
+      RowsFromResultMeta.ResultRowField field = input.getResultFields().get(i);
       TableItem item = wFields.table.getItem(i);
-      item.setText(1, input.getFieldname()[i] == null ? "" : 
input.getFieldname()[i]);
-      item.setText(2, ValueMetaFactory.getValueMetaName(input.getType()[i]));
-      int len = input.getLength()[i];
-      int prc = input.getPrecision()[i];
+      item.setText(1, Const.NVL(field.getName(), ""));
+      item.setText(2, ValueMetaFactory.getValueMetaName(field.getHopType()));
+      int len = field.getLength();
+      int prc = field.getPrecision();
       item.setText(3, len >= 0 ? "" + len : "");
       item.setText(4, prc >= 0 ? "" + prc : "");
     }
@@ -145,15 +146,15 @@ public class RowsFromResultDialog extends 
BaseTransformDialog {
     }
 
     transformName = wTransformName.getText(); // return value
-    int nrFields = wFields.nrNonEmpty();
-    input.allocate(nrFields);
-
-    for (int i = 0; i < nrFields; i++) {
-      TableItem item = wFields.getNonEmpty(i);
-      input.getFieldname()[i] = item.getText(1);
-      input.getType()[i] = ValueMetaFactory.getIdForValueMeta(item.getText(2));
-      input.getLength()[i] = Const.toInt(item.getText(3), -1);
-      input.getPrecision()[i] = Const.toInt(item.getText(4), -1);
+
+    input.getResultFields().clear();
+    for (TableItem item : wFields.getNonEmptyItems()) {
+      RowsFromResultMeta.ResultRowField field = new 
RowsFromResultMeta.ResultRowField();
+      field.setName(item.getText(1));
+      field.setHopType(ValueMetaFactory.getIdForValueMeta(item.getText(2)));
+      field.setLength(Const.toInt(item.getText(3), -1));
+      field.setPrecision(Const.toInt(item.getText(4), -1));
+      input.getResultFields().add(field);
     }
     dispose();
   }
diff --git 
a/plugins/transforms/rowsfromresult/src/main/java/org/apache/hop/pipeline/transforms/rowsfromresult/RowsFromResultMeta.java
 
b/plugins/transforms/rowsfromresult/src/main/java/org/apache/hop/pipeline/transforms/rowsfromresult/RowsFromResultMeta.java
index 6b9fc139b5..10d2eff76e 100644
--- 
a/plugins/transforms/rowsfromresult/src/main/java/org/apache/hop/pipeline/transforms/rowsfromresult/RowsFromResultMeta.java
+++ 
b/plugins/transforms/rowsfromresult/src/main/java/org/apache/hop/pipeline/transforms/rowsfromresult/RowsFromResultMeta.java
@@ -17,25 +17,26 @@
 
 package org.apache.hop.pipeline.transforms.rowsfromresult;
 
+import java.util.ArrayList;
 import java.util.List;
+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.HopPluginException;
 import org.apache.hop.core.exception.HopTransformException;
-import org.apache.hop.core.exception.HopXmlException;
 import org.apache.hop.core.row.IRowMeta;
 import org.apache.hop.core.row.IValueMeta;
+import org.apache.hop.core.row.value.ValueMetaBase;
 import org.apache.hop.core.row.value.ValueMetaFactory;
 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;
 import org.apache.hop.pipeline.transform.TransformMeta;
-import org.w3c.dom.Node;
 
 @Transform(
     id = "RowsFromResult",
@@ -45,137 +46,72 @@ import org.w3c.dom.Node;
     categoryDescription = 
"i18n:org.apache.hop.pipeline.transform:BaseTransform.Category.Workflow",
     keywords = "i18n::RowsFromResultMeta.keyword",
     documentationUrl = "/pipeline/transforms/getrowsfromresult.html")
+@Getter
+@Setter
 public class RowsFromResultMeta extends BaseTransformMeta<RowsFromResult, 
RowsFromResultData> {
   private static final Class<?> PKG = RowsFromResult.class;
-  public static final String CONST_SPACES = "        ";
 
-  private String[] fieldname;
-  private int[] type;
-  private int[] length;
-  private int[] precision;
-
-  /**
-   * @return Returns the length.
-   */
-  public int[] getLength() {
-    return length;
-  }
-
-  /**
-   * @param length The length to set.
-   */
-  public void setLength(int[] length) {
-    this.length = length;
-  }
-
-  /**
-   * @return Returns the name.
-   */
-  public String[] getFieldname() {
-    return fieldname;
-  }
-
-  /**
-   * @param name The name to set.
-   */
-  public void setFieldname(String[] name) {
-    this.fieldname = name;
-  }
-
-  /**
-   * @return Returns the precision.
-   */
-  public int[] getPrecision() {
-    return precision;
-  }
-
-  /**
-   * @param precision The precision to set.
-   */
-  public void setPrecision(int[] precision) {
-    this.precision = precision;
-  }
-
-  /**
-   * @return Returns the type.
-   */
-  public int[] getType() {
-    return type;
+  @Getter
+  @Setter
+  public static class ResultRowField {
+    @HopMetadataProperty(
+        key = "name",
+        injectionKey = "FIELD_NAME",
+        injectionKeyDescription = "RowsFromResultMeta.Injection.FIELD_NAME")
+    private String name;
+
+    @HopMetadataProperty(
+        key = "type",
+        intCodeConverter = ValueMetaBase.ValueTypeCodeConverter.class,
+        injectionKey = "FIELD_TYPE",
+        injectionKeyDescription = "RowsFromResultMeta.Injection.FIELD_TYPE")
+    private int hopType;
+
+    @HopMetadataProperty(
+        key = "length",
+        injectionKey = "FIELD_LENGTH",
+        injectionKeyDescription = "RowsFromResultMeta.Injection.FIELD_LENGTH")
+    private int length;
+
+    @HopMetadataProperty(
+        key = "precision",
+        injectionKey = "FIELD_PRECISION",
+        injectionKeyDescription = 
"RowsFromResultMeta.Injection.FIELD_PRECISION")
+    private int precision;
+
+    public ResultRowField() {}
+
+    public ResultRowField(ResultRowField f) {
+      this();
+      this.name = f.name;
+      this.hopType = f.hopType;
+      this.length = f.length;
+      this.precision = f.precision;
+    }
   }
 
-  /**
-   * @param type The type to set.
-   */
-  public void setType(int[] type) {
-    this.type = type;
-  }
+  @HopMetadataProperty(
+      key = "field",
+      groupKey = "fields",
+      injectionKey = "FIELD",
+      injectionGroupKey = "FIELDS",
+      injectionKeyDescription = "RowsFromResultMeta.Injection.FIELD",
+      injectionGroupDescription = "RowsFromResultMeta.Injection.FIELDS")
+  private List<ResultRowField> resultFields;
 
   public RowsFromResultMeta() {
-    super(); // allocate BaseTransformMeta
+    super();
+    this.resultFields = new ArrayList<>();
   }
 
-  @Override
-  public void loadXml(Node transformNode, IHopMetadataProvider 
metadataProvider)
-      throws HopXmlException {
-    readData(transformNode);
+  public RowsFromResultMeta(RowsFromResultMeta m) {
+    this();
+    m.resultFields.forEach(field -> this.resultFields.add(new 
ResultRowField(field)));
   }
 
   @Override
   public Object clone() {
-    RowsFromResultMeta retval = (RowsFromResultMeta) super.clone();
-    int nrFields = fieldname.length;
-    retval.allocate(nrFields);
-    System.arraycopy(fieldname, 0, retval.fieldname, 0, nrFields);
-    System.arraycopy(type, 0, retval.type, 0, nrFields);
-    System.arraycopy(length, 0, retval.length, 0, nrFields);
-    System.arraycopy(precision, 0, retval.precision, 0, nrFields);
-    return retval;
-  }
-
-  public void allocate(int nrFields) {
-    fieldname = new String[nrFields];
-    type = new int[nrFields];
-    length = new int[nrFields];
-    precision = new int[nrFields];
-  }
-
-  @Override
-  public String getXml() {
-    StringBuilder retval = new StringBuilder();
-    retval.append("    <fields>");
-    for (int i = 0; i < fieldname.length; i++) {
-      retval.append("      <field>");
-      retval.append(CONST_SPACES + XmlHandler.addTagValue("name", 
fieldname[i]));
-      retval.append(
-          CONST_SPACES
-              + XmlHandler.addTagValue("type", 
ValueMetaFactory.getValueMetaName(type[i])));
-      retval.append(CONST_SPACES + XmlHandler.addTagValue("length", 
length[i]));
-      retval.append(CONST_SPACES + XmlHandler.addTagValue("precision", 
precision[i]));
-      retval.append("        </field>");
-    }
-    retval.append("      </fields>");
-
-    return retval.toString();
-  }
-
-  private void readData(Node transformNode) {
-    Node fields = XmlHandler.getSubNode(transformNode, "fields");
-    int nrFields = XmlHandler.countNodes(fields, "field");
-
-    allocate(nrFields);
-
-    for (int i = 0; i < nrFields; i++) {
-      Node line = XmlHandler.getSubNodeByNr(fields, "field", i);
-      fieldname[i] = XmlHandler.getTagValue(line, "name");
-      type[i] = 
ValueMetaFactory.getIdForValueMeta(XmlHandler.getTagValue(line, "type"));
-      length[i] = Const.toInt(XmlHandler.getTagValue(line, "length"), -2);
-      precision[i] = Const.toInt(XmlHandler.getTagValue(line, "precision"), 
-2);
-    }
-  }
-
-  @Override
-  public void setDefault() {
-    allocate(0);
+    return new RowsFromResultMeta(this);
   }
 
   @Override
@@ -187,10 +123,12 @@ public class RowsFromResultMeta extends 
BaseTransformMeta<RowsFromResult, RowsFr
       IVariables variables,
       IHopMetadataProvider metadataProvider)
       throws HopTransformException {
-    for (int i = 0; i < this.fieldname.length; i++) {
+    for (ResultRowField field : resultFields) {
       IValueMeta v;
       try {
-        v = ValueMetaFactory.createValueMeta(fieldname[i], type[i], length[i], 
precision[i]);
+        v =
+            ValueMetaFactory.createValueMeta(
+                field.getName(), field.getHopType(), field.getLength(), 
field.getPrecision());
         v.setOrigin(origin);
         r.addValueMeta(v);
       } catch (HopPluginException e) {
diff --git 
a/plugins/transforms/rowsfromresult/src/main/resources/org/apache/hop/pipeline/transforms/rowsfromresult/messages/messages_en_US.properties
 
b/plugins/transforms/rowsfromresult/src/main/resources/org/apache/hop/pipeline/transforms/rowsfromresult/messages/messages_en_US.properties
index 6db3c64073..35e11e5d67 100644
--- 
a/plugins/transforms/rowsfromresult/src/main/resources/org/apache/hop/pipeline/transforms/rowsfromresult/messages/messages_en_US.properties
+++ 
b/plugins/transforms/rowsfromresult/src/main/resources/org/apache/hop/pipeline/transforms/rowsfromresult/messages/messages_en_US.properties
@@ -28,3 +28,9 @@ RowsFromResultDialog.TransformName.Label=Transform name
 RowsFromResultMeta.CheckResult.NoInputReceivedError=No input received from 
other transforms.
 
RowsFromResultMeta.CheckResult.TransformExpectingNoReadingInfoFromOtherTransforms=This
 transform is not expecting nor reading info from other transforms.
 RowsFromResultMeta.keyword=row,result
+RowsFromResultMeta.Injection.FIELD_NAME=Field name
+RowsFromResultMeta.Injection.FIELD_TYPE=Field type
+RowsFromResultMeta.Injection.FIELD_LENGTH=Field length
+RowsFromResultMeta.Injection.FIELD_PRECISION=Field precision
+RowsFromResultMeta.Injection.FIELD=Result row field
+RowsFromResultMeta.Injection.FIELDS=Result row fields
diff --git 
a/plugins/transforms/rowsfromresult/src/test/java/org/apache/hop/pipeline/transforms/rowsfromresult/RowsFromResultMetaTest.java
 
b/plugins/transforms/rowsfromresult/src/test/java/org/apache/hop/pipeline/transforms/rowsfromresult/RowsFromResultMetaTest.java
index 7b9c528746..c8a3257c3d 100644
--- 
a/plugins/transforms/rowsfromresult/src/test/java/org/apache/hop/pipeline/transforms/rowsfromresult/RowsFromResultMetaTest.java
+++ 
b/plugins/transforms/rowsfromresult/src/test/java/org/apache/hop/pipeline/transforms/rowsfromresult/RowsFromResultMetaTest.java
@@ -16,77 +16,95 @@
  */
 package org.apache.hop.pipeline.transforms.rowsfromresult;
 
-import java.util.Arrays;
-import java.util.HashMap;
-import java.util.List;
-import java.util.Map;
-import org.apache.hop.core.HopEnvironment;
-import org.apache.hop.core.exception.HopException;
+import static org.junit.jupiter.api.Assertions.assertEquals;
+import static org.junit.jupiter.api.Assertions.assertNotNull;
+
+import java.nio.file.Files;
+import java.nio.file.Path;
+import java.nio.file.Paths;
+import java.util.Objects;
 import org.apache.hop.core.plugins.PluginRegistry;
-import org.apache.hop.junit.rules.RestoreHopEngineEnvironmentExtension;
-import org.apache.hop.pipeline.transform.ITransformMeta;
-import org.apache.hop.pipeline.transforms.loadsave.LoadSaveTester;
-import org.apache.hop.pipeline.transforms.loadsave.initializer.IInitializer;
-import 
org.apache.hop.pipeline.transforms.loadsave.validator.ArrayLoadSaveValidator;
-import 
org.apache.hop.pipeline.transforms.loadsave.validator.IFieldLoadSaveValidator;
-import 
org.apache.hop.pipeline.transforms.loadsave.validator.IntLoadSaveValidator;
-import 
org.apache.hop.pipeline.transforms.loadsave.validator.PrimitiveIntArrayLoadSaveValidator;
-import 
org.apache.hop.pipeline.transforms.loadsave.validator.StringLoadSaveValidator;
+import org.apache.hop.core.row.IValueMeta;
+import org.apache.hop.core.row.value.ValueMetaDate;
+import org.apache.hop.core.row.value.ValueMetaInteger;
+import org.apache.hop.core.row.value.ValueMetaNumber;
+import org.apache.hop.core.row.value.ValueMetaPlugin;
+import org.apache.hop.core.row.value.ValueMetaPluginType;
+import org.apache.hop.core.row.value.ValueMetaString;
+import org.apache.hop.core.xml.XmlHandler;
+import org.apache.hop.metadata.serializer.memory.MemoryMetadataProvider;
+import org.apache.hop.metadata.serializer.xml.XmlMetadataUtil;
+import org.apache.hop.pipeline.transform.TransformMeta;
 import org.junit.jupiter.api.BeforeEach;
 import org.junit.jupiter.api.Test;
-import org.junit.jupiter.api.extension.RegisterExtension;
-
-class RowsFromResultMetaTest implements IInitializer<ITransformMeta> {
-  LoadSaveTester loadSaveTester;
-  Class<RowsFromResultMeta> testMetaClass = RowsFromResultMeta.class;
-
-  @RegisterExtension
-  static RestoreHopEngineEnvironmentExtension env = new 
RestoreHopEngineEnvironmentExtension();
 
+class RowsFromResultMetaTest {
   @BeforeEach
-  void setUpLoadSave() throws Exception {
-    HopEnvironment.init();
-    PluginRegistry.init();
-    List<String> attributes = Arrays.asList("fieldname", "type", "length", 
"precision");
+  void beforeEach() throws Exception {
+    PluginRegistry registry = PluginRegistry.getInstance();
+    String[] classNames = {
+      ValueMetaString.class.getName(), ValueMetaInteger.class.getName(),
+      ValueMetaDate.class.getName(), ValueMetaNumber.class.getName()
+    };
+    for (String className : classNames) {
+      registry.registerPluginClass(className, ValueMetaPluginType.class, 
ValueMetaPlugin.class);
+    }
+  }
+
+  @Test
+  void testLoadSave() throws Exception {
+    Path path = 
Paths.get(Objects.requireNonNull(getClass().getResource("/transform.xml")).toURI());
+    String xml = Files.readString(path);
+    RowsFromResultMeta meta = new RowsFromResultMeta();
+    XmlMetadataUtil.deSerializeFromXml(
+        XmlHandler.loadXmlString(xml, TransformMeta.XML_TAG),
+        RowsFromResultMeta.class,
+        meta,
+        new MemoryMetadataProvider());
 
-    Map<String, String> getterMap = new HashMap<>();
-    Map<String, String> setterMap = new HashMap<>();
+    validate(meta);
 
-    IFieldLoadSaveValidator<String[]> stringArrayLoadSaveValidator =
-        new ArrayLoadSaveValidator<>(new StringLoadSaveValidator(), 5);
+    // Do a round trip:
+    //
+    String xmlCopy =
+        XmlHandler.openTag(TransformMeta.XML_TAG)
+            + XmlMetadataUtil.serializeObjectToXml(meta)
+            + XmlHandler.closeTag(TransformMeta.XML_TAG);
+    RowsFromResultMeta metaCopy = new RowsFromResultMeta();
+    XmlMetadataUtil.deSerializeFromXml(
+        XmlHandler.loadXmlString(xmlCopy, TransformMeta.XML_TAG),
+        RowsFromResultMeta.class,
+        metaCopy,
+        new MemoryMetadataProvider());
+    validate(metaCopy);
+  }
 
-    Map<String, IFieldLoadSaveValidator<?>> attrValidatorMap = new HashMap<>();
-    attrValidatorMap.put("fieldname", stringArrayLoadSaveValidator);
-    attrValidatorMap.put(
-        "type", new PrimitiveIntArrayLoadSaveValidator(new 
IntLoadSaveValidator(7), 5));
-    attrValidatorMap.put(
-        "length", new PrimitiveIntArrayLoadSaveValidator(new 
IntLoadSaveValidator(100), 5));
-    attrValidatorMap.put(
-        "precision", new PrimitiveIntArrayLoadSaveValidator(new 
IntLoadSaveValidator(9), 5));
+  private static void validate(RowsFromResultMeta meta) {
+    assertNotNull(meta.getResultFields());
+    assertEquals(4, meta.getResultFields().size());
 
-    Map<String, IFieldLoadSaveValidator<?>> typeValidatorMap = new HashMap<>();
+    RowsFromResultMeta.ResultRowField f = meta.getResultFields().get(0);
+    assertEquals("field1", f.getName());
+    assertEquals(IValueMeta.TYPE_STRING, f.getHopType());
+    assertEquals(100, f.getLength());
+    assertEquals(-1, f.getPrecision());
 
-    loadSaveTester =
-        new LoadSaveTester(
-            testMetaClass,
-            attributes,
-            getterMap,
-            setterMap,
-            attrValidatorMap,
-            typeValidatorMap,
-            this);
-  }
+    f = meta.getResultFields().get(1);
+    assertEquals("field2", f.getName());
+    assertEquals(IValueMeta.TYPE_DATE, f.getHopType());
+    assertEquals(-1, f.getLength());
+    assertEquals(-1, f.getPrecision());
 
-  // Call the allocate method on the LoadSaveTester meta class
-  @Override
-  public void modify(ITransformMeta someMeta) {
-    if (someMeta instanceof RowsFromResultMeta) {
-      ((RowsFromResultMeta) someMeta).allocate(5);
-    }
-  }
+    f = meta.getResultFields().get(2);
+    assertEquals("field3", f.getName());
+    assertEquals(IValueMeta.TYPE_INTEGER, f.getHopType());
+    assertEquals(7, f.getLength());
+    assertEquals(-1, f.getPrecision());
 
-  @Test
-  void testSerialization() throws HopException {
-    loadSaveTester.testSerialization();
+    f = meta.getResultFields().get(3);
+    assertEquals("field4", f.getName());
+    assertEquals(IValueMeta.TYPE_NUMBER, f.getHopType());
+    assertEquals(9, f.getLength());
+    assertEquals(2, f.getPrecision());
   }
 }
diff --git a/plugins/transforms/rowsfromresult/src/test/resources/transform.xml 
b/plugins/transforms/rowsfromresult/src/test/resources/transform.xml
new file mode 100644
index 0000000000..7a79ddec53
--- /dev/null
+++ b/plugins/transforms/rowsfromresult/src/test/resources/transform.xml
@@ -0,0 +1,46 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+  ~ Licensed to the Apache Software Foundation (ASF) under one or more
+  ~ contributor license agreements.  See the NOTICE file distributed with
+  ~ this work for additional information regarding copyright ownership.
+  ~ The ASF licenses this file to You under the Apache License, Version 2.0
+  ~ (the "License"); you may not use this file except in compliance with
+  ~ the License.  You may obtain a copy of the License at
+  ~
+  ~       http://www.apache.org/licenses/LICENSE-2.0
+  ~
+  ~ Unless required by applicable law or agreed to in writing, software
+  ~ distributed under the License is distributed on an "AS IS" BASIS,
+  ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+  ~ See the License for the specific language governing permissions and
+  ~ limitations under the License.
+  -->
+
+<transform>
+    <fields>
+        <field>
+            <name>field1</name>
+            <type>String</type>
+            <length>100</length>
+            <precision>-1</precision>
+        </field>
+        <field>
+            <name>field2</name>
+            <type>Date</type>
+            <length>-1</length>
+            <precision>-1</precision>
+        </field>
+        <field>
+            <name>field3</name>
+            <type>Integer</type>
+            <length>7</length>
+            <precision>-1</precision>
+        </field>
+        <field>
+            <name>field4</name>
+            <type>Number</type>
+            <length>9</length>
+            <precision>2</precision>
+        </field>
+    </fields>
+</transform>

Reply via email to