This is an automated email from the ASF dual-hosted git repository.
mcasters 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 9b6313f390 IT and 2.17 compatibility fixes (#6909)
9b6313f390 is described below
commit 9b6313f390142245ffc9f538f328090cbe43943e
Author: Matt Casters <[email protected]>
AuthorDate: Tue Mar 31 15:17:29 2026 +0200
IT and 2.17 compatibility fixes (#6909)
* Issue #6884 (2.17 compatibility fixes)
* Issue #6884 (2.17 mongo collection tag fix)
* Issue #6884 (script fix)
* IT fixes
extra null checks
* Issue #6884 (spotless)
---------
Co-authored-by: Hans Van Akelyen <[email protected]>
---
.../hop/metadata/inject/HopMetadataInjector.java | 6 +
.../metadata/serializer/xml/XmlMetadataUtil.java | 3 +
.../metadata/inject/HopMetadataInjectorTest.java | 48 +++++
.../serializer/xml/XmlMetadataUtilTest.java | 22 +++
.../java/org/apache/hop/pipeline/PipelineMeta.java | 4 +-
.../hop_server/0005-verify-executions-logged.hpl | 208 ++++++++++-----------
.../0008-email-messages-connection-golden.csv | 2 +-
.../0009-getConnectionValues.hpl | 2 +-
.../parameters_and_variables/run-all.hwf | 158 ++++++----------
.../transforms/memgroupby/MemoryGroupByMeta.java | 4 +-
.../apache/hop/mongo/wrapper/field/MongoField.java | 2 +-
.../mongodboutput/MongoDbOutputMeta.java | 24 +--
.../apache/hop/mongo/wrapper/MongoFieldTest.java | 8 +
.../MongoDbDeleteMetaInjectionTest.java | 57 ++++++
.../mongodbdelete/MongoDbDeleteMetaTest.java | 85 +++++++++
.../transforms/multimerge/MultiMergeJoinMeta.java | 44 +----
.../mysqlbulkloader/MySqlBulkLoaderMeta.java | 45 ++---
.../pipelineexecutor/PipelineExecutorMeta.java | 39 ++--
.../hop/pipeline/transforms/script/Script.java | 9 +-
.../hop/pipeline/transforms/script/ScriptData.java | 1 +
.../sqlfileoutput/SQLFileOutputMeta.java | 25 +--
.../workflowexecutor/WorkflowExecutorMeta.java | 39 ++--
.../transforms/writetolog/WriteToLogMeta.java | 22 +--
.../perspective/explorer/ExplorerPerspective.java | 21 ++-
24 files changed, 497 insertions(+), 381 deletions(-)
diff --git
a/core/src/main/java/org/apache/hop/metadata/inject/HopMetadataInjector.java
b/core/src/main/java/org/apache/hop/metadata/inject/HopMetadataInjector.java
index b29c0134ff..c20ca7952a 100644
--- a/core/src/main/java/org/apache/hop/metadata/inject/HopMetadataInjector.java
+++ b/core/src/main/java/org/apache/hop/metadata/inject/HopMetadataInjector.java
@@ -37,6 +37,7 @@ import org.apache.hop.core.row.IValueMeta;
import org.apache.hop.core.row.RowBuffer;
import org.apache.hop.metadata.api.HopMetadataProperty;
import org.apache.hop.metadata.api.IEnumHasCode;
+import org.apache.hop.metadata.api.IEnumHasCodeAndDescription;
import org.apache.hop.metadata.api.IHopMetadata;
import org.apache.hop.metadata.api.IHopMetadataProvider;
import org.apache.hop.metadata.api.IHopMetadataSerializer;
@@ -474,6 +475,11 @@ public class HopMetadataInjector {
final Class<? extends IEnumHasCode> enumerationClass =
(Class<? extends IEnumHasCode>) field.getType();
fieldValue = IEnumHasCode.lookupCode(enumerationClass, code, null);
+ if (fieldValue == null &&
IEnumHasCodeAndDescription.class.isAssignableFrom(enumerationClass)) {
+ fieldValue =
+ IEnumHasCodeAndDescription.lookupDescription(
+ (Class<? extends IEnumHasCodeAndDescription>) enumerationClass,
code, null);
+ }
if (fieldValue == null) {
// For backward compatibility, retry with the name as well
//
diff --git
a/core/src/main/java/org/apache/hop/metadata/serializer/xml/XmlMetadataUtil.java
b/core/src/main/java/org/apache/hop/metadata/serializer/xml/XmlMetadataUtil.java
index 9c76c2039a..e857234f0f 100644
---
a/core/src/main/java/org/apache/hop/metadata/serializer/xml/XmlMetadataUtil.java
+++
b/core/src/main/java/org/apache/hop/metadata/serializer/xml/XmlMetadataUtil.java
@@ -723,6 +723,9 @@ public class XmlMetadataUtil {
// What is the name of the object to reference?
//
String name = XmlHandler.getTagValue(node, tag);
+ if (StringUtils.isEmpty(name)) {
+ return null;
+ }
// We need the list to look up the name with.
//
diff --git
a/core/src/test/java/org/apache/hop/metadata/inject/HopMetadataInjectorTest.java
b/core/src/test/java/org/apache/hop/metadata/inject/HopMetadataInjectorTest.java
index 8d95945e55..704f3d2820 100644
---
a/core/src/test/java/org/apache/hop/metadata/inject/HopMetadataInjectorTest.java
+++
b/core/src/test/java/org/apache/hop/metadata/inject/HopMetadataInjectorTest.java
@@ -42,6 +42,8 @@ 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.metadata.api.HopMetadataProperty;
+import org.apache.hop.metadata.api.IEnumHasCodeAndDescription;
import org.apache.hop.metadata.inject.company.Company;
import org.apache.hop.metadata.inject.company.Employee;
import org.apache.hop.metadata.inject.sample.Field;
@@ -222,4 +224,50 @@ class HopMetadataInjectorTest {
assertTrue(moreFields.contains("FIELD_PRECISION"));
assertTrue(moreFields.contains("FIELD_TRIM_TYPE"));
}
+
+ @Test
+ void testStoreWithCodeEnumInjectionWithDescription() throws Exception {
+ Map<String, Object> injectionKeyMap = new HashMap<>();
+ injectionKeyMap.put("TYPE", "Number of Distinct Values (N)");
+
+ DescriptionEnumMeta meta = new DescriptionEnumMeta();
+ HopMetadataInjector.inject(new MemoryMetadataProvider(), meta,
injectionKeyMap, Map.of());
+
+ assertEquals(DescriptionEnum.COUNT_DISTINCT, meta.getType());
+ }
+
+ private static class DescriptionEnumMeta {
+ @HopMetadataProperty(injectionKey = "TYPE", storeWithCode = true)
+ private DescriptionEnum type;
+
+ public DescriptionEnum getType() {
+ return type;
+ }
+
+ public void setType(DescriptionEnum type) {
+ this.type = type;
+ }
+ }
+
+ private enum DescriptionEnum implements IEnumHasCodeAndDescription {
+ COUNT_DISTINCT("COUNT_DISTINCT", "Number of Distinct Values (N)");
+
+ private final String code;
+ private final String description;
+
+ DescriptionEnum(String code, String description) {
+ this.code = code;
+ this.description = description;
+ }
+
+ @Override
+ public String getCode() {
+ return code;
+ }
+
+ @Override
+ public String getDescription() {
+ return description;
+ }
+ }
}
diff --git
a/core/src/test/java/org/apache/hop/metadata/serializer/xml/XmlMetadataUtilTest.java
b/core/src/test/java/org/apache/hop/metadata/serializer/xml/XmlMetadataUtilTest.java
index 2d5870d0b7..796c681f21 100644
---
a/core/src/test/java/org/apache/hop/metadata/serializer/xml/XmlMetadataUtilTest.java
+++
b/core/src/test/java/org/apache/hop/metadata/serializer/xml/XmlMetadataUtilTest.java
@@ -213,4 +213,26 @@ class XmlMetadataUtilTest {
assertEquals(withCopy.getSteps().size(), listRef.getSteps().size());
assertEquals(withCopy.getHops().size(), listRef.getHops().size());
}
+
+ @Test
+ void testListReferenceSerializationWithEmptyReference() throws Exception {
+ String xml =
+ """
+ <steps>
+
<step><name>S1</name><description>Description1</description><enabled>Y</enabled></step>
+ </steps>
+ <order>
+ <hop><from>S1</from><to/></hop>
+ </order>
+ """;
+ Node node = XmlHandler.loadXmlString("<hop>" + xml + "</hop>", "hop");
+ WithListReference withCopy =
+ XmlMetadataUtil.deSerializeFromXml(
+ node, WithListReference.class, new MemoryMetadataProvider());
+
+ assertEquals(1, withCopy.getSteps().size());
+ assertEquals(1, withCopy.getHops().size());
+ assertEquals("S1", withCopy.getHops().get(0).getFrom().getName());
+ assertNull(withCopy.getHops().get(0).getTo());
+ }
}
diff --git a/engine/src/main/java/org/apache/hop/pipeline/PipelineMeta.java
b/engine/src/main/java/org/apache/hop/pipeline/PipelineMeta.java
index 6f0248edbc..3fb03561a7 100644
--- a/engine/src/main/java/org/apache/hop/pipeline/PipelineMeta.java
+++ b/engine/src/main/java/org/apache/hop/pipeline/PipelineMeta.java
@@ -70,6 +70,7 @@ import org.apache.hop.core.util.Utils;
import org.apache.hop.core.variables.IVariables;
import org.apache.hop.core.vfs.HopVfs;
import org.apache.hop.core.xml.IXml;
+import org.apache.hop.core.xml.XmlFormatter;
import org.apache.hop.core.xml.XmlHandler;
import org.apache.hop.i18n.BaseMessages;
import org.apache.hop.metadata.api.HopMetadataProperty;
@@ -1442,7 +1443,8 @@ public class PipelineMeta extends AbstractMeta
@Override
public String getXml(IVariables variables) throws HopException {
return XmlHandler.getLicenseHeader(variables)
- + XmlHandler.aroundTag(XML_TAG,
XmlMetadataUtil.serializeObjectToXml(this));
+ + XmlFormatter.format(
+ XmlHandler.aroundTag(XML_TAG,
XmlMetadataUtil.serializeObjectToXml(this)));
}
/**
diff --git a/integration-tests/hop_server/0005-verify-executions-logged.hpl
b/integration-tests/hop_server/0005-verify-executions-logged.hpl
index 01a62f871a..709d106bb0 100644
--- a/integration-tests/hop_server/0005-verify-executions-logged.hpl
+++ b/integration-tests/hop_server/0005-verify-executions-logged.hpl
@@ -20,171 +20,159 @@ limitations under the License.
<pipeline>
<info>
<name>0005-verify-executions-logged</name>
- <name_sync_with_filename>Y</name_sync_with_filename>
- <description/>
- <extended_description/>
- <pipeline_version/>
- <pipeline_type>Normal</pipeline_type>
- <parameters>
- </parameters>
- <capture_transform_performance>N</capture_transform_performance>
-
<transform_performance_capturing_delay>1000</transform_performance_capturing_delay>
-
<transform_performance_capturing_size_limit>100</transform_performance_capturing_size_limit>
+ <modified_date>2023/02/17 13:40:27.812</modified_date>
<created_user>-</created_user>
<created_date>2023/02/17 13:40:27.812</created_date>
+
<transform_performance_capturing_size_limit>100</transform_performance_capturing_size_limit>
+ <parameters>
+</parameters>
+ <pipeline_status>0</pipeline_status>
+
<transform_performance_capturing_delay>1000</transform_performance_capturing_delay>
+ <name_sync_with_filename>Y</name_sync_with_filename>
<modified_user>-</modified_user>
- <modified_date>2023/02/17 13:40:27.812</modified_date>
+ <capture_transform_performance>N</capture_transform_performance>
+ <pipeline_type>Normal</pipeline_type>
</info>
- <notepads>
- </notepads>
- <order>
- <hop>
- <from>list /tmp/executions</from>
- <to>count</to>
- <enabled>Y</enabled>
- </hop>
- <hop>
- <from>count</from>
- <to>count==0?</to>
- <enabled>Y</enabled>
- </hop>
- <hop>
- <from>count==0?</from>
- <to>Nothing logged: abort</to>
- <enabled>Y</enabled>
- </hop>
- </order>
<transform>
- <name>list /tmp/executions</name>
<type>GetFileNames</type>
- <description/>
- <distribute>Y</distribute>
- <custom_distribution/>
+ <attributes>
+</attributes>
+ <GUI>
+ <yloc>96</yloc>
+ <xloc>112</xloc>
+ </GUI>
<copies>1</copies>
- <partitioning>
- <method>none</method>
- <schema_name/>
- </partitioning>
+ <name>list /tmp/executions</name>
+ <distribute>Y</distribute>
<doNotFailIfNoFile>N</doNotFailIfNoFile>
+ <filefield>N</filefield>
<dynamic_include_subfolders>N</dynamic_include_subfolders>
- <exclude_wildcard_Field/>
+ <raiseAnExceptionIfNoFile>N</raiseAnExceptionIfNoFile>
+ <isaddresult>Y</isaddresult>
+ <limit>0</limit>
<file>
- <exclude_filemask/>
<file_required>N</file_required>
- <filemask>.*</filemask>
- <include_subfolders>N</include_subfolders>
<name>${java.io.tmpdir}/executions/</name>
+ <include_subfolders>Y</include_subfolders>
+ <filemask>.*</filemask>
</file>
- <filefield>N</filefield>
- <filename_Field/>
<filter>
<filterfiletype>all_files</filterfiletype>
</filter>
- <isaddresult>Y</isaddresult>
- <limit>0</limit>
- <raiseAnExceptionIfNoFile>N</raiseAnExceptionIfNoFile>
<rownum>N</rownum>
- <rownum_field/>
- <wildcard_Field/>
- <attributes/>
+ <partitioning>
+ <method>none</method>
+ <schema_name/>
+ </partitioning>
+ </transform>
+ <transform>
+ <type>GroupBy</type>
+ <attributes>
+</attributes>
<GUI>
- <xloc>112</xloc>
<yloc>96</yloc>
+ <xloc>288</xloc>
</GUI>
- </transform>
- <transform>
+ <copies>1</copies>
<name>count</name>
- <type>GroupBy</type>
- <description/>
<distribute>Y</distribute>
- <custom_distribution/>
- <copies>1</copies>
- <partitioning>
- <method>none</method>
- <schema_name/>
- </partitioning>
- <add_linenr>N</add_linenr>
- <all_rows>N</all_rows>
+ <give_back_row>Y</give_back_row>
+ <prefix>grp</prefix>
+ <ignore_aggregate>N</ignore_aggregate>
<directory>${java.io.tmpdir}</directory>
+ <group>
+</group>
<fields>
<field>
+ <type>COUNT_ANY</type>
<aggregate>count</aggregate>
<subject>filename</subject>
- <type>COUNT_ANY</type>
- <valuefield/>
</field>
</fields>
- <give_back_row>Y</give_back_row>
- <group>
-</group>
- <ignore_aggregate>N</ignore_aggregate>
- <linenr_fieldname/>
- <prefix>grp</prefix>
- <attributes/>
+ <all_rows>N</all_rows>
+ <add_linenr>N</add_linenr>
+ <partitioning>
+ <method>none</method>
+ <schema_name/>
+ </partitioning>
+ </transform>
+ <transform>
+ <type>FilterRows</type>
+ <attributes>
+</attributes>
<GUI>
- <xloc>288</xloc>
<yloc>96</yloc>
+ <xloc>432</xloc>
</GUI>
- </transform>
- <transform>
+ <copies>1</copies>
<name>count==0?</name>
- <type>FilterRows</type>
- <description/>
<distribute>Y</distribute>
- <custom_distribution/>
- <copies>1</copies>
- <partitioning>
- <method>none</method>
- <schema_name/>
- </partitioning>
+ <send_true_to>Nothing logged: abort</send_true_to>
<compare>
<condition>
+ <leftvalue>count</leftvalue>
+ <operator>-</operator>
+ <negated>N</negated>
<conditions>
</conditions>
<function>=</function>
- <leftvalue>count</leftvalue>
- <negated>N</negated>
- <operator>-</operator>
<value>
- <isnull>N</isnull>
- <length>-1</length>
- <mask>####0;-####0</mask>
<name>constant</name>
- <precision>0</precision>
+ <length>-1</length>
<text>0</text>
+ <isnull>N</isnull>
<type>Integer</type>
+ <mask>####0;-####0</mask>
+ <precision>0</precision>
</value>
</condition>
</compare>
- <send_true_to>Nothing logged: abort</send_true_to>
- <attributes/>
+ <partitioning>
+ <method>none</method>
+ <schema_name/>
+ </partitioning>
+ </transform>
+ <transform>
+ <type>Abort</type>
+ <attributes>
+</attributes>
<GUI>
- <xloc>432</xloc>
<yloc>96</yloc>
+ <xloc>608</xloc>
</GUI>
- </transform>
- <transform>
+ <copies>1</copies>
<name>Nothing logged: abort</name>
- <type>Abort</type>
- <description/>
<distribute>Y</distribute>
- <custom_distribution/>
- <copies>1</copies>
+ <always_log_rows>Y</always_log_rows>
+ <message>No logging was performed on the remote server: no log folders
detected.</message>
+ <abort_option>ABORT_WITH_ERROR</abort_option>
+ <row_threshold>0</row_threshold>
<partitioning>
<method>none</method>
<schema_name/>
</partitioning>
- <abort_option>ABORT_WITH_ERROR</abort_option>
- <always_log_rows>Y</always_log_rows>
- <message>No logging was performed on the remote server: no log folders
detected.</message>
- <row_threshold>0</row_threshold>
- <attributes/>
- <GUI>
- <xloc>608</xloc>
- <yloc>96</yloc>
- </GUI>
</transform>
+ <notepads>
+</notepads>
+ <order>
+ <hop>
+ <to>count</to>
+ <from>list /tmp/executions</from>
+ <enabled>Y</enabled>
+ </hop>
+ <hop>
+ <to>count==0?</to>
+ <from>count</from>
+ <enabled>Y</enabled>
+ </hop>
+ <hop>
+ <to>Nothing logged: abort</to>
+ <from>count==0?</from>
+ <enabled>Y</enabled>
+ </hop>
+ </order>
+ <attributes>
+</attributes>
<transform_error_handling>
- </transform_error_handling>
- <attributes/>
+</transform_error_handling>
</pipeline>
diff --git
a/integration-tests/mail/datasets/0008-email-messages-connection-golden.csv
b/integration-tests/mail/datasets/0008-email-messages-connection-golden.csv
index 4074c518a1..b519d0ee70 100644
--- a/integration-tests/mail/datasets/0008-email-messages-connection-golden.csv
+++ b/integration-tests/mail/datasets/0008-email-messages-connection-golden.csv
@@ -1,2 +1,2 @@
Message number,Subject,Sender,Reply to,Recipients,Description,Folder name,Flag
new,Flag read,Flag flagged,Flag draft,Flag deleted,Attached files count,Mail
Header(Name)
-1,ACTION: Appointment confirmation,"""\""Wile E. Coyote\""""
<[email protected]>","""\""Wile E. Coyote\""""
<[email protected]>",[email protected],,INBOX,Y,Y,N,N,N,0,
+1,ACTION: Appointment confirmation,"""\""Wile E. Coyote\""""
<[email protected]>","""\""Wile E. Coyote\""""
<[email protected]>",[email protected],,INBOX,N,Y,N,N,N,0,
diff --git
a/integration-tests/parameters_and_variables/0009-getConnectionValues.hpl
b/integration-tests/parameters_and_variables/0009-getConnectionValues.hpl
index dc6f1e80fd..e7f78ec5f7 100644
--- a/integration-tests/parameters_and_variables/0009-getConnectionValues.hpl
+++ b/integration-tests/parameters_and_variables/0009-getConnectionValues.hpl
@@ -199,7 +199,7 @@ com (for direct db connection)
</transform>
<transform>
<name>Text file input</name>
- <type>TextFileInput</type>
+ <type>TextFileInput2</type>
<description/>
<distribute>Y</distribute>
<custom_distribution/>
diff --git a/integration-tests/parameters_and_variables/run-all.hwf
b/integration-tests/parameters_and_variables/run-all.hwf
index 9af1eb41be..644e3efac1 100644
--- a/integration-tests/parameters_and_variables/run-all.hwf
+++ b/integration-tests/parameters_and_variables/run-all.hwf
@@ -35,18 +35,16 @@ limitations under the License.
<description/>
<type>SPECIAL</type>
<attributes/>
- <start>Y</start>
- <dummy>N</dummy>
- <repeat>N</repeat>
- <schedulerType>0</schedulerType>
+ <doNotWaitOnFirstExecution>N</doNotWaitOnFirstExecution>
<intervalSeconds>0</intervalSeconds>
+ <schedulerType>0</schedulerType>
<intervalMinutes>60</intervalMinutes>
+ <DayOfMonth>1</DayOfMonth>
<hour>12</hour>
- <minutes>0</minutes>
+ <repeat>N</repeat>
<weekDay>1</weekDay>
- <DayOfMonth>1</DayOfMonth>
+ <minutes>0</minutes>
<parallel>N</parallel>
- <nr>0</nr>
<xloc>80</xloc>
<yloc>80</yloc>
<attributes_hac/>
@@ -56,57 +54,47 @@ limitations under the License.
<description/>
<type>WORKFLOW</type>
<attributes/>
- <run_configuration>local</run_configuration>
-
<filename>${PROJECT_HOME}/main-0001-workflow-set-get-variable.hwf</filename>
- <params_from_previous>N</params_from_previous>
- <exec_per_row>N</exec_per_row>
- <set_logfile>N</set_logfile>
- <logfile/>
- <logext/>
- <add_date>N</add_date>
- <add_time>N</add_time>
- <loglevel>Nothing</loglevel>
- <wait_until_finished>Y</wait_until_finished>
- <follow_abort_remote>N</follow_abort_remote>
- <create_parent_folder>N</create_parent_folder>
- <pass_export>N</pass_export>
- <run_configuration>local</run_configuration>
<parameters>
<pass_all_parameters>Y</pass_all_parameters>
</parameters>
+ <add_date>N</add_date>
+ <params_from_previous>N</params_from_previous>
+ <add_time>N</add_time>
+ <set_logfile>N</set_logfile>
+ <exec_per_row>N</exec_per_row>
+
<filename>${PROJECT_HOME}/main-0001-workflow-set-get-variable.hwf</filename>
<set_append_logfile>N</set_append_logfile>
+ <run_configuration>local</run_configuration>
+ <create_parent_folder>N</create_parent_folder>
+ <loglevel>Nothing</loglevel>
+ <wait_until_finished>Y</wait_until_finished>
<parallel>N</parallel>
- <nr>0</nr>
<xloc>256</xloc>
<yloc>80</yloc>
<attributes_hac/>
</action>
<action>
- <name>main-0002-pipeline-job-executor.hwf</name>
+ <name>main-0002-pipeline-workflow-executor.hwf</name>
<description/>
<type>WORKFLOW</type>
<attributes/>
- <run_configuration>local</run_configuration>
- <filename>${PROJECT_HOME}/main-0002-pipeline-job-executor.hwf</filename>
- <params_from_previous>N</params_from_previous>
- <exec_per_row>N</exec_per_row>
- <set_logfile>N</set_logfile>
- <logfile/>
<logext/>
- <add_date>N</add_date>
- <add_time>N</add_time>
- <loglevel>Nothing</loglevel>
- <wait_until_finished>Y</wait_until_finished>
- <follow_abort_remote>N</follow_abort_remote>
- <create_parent_folder>N</create_parent_folder>
- <pass_export>N</pass_export>
- <run_configuration>local</run_configuration>
<parameters>
<pass_all_parameters>Y</pass_all_parameters>
</parameters>
+ <add_date>N</add_date>
+ <params_from_previous>N</params_from_previous>
+ <logfile/>
+ <add_time>N</add_time>
+ <set_logfile>N</set_logfile>
+ <exec_per_row>N</exec_per_row>
+
<filename>${PROJECT_HOME}/main-0002-pipeline-workflow-executor.hwf</filename>
<set_append_logfile>N</set_append_logfile>
+ <run_configuration>local</run_configuration>
+ <create_parent_folder>N</create_parent_folder>
+ <loglevel>Nothing</loglevel>
+ <wait_until_finished>Y</wait_until_finished>
<parallel>N</parallel>
- <nr>0</nr>
<xloc>528</xloc>
<yloc>80</yloc>
<attributes_hac/>
@@ -116,27 +104,21 @@ limitations under the License.
<description/>
<type>WORKFLOW</type>
<attributes/>
- <run_configuration>local</run_configuration>
-
<filename>${PROJECT_HOME}/main-0003-pipeline-pipeline-executor.hwf</filename>
- <params_from_previous>N</params_from_previous>
- <exec_per_row>N</exec_per_row>
- <set_logfile>N</set_logfile>
- <logfile/>
- <logext/>
- <add_date>N</add_date>
- <add_time>N</add_time>
- <loglevel>Nothing</loglevel>
- <wait_until_finished>Y</wait_until_finished>
- <follow_abort_remote>N</follow_abort_remote>
- <create_parent_folder>N</create_parent_folder>
- <pass_export>N</pass_export>
- <run_configuration>local</run_configuration>
<parameters>
<pass_all_parameters>Y</pass_all_parameters>
</parameters>
+ <add_date>N</add_date>
+ <params_from_previous>N</params_from_previous>
+ <add_time>N</add_time>
+ <set_logfile>N</set_logfile>
+ <exec_per_row>N</exec_per_row>
+
<filename>${PROJECT_HOME}/main-0003-pipeline-pipeline-executor.hwf</filename>
<set_append_logfile>N</set_append_logfile>
+ <run_configuration>local</run_configuration>
+ <create_parent_folder>N</create_parent_folder>
+ <loglevel>Nothing</loglevel>
+ <wait_until_finished>Y</wait_until_finished>
<parallel>N</parallel>
- <nr>0</nr>
<xloc>816</xloc>
<yloc>80</yloc>
<attributes_hac/>
@@ -146,27 +128,21 @@ limitations under the License.
<description/>
<type>WORKFLOW</type>
<attributes/>
- <run_configuration>local</run_configuration>
-
<filename>${PROJECT_HOME}/main-0004-pass-variables-and-parameters.hwf</filename>
- <params_from_previous>N</params_from_previous>
- <exec_per_row>N</exec_per_row>
- <set_logfile>N</set_logfile>
- <logfile/>
- <logext/>
- <add_date>N</add_date>
- <add_time>N</add_time>
- <loglevel>Nothing</loglevel>
- <wait_until_finished>Y</wait_until_finished>
- <follow_abort_remote>N</follow_abort_remote>
- <create_parent_folder>N</create_parent_folder>
- <pass_export>N</pass_export>
- <run_configuration>local</run_configuration>
<parameters>
<pass_all_parameters>Y</pass_all_parameters>
</parameters>
+ <add_date>N</add_date>
+ <params_from_previous>N</params_from_previous>
+ <add_time>N</add_time>
+ <set_logfile>N</set_logfile>
+ <exec_per_row>N</exec_per_row>
+
<filename>${PROJECT_HOME}/main-0004-pass-variables-and-parameters.hwf</filename>
<set_append_logfile>N</set_append_logfile>
+ <run_configuration>local</run_configuration>
+ <create_parent_folder>N</create_parent_folder>
+ <loglevel>Nothing</loglevel>
+ <wait_until_finished>Y</wait_until_finished>
<parallel>N</parallel>
- <nr>0</nr>
<xloc>254</xloc>
<yloc>194</yloc>
<attributes_hac/>
@@ -176,27 +152,21 @@ limitations under the License.
<description/>
<type>WORKFLOW</type>
<attributes/>
- <run_configuration>local</run_configuration>
- <filename>${PROJECT_HOME}/main-0005-mappings.hwf</filename>
- <params_from_previous>N</params_from_previous>
- <exec_per_row>N</exec_per_row>
- <set_logfile>N</set_logfile>
- <logfile/>
- <logext/>
- <add_date>N</add_date>
- <add_time>N</add_time>
- <loglevel>Nothing</loglevel>
- <wait_until_finished>Y</wait_until_finished>
- <follow_abort_remote>N</follow_abort_remote>
- <create_parent_folder>N</create_parent_folder>
- <pass_export>N</pass_export>
- <run_configuration>local</run_configuration>
<parameters>
<pass_all_parameters>Y</pass_all_parameters>
</parameters>
+ <add_date>N</add_date>
+ <params_from_previous>N</params_from_previous>
+ <add_time>N</add_time>
+ <set_logfile>N</set_logfile>
+ <exec_per_row>N</exec_per_row>
+ <filename>${PROJECT_HOME}/main-0005-mappings.hwf</filename>
<set_append_logfile>N</set_append_logfile>
+ <run_configuration>local</run_configuration>
+ <create_parent_folder>N</create_parent_folder>
+ <loglevel>Nothing</loglevel>
+ <wait_until_finished>Y</wait_until_finished>
<parallel>N</parallel>
- <nr>0</nr>
<xloc>528</xloc>
<yloc>192</yloc>
<attributes_hac/>
@@ -206,26 +176,20 @@ limitations under the License.
<hop>
<from>START</from>
<to>main-0001-workflow-set-get-variable.hwf</to>
- <from_nr>0</from_nr>
- <to_nr>0</to_nr>
<enabled>Y</enabled>
<evaluation>Y</evaluation>
<unconditional>Y</unconditional>
</hop>
<hop>
<from>main-0001-workflow-set-get-variable.hwf</from>
- <to>main-0002-pipeline-job-executor.hwf</to>
- <from_nr>0</from_nr>
- <to_nr>0</to_nr>
+ <to>main-0002-pipeline-workflow-executor.hwf</to>
<enabled>Y</enabled>
<evaluation>Y</evaluation>
<unconditional>N</unconditional>
</hop>
<hop>
- <from>main-0002-pipeline-job-executor.hwf</from>
+ <from>main-0002-pipeline-workflow-executor.hwf</from>
<to>main-0003-pipeline-pipeline-executor.hwf</to>
- <from_nr>0</from_nr>
- <to_nr>0</to_nr>
<enabled>Y</enabled>
<evaluation>Y</evaluation>
<unconditional>N</unconditional>
@@ -233,8 +197,6 @@ limitations under the License.
<hop>
<from>main-0003-pipeline-pipeline-executor.hwf</from>
<to>main-0004-pass-variables-and-parameters.hwf</to>
- <from_nr>0</from_nr>
- <to_nr>0</to_nr>
<enabled>Y</enabled>
<evaluation>Y</evaluation>
<unconditional>N</unconditional>
@@ -242,8 +204,6 @@ limitations under the License.
<hop>
<from>main-0004-pass-variables-and-parameters.hwf</from>
<to>main-0005-mappings.hwf</to>
- <from_nr>0</from_nr>
- <to_nr>0</to_nr>
<enabled>Y</enabled>
<evaluation>Y</evaluation>
<unconditional>N</unconditional>
diff --git
a/plugins/transforms/memgroupby/src/main/java/org/apache/hop/pipeline/transforms/memgroupby/MemoryGroupByMeta.java
b/plugins/transforms/memgroupby/src/main/java/org/apache/hop/pipeline/transforms/memgroupby/MemoryGroupByMeta.java
index 88da90aac8..74b7289123 100644
---
a/plugins/transforms/memgroupby/src/main/java/org/apache/hop/pipeline/transforms/memgroupby/MemoryGroupByMeta.java
+++
b/plugins/transforms/memgroupby/src/main/java/org/apache/hop/pipeline/transforms/memgroupby/MemoryGroupByMeta.java
@@ -42,7 +42,7 @@ import org.apache.hop.core.row.value.ValueMetaNone;
import org.apache.hop.core.variables.IVariables;
import org.apache.hop.i18n.BaseMessages;
import org.apache.hop.metadata.api.HopMetadataProperty;
-import org.apache.hop.metadata.api.IEnumHasCode;
+import org.apache.hop.metadata.api.IEnumHasCodeAndDescription;
import org.apache.hop.metadata.api.IHopMetadataProvider;
import org.apache.hop.pipeline.PipelineMeta;
import org.apache.hop.pipeline.transform.BaseTransformMeta;
@@ -323,7 +323,7 @@ public class MemoryGroupByMeta extends
BaseTransformMeta<MemoryGroupBy, MemoryGr
}
@SuppressWarnings("java:S115")
- public enum GroupType implements IEnumHasCode {
+ public enum GroupType implements IEnumHasCodeAndDescription {
None("-", "-"),
Sum("SUM", BaseMessages.getString(PKG,
"MemoryGroupByMeta.TypeGroupLongDesc.SUM")),
Average("AVERAGE", BaseMessages.getString(PKG,
"MemoryGroupByMeta.TypeGroupLongDesc.AVERAGE")),
diff --git
a/plugins/transforms/mongodb/src/main/java/org/apache/hop/mongo/wrapper/field/MongoField.java
b/plugins/transforms/mongodb/src/main/java/org/apache/hop/mongo/wrapper/field/MongoField.java
index 1ee077a39f..68621ded13 100644
---
a/plugins/transforms/mongodb/src/main/java/org/apache/hop/mongo/wrapper/field/MongoField.java
+++
b/plugins/transforms/mongodb/src/main/java/org/apache/hop/mongo/wrapper/field/MongoField.java
@@ -57,7 +57,7 @@ public class MongoField implements Comparable<MongoField> {
/** User-defined indexed values for String types */
@HopMetadataProperty(key = "indexed_vals", injectionKey = "FIELD_INDEXED")
- public List<String> indexedValues;
+ public List<String> indexedValues = new ArrayList<>();
/**
* Temporary variable to hold the min:max array index info for fields
determined when sampling
diff --git
a/plugins/transforms/mongodb/src/main/java/org/apache/hop/pipeline/transforms/mongodboutput/MongoDbOutputMeta.java
b/plugins/transforms/mongodb/src/main/java/org/apache/hop/pipeline/transforms/mongodboutput/MongoDbOutputMeta.java
index a5883edc85..d3196b687b 100644
---
a/plugins/transforms/mongodb/src/main/java/org/apache/hop/pipeline/transforms/mongodboutput/MongoDbOutputMeta.java
+++
b/plugins/transforms/mongodb/src/main/java/org/apache/hop/pipeline/transforms/mongodboutput/MongoDbOutputMeta.java
@@ -24,9 +24,9 @@ import lombok.Getter;
import lombok.Setter;
import org.apache.commons.lang3.StringUtils;
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.HopXmlException;
import org.apache.hop.core.row.IRowMeta;
import org.apache.hop.core.util.Utils;
import org.apache.hop.core.variables.IVariables;
@@ -284,23 +284,6 @@ public class MongoDbOutputMeta extends
MongoDbMeta<MongoDbOutput, MongoDbOutputD
batchInsertSize = "100";
}
- /**
- * Added for backwards compatibility
- *
- * @param transformNode XML Node of the transform
- * @param metadataProvider metadata provider
- * @throws HopXmlException when unable to load from XML
- */
- @Override
- public void loadXml(Node transformNode, IHopMetadataProvider
metadataProvider)
- throws HopXmlException {
- super.loadXml(transformNode, metadataProvider);
- String tempCollection = XmlHandler.getTagValue(transformNode,
"mongo_collection");
- if (!Utils.isEmpty(tempCollection)) {
- setCollection(tempCollection);
- }
- }
-
@Override
public void check(
List<ICheckResult> remarks,
@@ -370,4 +353,9 @@ public class MongoDbOutputMeta extends
MongoDbMeta<MongoDbOutput, MongoDbOutputD
public boolean supportsErrorHandling() {
return true;
}
+
+ @Override
+ public void convertLegacyXml(Node transformNode) {
+ collection = Const.NVL(collection, XmlHandler.getTagValue(transformNode,
"mongo_collection"));
+ }
}
diff --git
a/plugins/transforms/mongodb/src/test/java/org/apache/hop/mongo/wrapper/MongoFieldTest.java
b/plugins/transforms/mongodb/src/test/java/org/apache/hop/mongo/wrapper/MongoFieldTest.java
index e2796cd281..5d64f8d135 100644
---
a/plugins/transforms/mongodb/src/test/java/org/apache/hop/mongo/wrapper/MongoFieldTest.java
+++
b/plugins/transforms/mongodb/src/test/java/org/apache/hop/mongo/wrapper/MongoFieldTest.java
@@ -19,6 +19,7 @@ package org.apache.hop.mongo.wrapper;
import static org.junit.jupiter.api.Assertions.assertEquals;
import static org.junit.jupiter.api.Assertions.assertFalse;
+import static org.junit.jupiter.api.Assertions.assertNotNull;
import static org.junit.jupiter.api.Assertions.assertNull;
import static org.junit.jupiter.api.Assertions.assertTrue;
import static org.junit.jupiter.api.Assertions.fail;
@@ -71,6 +72,13 @@ class MongoFieldTest {
assertEquals("parent.child", mongoField.getPath());
}
+ @Test
+ void testIndexedValuesDefaultInitialized() {
+ MongoField mongoField = new MongoField();
+ assertNotNull(mongoField.indexedValues);
+ assertTrue(mongoField.indexedValues.isEmpty());
+ }
+
// "Number", "String", "Date", "Boolean", "Integer", "BigNumber",
"Serializable",
// "Binary", "Timestamp", "Internet Address"
@Test
diff --git
a/plugins/transforms/mongodb/src/test/java/org/apache/hop/pipeline/transforms/mongodbdelete/MongoDbDeleteMetaInjectionTest.java
b/plugins/transforms/mongodb/src/test/java/org/apache/hop/pipeline/transforms/mongodbdelete/MongoDbDeleteMetaInjectionTest.java
new file mode 100644
index 0000000000..a46790c6d9
--- /dev/null
+++
b/plugins/transforms/mongodb/src/test/java/org/apache/hop/pipeline/transforms/mongodbdelete/MongoDbDeleteMetaInjectionTest.java
@@ -0,0 +1,57 @@
+/*
+ * 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.
+ */
+package org.apache.hop.pipeline.transforms.mongodbdelete;
+
+import org.apache.hop.core.injection.BaseMetadataInjectionTestJunit5;
+import org.apache.hop.core.logging.HopLogStore;
+import org.apache.hop.core.logging.ILogChannelFactory;
+import
org.apache.hop.pipeline.transforms.mongodboutput.MongoDbOutputMetaInjectionTest;
+import org.junit.jupiter.api.AfterEach;
+import org.junit.jupiter.api.BeforeEach;
+import org.junit.jupiter.api.Test;
+
+class MongoDbDeleteMetaInjectionTest extends
BaseMetadataInjectionTestJunit5<MongoDbDeleteMeta> {
+ private ILogChannelFactory oldLogChannelInterfaceFactory;
+
+ @BeforeEach
+ void setup() throws Exception {
+ oldLogChannelInterfaceFactory = HopLogStore.getLogChannelFactory();
+ MongoDbOutputMetaInjectionTest.setHopLogFactoryWithMock();
+ setup(new MongoDbDeleteMeta());
+ }
+
+ @AfterEach
+ void tearDown() {
+ HopLogStore.setLogChannelFactory(oldLogChannelInterfaceFactory);
+ }
+
+ @Test
+ void test() throws Exception {
+ check("CONNECTION", () -> meta.getConnectionName());
+ check("COLLECTION", () -> meta.getCollection());
+ check("RETRIES", () -> meta.nbRetries);
+ check("WRITE_RETRIES", () -> meta.getWriteRetries());
+ check("RETRY_DELAY", () -> meta.getWriteRetryDelay());
+ check("USE_JSON_QUERY", () -> meta.isUseJsonQuery());
+ check("JSON_QUERY", () -> meta.getJsonQuery());
+ check("EXECUTE_FOR_EACH_ROW", () -> meta.isExecuteForEachIncomingRow());
+ check("INCOMING_FIELD_1", () ->
meta.getMongoFields().get(0).incomingField1);
+ check("INCOMING_FIELD_2", () ->
meta.getMongoFields().get(0).incomingField2);
+ check("DOC_PATH", () -> meta.getMongoFields().get(0).mongoDocPath);
+ check("COMPARATOR", () -> meta.getMongoFields().get(0).comparator);
+ }
+}
diff --git
a/plugins/transforms/mongodb/src/test/java/org/apache/hop/pipeline/transforms/mongodbdelete/MongoDbDeleteMetaTest.java
b/plugins/transforms/mongodb/src/test/java/org/apache/hop/pipeline/transforms/mongodbdelete/MongoDbDeleteMetaTest.java
new file mode 100644
index 0000000000..6c8a0053da
--- /dev/null
+++
b/plugins/transforms/mongodb/src/test/java/org/apache/hop/pipeline/transforms/mongodbdelete/MongoDbDeleteMetaTest.java
@@ -0,0 +1,85 @@
+/*
+ * 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.
+ */
+
+package org.apache.hop.pipeline.transforms.mongodbdelete;
+
+import java.util.Arrays;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+import org.apache.hop.core.Const;
+import org.apache.hop.core.encryption.Encr;
+import org.apache.hop.core.encryption.TwoWayPasswordEncoderPluginType;
+import org.apache.hop.core.exception.HopException;
+import org.apache.hop.core.plugins.PluginRegistry;
+import org.apache.hop.core.util.EnvUtil;
+import org.apache.hop.pipeline.transforms.loadsave.LoadSaveTester;
+import
org.apache.hop.pipeline.transforms.loadsave.validator.IFieldLoadSaveValidatorFactory;
+import
org.apache.hop.pipeline.transforms.loadsave.validator.ListLoadSaveValidator;
+import org.apache.hop.pipeline.transforms.loadsave.validator.ObjectValidator;
+import org.junit.jupiter.api.BeforeAll;
+import org.junit.jupiter.api.Test;
+
+class MongoDbDeleteMetaTest {
+
+ @BeforeAll
+ static void beforeClass() throws HopException {
+
PluginRegistry.addPluginType(TwoWayPasswordEncoderPluginType.getInstance());
+ PluginRegistry.init();
+ String passwordEncoderPluginID =
+
Const.NVL(EnvUtil.getSystemProperty(Const.HOP_PASSWORD_ENCODER_PLUGIN), "Hop");
+ Encr.init(passwordEncoderPluginID);
+ }
+
+ @Test
+ void testRoundTrips() throws HopException {
+ Map<String, String> getterMap = new HashMap<>();
+ getterMap.put("execute_for_each_row", "isExecuteForEachIncomingRow");
+ getterMap.put("fields", "getMongoFields");
+
+ Map<String, String> setterMap = new HashMap<>();
+ setterMap.put("execute_for_each_row", "setExecuteForEachIncomingRow");
+ setterMap.put("fields", "setMongoFields");
+
+ LoadSaveTester tester =
+ new LoadSaveTester(
+ MongoDbDeleteMeta.class,
+ Arrays.asList(
+ "collection",
+ "connectionName",
+ "nbRetries",
+ "writeRetries",
+ "writeRetryDelay",
+ "useJsonQuery",
+ "jsonQuery",
+ "executeForEachIncomingRow",
+ "mongoFields"),
+ getterMap,
+ setterMap);
+
+ IFieldLoadSaveValidatorFactory validatorFactory =
tester.getFieldLoadSaveValidatorFactory();
+ validatorFactory.registerValidator(
+ validatorFactory.getName(List.class, MongoDbDeleteField.class),
+ new ListLoadSaveValidator<>(
+ new ObjectValidator<>(
+ validatorFactory,
+ MongoDbDeleteField.class,
+ Arrays.asList("incomingField1", "incomingField2",
"mongoDocPath", "comparator"))));
+
+ tester.testXmlRoundTrip();
+ }
+}
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 a5d9b80c68..d07e686268 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
@@ -28,7 +28,6 @@ import org.apache.hop.core.ICheckResult;
import org.apache.hop.core.annotations.Transform;
import org.apache.hop.core.exception.HopException;
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.util.Utils;
import org.apache.hop.core.variables.IVariables;
@@ -91,42 +90,6 @@ public class MultiMergeJoinMeta extends
BaseTransformMeta<MultiMergeJoin, MultiM
this.inputTransforms = new ArrayList<>();
}
- /**
- * 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);
- }
-
- private void readData(Node transformNode) throws HopXmlException {
- try {
- String numInputStreamsStr = XmlHandler.getTagValue(transformNode,
"number_input");
-
- // Skip if number_input doesn't exist (null or empty)
- if (numInputStreamsStr == null || numInputStreamsStr.trim().isEmpty()) {
- return;
- }
-
- int nInputStreams = Integer.parseInt(numInputStreamsStr);
- for (int i = 0; i < nInputStreams; i++) {
- inputTransforms.add(XmlHandler.getTagValue(transformNode, "transform"
+ i));
- }
- } catch (Exception e) {
- throw new HopXmlException(
- BaseMessages.getString(PKG,
"MultiMergeJoinMeta.Exception.UnableToLoadTransformMeta"), e);
- }
- }
-
@Override
public void setDefault() {
joinType = joinTypes[0];
@@ -354,11 +317,18 @@ public class MultiMergeJoinMeta extends
BaseTransformMeta<MultiMergeJoin, MultiM
@Override
public void convertLegacyXml(Node node) throws HopException {
+ if (node == null) {
+ return;
+ }
+
// Get the number of input transforms
int numberOfInput = Const.toInt(XmlHandler.getTagValue(node,
"number_input"), -1);
if (numberOfInput < 0) {
return;
}
+ if (inputTransforms == null) {
+ inputTransforms = new ArrayList<>();
+ }
inputTransforms.clear();
for (int i = 0; i < numberOfInput; i++) {
String inputTransform = XmlHandler.getTagValue(node, "transform" + i);
diff --git
a/plugins/transforms/mysqlbulkloader/src/main/java/org/apache/hop/pipeline/transforms/mysqlbulkloader/MySqlBulkLoaderMeta.java
b/plugins/transforms/mysqlbulkloader/src/main/java/org/apache/hop/pipeline/transforms/mysqlbulkloader/MySqlBulkLoaderMeta.java
index 81e5bf775d..8e8c80dfcb 100644
---
a/plugins/transforms/mysqlbulkloader/src/main/java/org/apache/hop/pipeline/transforms/mysqlbulkloader/MySqlBulkLoaderMeta.java
+++
b/plugins/transforms/mysqlbulkloader/src/main/java/org/apache/hop/pipeline/transforms/mysqlbulkloader/MySqlBulkLoaderMeta.java
@@ -29,7 +29,6 @@ import org.apache.hop.core.database.Database;
import org.apache.hop.core.database.DatabaseMeta;
import org.apache.hop.core.exception.HopException;
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.RowMeta;
@@ -118,32 +117,28 @@ public class MySqlBulkLoaderMeta extends
BaseTransformMeta<MySqlBulkLoader, MySq
@HopMetadataProperty(key = "bulk_size")
private String bulkSize;
- /**
- * @deprecated Keep for backwards compatibility
- * @param transformNode xml transform node
- * @param metadataProvider metadata provider
- * @throws HopXmlException thrown when unable to read XML
- */
+ /** Added for backwards compatibility with older XML "mapping" blocks. */
@Override
- @Deprecated(since = "2.13")
- public void loadXml(Node transformNode, IHopMetadataProvider
metadataProvider)
- throws HopXmlException {
- super.loadXml(transformNode, metadataProvider);
- try {
- int nrvalues = XmlHandler.countNodes(transformNode, "mapping");
- for (int i = 0; i < nrvalues; i++) {
- Node vnode = XmlHandler.getSubNodeByNr(transformNode, "mapping", i);
- Field field = new Field();
- field.setFieldStream(XmlHandler.getTagValue(vnode, "field_name"));
- field.setFieldTable(XmlHandler.getTagValue(vnode, "stream_name"));
- field.setFieldFormatType(XmlHandler.getTagValue(vnode,
"field_format_ok"));
- fields.add(field);
+ public void convertLegacyXml(Node node) throws HopException {
+ if (node == null) {
+ return;
+ }
+
+ if (fields == null) {
+ fields = new java.util.ArrayList<>();
+ }
+
+ int nrvalues = XmlHandler.countNodes(node, "mapping");
+ for (int i = 0; i < nrvalues; i++) {
+ Node vnode = XmlHandler.getSubNodeByNr(node, "mapping", i);
+ if (vnode == null) {
+ continue;
}
- } catch (Exception e) {
- throw new HopXmlException(
- BaseMessages.getString(
- PKG,
"MySqlBulkLoaderMeta.Exception.UnableToReadTransformInfoFromXML"),
- e);
+ Field field = new Field();
+ field.setFieldStream(XmlHandler.getTagValue(vnode, "field_name"));
+ field.setFieldTable(XmlHandler.getTagValue(vnode, "stream_name"));
+ field.setFieldFormatType(XmlHandler.getTagValue(vnode,
"field_format_ok"));
+ fields.add(field);
}
}
diff --git
a/plugins/transforms/pipelineexecutor/src/main/java/org/apache/hop/pipeline/transforms/pipelineexecutor/PipelineExecutorMeta.java
b/plugins/transforms/pipelineexecutor/src/main/java/org/apache/hop/pipeline/transforms/pipelineexecutor/PipelineExecutorMeta.java
index 904b1df2e0..0cbafd2462 100644
---
a/plugins/transforms/pipelineexecutor/src/main/java/org/apache/hop/pipeline/transforms/pipelineexecutor/PipelineExecutorMeta.java
+++
b/plugins/transforms/pipelineexecutor/src/main/java/org/apache/hop/pipeline/transforms/pipelineexecutor/PipelineExecutorMeta.java
@@ -29,7 +29,6 @@ import org.apache.hop.core.annotations.Transform;
import org.apache.hop.core.exception.HopException;
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.file.IHasFilename;
import org.apache.hop.core.row.IRowMeta;
import org.apache.hop.core.row.IValueMeta;
@@ -235,31 +234,21 @@ public class PipelineExecutorMeta
super(); // allocate BaseTransformMeta
}
- /**
- * @deprecated Added for backwards compatibility for old parameter style
- * @param transformNode Transform node XML
- * @param metadataProvider Metadata provider
- * @throws HopXmlException when unable to parse XML
- */
+ /** Added for backwards compatibility with older parameter style XML. */
@Override
- @Deprecated(since = "2.13")
- public void loadXml(Node transformNode, IHopMetadataProvider
metadataProvider)
- throws HopXmlException {
- super.loadXml(transformNode, metadataProvider);
- try {
- // Load inherit_all_vars
- //
- String value =
- XmlHandler.getTagValue(
- XmlHandler.getSubNode(transformNode, "parameters"),
"inherit_all_vars");
- if (value != null) {
- setInheritingAllVariables("Y".equalsIgnoreCase(value));
- }
- } catch (Exception e) {
- throw new HopXmlException(
- BaseMessages.getString(
- PKG,
"PipelineExecutorMeta.Exception.ErrorLoadingPipelineExecutorDetailsFromXML"),
- e);
+ public void convertLegacyXml(Node node) throws HopException {
+ if (node == null) {
+ return;
+ }
+
+ // Load inherit_all_vars from the old nested location under <parameters>
+ Node parametersNode = XmlHandler.getSubNode(node, "parameters");
+ if (parametersNode == null) {
+ return;
+ }
+ String value = XmlHandler.getTagValue(parametersNode, "inherit_all_vars");
+ if (value != null) {
+ setInheritingAllVariables("Y".equalsIgnoreCase(value));
}
}
diff --git
a/plugins/transforms/script/src/main/java/org/apache/hop/pipeline/transforms/script/Script.java
b/plugins/transforms/script/src/main/java/org/apache/hop/pipeline/transforms/script/Script.java
index 8b42f39581..2c77677149 100644
---
a/plugins/transforms/script/src/main/java/org/apache/hop/pipeline/transforms/script/Script.java
+++
b/plugins/transforms/script/src/main/java/org/apache/hop/pipeline/transforms/script/Script.java
@@ -640,7 +640,11 @@ public class Script extends BaseTransform<ScriptMeta,
ScriptData> implements ITr
@Override
public boolean processRow() throws HopException {
Object[] r = getRow();
- if (r == null && !first) {
+
+ // If this transform receives input, we stop if there are no more rows.
+ // If this transform doesn't receive input we probably want to generate
rows.
+ //
+ if (r == null && (!first || data.hasPreviousTransforms)) {
processEndOfStream();
setOutputDone();
return false;
@@ -698,6 +702,9 @@ public class Script extends BaseTransform<ScriptMeta,
ScriptData> implements ITr
return false;
}
+ TransformMeta[] prevTransforms =
getPipelineMeta().getPrevTransforms(getTransformMeta());
+ data.hasPreviousTransforms = (prevTransforms != null) &&
(prevTransforms.length > 0);
+
// Add init code here.
// Get the actual Scripts from our MetaData
//
diff --git
a/plugins/transforms/script/src/main/java/org/apache/hop/pipeline/transforms/script/ScriptData.java
b/plugins/transforms/script/src/main/java/org/apache/hop/pipeline/transforms/script/ScriptData.java
index 7cdf9007c0..cca9d06fa5 100644
---
a/plugins/transforms/script/src/main/java/org/apache/hop/pipeline/transforms/script/ScriptData.java
+++
b/plugins/transforms/script/src/main/java/org/apache/hop/pipeline/transforms/script/ScriptData.java
@@ -38,6 +38,7 @@ public class ScriptData extends BaseTransformData implements
ITransformData {
public IRowMeta outputRowMeta;
public int[] replaceIndex;
+ public boolean hasPreviousTransforms;
/** */
public ScriptData() {
diff --git
a/plugins/transforms/sqlfileoutput/src/main/java/org/apache/hop/pipeline/transforms/sqlfileoutput/SQLFileOutputMeta.java
b/plugins/transforms/sqlfileoutput/src/main/java/org/apache/hop/pipeline/transforms/sqlfileoutput/SQLFileOutputMeta.java
index 3cabdddcbf..ae6e0fb56c 100644
---
a/plugins/transforms/sqlfileoutput/src/main/java/org/apache/hop/pipeline/transforms/sqlfileoutput/SQLFileOutputMeta.java
+++
b/plugins/transforms/sqlfileoutput/src/main/java/org/apache/hop/pipeline/transforms/sqlfileoutput/SQLFileOutputMeta.java
@@ -34,7 +34,6 @@ import org.apache.hop.core.database.DatabaseMeta;
import org.apache.hop.core.exception.HopDatabaseException;
import org.apache.hop.core.exception.HopException;
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.util.Utils;
@@ -100,23 +99,17 @@ public class SQLFileOutputMeta extends
BaseTransformMeta<SQLFileOutput, SQLFileO
@HopMetadataProperty(key = "StartNewLine")
private boolean startNewLine;
- /**
- * @deprecated keep for backwards compatibility
- * @param transformNode the XML of the transform node
- * @param metadataProvider the metadata provider
- * @throws HopXmlException when unable to parse the XML
- */
+ /** Added for backwards compatibility with older XML using "extention". */
@Override
- @Deprecated(since = "2.13")
- public void loadXml(Node transformNode, IHopMetadataProvider
metadataProvider)
- throws HopXmlException {
- try {
- super.loadXml(transformNode, metadataProvider);
+ public void convertLegacyXml(Node node) throws HopException {
+ if (node == null) {
+ return;
+ }
- // Rename from extention to extension
- file.extension = XmlHandler.getTagValue(transformNode, "file",
"extention");
- } catch (Exception e) {
- throw new HopXmlException("Unable to load transform info from XML", e);
+ // Rename from legacy "extention" to "extension", but don't overwrite
modern XML values.
+ String legacyExtension = XmlHandler.getTagValue(node, "file", "extention");
+ if (file != null && !Utils.isEmpty(legacyExtension)) {
+ file.extension = legacyExtension;
}
}
diff --git
a/plugins/transforms/workflowexecutor/src/main/java/org/apache/hop/pipeline/transforms/workflowexecutor/WorkflowExecutorMeta.java
b/plugins/transforms/workflowexecutor/src/main/java/org/apache/hop/pipeline/transforms/workflowexecutor/WorkflowExecutorMeta.java
index a1f2068307..c3dd047b72 100644
---
a/plugins/transforms/workflowexecutor/src/main/java/org/apache/hop/pipeline/transforms/workflowexecutor/WorkflowExecutorMeta.java
+++
b/plugins/transforms/workflowexecutor/src/main/java/org/apache/hop/pipeline/transforms/workflowexecutor/WorkflowExecutorMeta.java
@@ -31,7 +31,6 @@ import org.apache.hop.core.annotations.Transform;
import org.apache.hop.core.exception.HopException;
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.file.IHasFilename;
import org.apache.hop.core.logging.LogChannel;
import org.apache.hop.core.row.IRowMeta;
@@ -231,33 +230,21 @@ public class WorkflowExecutorMeta
super(); // allocate BaseTransformMeta
}
- /**
- * @deprecated keep for backwards compatibility
- * @param transformNode the XML of the transform node
- * @param metadataProvider the metadata provider
- * @throws HopXmlException when unable to parse the XML
- */
+ /** Added for backwards compatibility with older parameter style XML. */
@Override
- @Deprecated(since = "2.13")
- public void loadXml(Node transformNode, IHopMetadataProvider
metadataProvider)
- throws HopXmlException {
- try {
- super.loadXml(transformNode, metadataProvider);
-
- // Load inherit_all_vars
- //
- String value =
- XmlHandler.getTagValue(
- XmlHandler.getSubNode(transformNode, "parameters"),
"inherit_all_vars");
- if (value != null) {
- setInheritingAllVariables("Y".equalsIgnoreCase(value));
- }
+ public void convertLegacyXml(Node node) throws HopException {
+ if (node == null) {
+ return;
+ }
- } catch (Exception e) {
- throw new HopXmlException(
- BaseMessages.getString(
- PKG,
"WorkflowExecutorMeta.Exception.ErrorLoadingJobExecutorDetailsFromXML"),
- e);
+ // Load inherit_all_vars from the old nested location under <parameters>
+ Node parametersNode = XmlHandler.getSubNode(node, "parameters");
+ if (parametersNode == null) {
+ return;
+ }
+ String value = XmlHandler.getTagValue(parametersNode, "inherit_all_vars");
+ if (value != null) {
+ setInheritingAllVariables("Y".equalsIgnoreCase(value));
}
}
diff --git
a/plugins/transforms/writetolog/src/main/java/org/apache/hop/pipeline/transforms/writetolog/WriteToLogMeta.java
b/plugins/transforms/writetolog/src/main/java/org/apache/hop/pipeline/transforms/writetolog/WriteToLogMeta.java
index 53ffae9f3e..32a13da9b3 100644
---
a/plugins/transforms/writetolog/src/main/java/org/apache/hop/pipeline/transforms/writetolog/WriteToLogMeta.java
+++
b/plugins/transforms/writetolog/src/main/java/org/apache/hop/pipeline/transforms/writetolog/WriteToLogMeta.java
@@ -25,7 +25,7 @@ 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.HopXmlException;
+import org.apache.hop.core.exception.HopException;
import org.apache.hop.core.logging.LogLevel;
import org.apache.hop.core.row.IRowMeta;
import org.apache.hop.core.variables.IVariables;
@@ -101,20 +101,14 @@ public class WriteToLogMeta extends
BaseTransformMeta<WriteToLog, WriteToLogData
return retval;
}
- /**
- * Added for backwards compatibility
- *
- * @deprecated
- * @param transformNode The XML node of the transform
- * @param metadataProvider The metadata provided
- * @throws HopXmlException When unable to read the XML
- */
+ /** Added for backwards compatibility with older prefixed log level values.
*/
@Override
- @Deprecated(since = "2.13")
- public void loadXml(Node transformNode, IHopMetadataProvider
metadataProvider)
- throws HopXmlException {
- super.loadXml(transformNode, metadataProvider);
- String loglevel = XmlHandler.getTagValue(transformNode, "loglevel");
+ public void convertLegacyXml(Node node) throws HopException {
+ if (node == null) {
+ return;
+ }
+
+ String loglevel = XmlHandler.getTagValue(node, "loglevel");
if (loglevel != null && loglevel.startsWith("log_level_")) {
switch (loglevel) {
case "log_level_nothing":
diff --git
a/ui/src/main/java/org/apache/hop/ui/hopgui/perspective/explorer/ExplorerPerspective.java
b/ui/src/main/java/org/apache/hop/ui/hopgui/perspective/explorer/ExplorerPerspective.java
index 6f25060d9f..fd45b5d200 100644
---
a/ui/src/main/java/org/apache/hop/ui/hopgui/perspective/explorer/ExplorerPerspective.java
+++
b/ui/src/main/java/org/apache/hop/ui/hopgui/perspective/explorer/ExplorerPerspective.java
@@ -2901,17 +2901,30 @@ public class ExplorerPerspective implements
IHopPerspective, TabClosable, IFileD
// Sort by full path ascending
Arrays.sort(children, Comparator.comparing(Object::toString));
+ String metadataFolder =
hopGui.getVariables().getVariable(Const.HOP_METADATA_FOLDER);
+ String metadataFolderName = null;
+ if (!Utils.isEmpty(metadataFolder)) {
+ String resolvedMetadataFolder =
hopGui.getVariables().resolve(metadataFolder);
+ if (!Utils.isEmpty(resolvedMetadataFolder)) {
+ String normalizedMetadataFolder =
resolvedMetadataFolder.replace('\\', '/');
+ int lastSlashIndex = normalizedMetadataFolder.lastIndexOf('/');
+ metadataFolderName =
+ (lastSlashIndex >= 0)
+ ? normalizedMetadataFolder.substring(lastSlashIndex + 1)
+ : normalizedMetadataFolder;
+ }
+ }
+
for (boolean folder : new boolean[] {true, false}) {
for (FileObject child : children) {
String childName = child.getName().getBaseName();
- String metadataFolder =
hopGui.getVariables().getVariable(Const.HOP_METADATA_FOLDER);
+ boolean isMetadataFolderMatch =
+ !Utils.isEmpty(metadataFolderName) &&
metadataFolderName.equals(childName);
// Skip hidden files or folders
if (!showingHiddenFiles
- && (child.isHidden()
- || childName.startsWith(".")
- || child.toString().contains(metadataFolder))) {
+ && (child.isHidden() || childName.startsWith(".") ||
isMetadataFolderMatch)) {
continue;
}