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 c4753932f0 Issue #1938 (code cleanup, extra integration tests) (#6756)
c4753932f0 is described below
commit c4753932f02aa96dec5b35b06a886464cfce63e9
Author: Matt Casters <[email protected]>
AuthorDate: Thu Mar 12 08:19:50 2026 +0100
Issue #1938 (code cleanup, extra integration tests) (#6756)
---
.../transforms/0086-string-operations.hpl | 534 +++++++++
.../datasets/golden-string-operations.csv | 2 +
.../datasets/golden-string-operations2.csv | 2 +
.../transforms/main-0086-string-operations.hwf | 80 ++
.../metadata/dataset/golden-string-operations.json | 64 ++
.../dataset/golden-string-operations2.json | 64 ++
.../unit-test/0086-string-operations UNIT.json | 101 ++
.../stringoperations/StringOperations.java | 382 +++----
.../stringoperations/StringOperationsData.java | 28 -
.../stringoperations/StringOperationsDialog.java | 229 ++--
.../stringoperations/StringOperationsMeta.java | 1157 +++++++-------------
.../stringoperations/StringOperationsMetaTest.java | 247 +++--
.../stringoperations/StringOperationsTest.java | 149 ---
.../src/test/resources/transform.xml | 74 ++
.../src/test/resources/transform2.xml | 35 +
15 files changed, 1697 insertions(+), 1451 deletions(-)
diff --git a/integration-tests/transforms/0086-string-operations.hpl
b/integration-tests/transforms/0086-string-operations.hpl
new file mode 100644
index 0000000000..bd0873f114
--- /dev/null
+++ b/integration-tests/transforms/0086-string-operations.hpl
@@ -0,0 +1,534 @@
+<?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.
+
+-->
+<pipeline>
+ <info>
+ <name>0086-string-operations</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>
+ <created_user>-</created_user>
+ <created_date>2026/03/10 18:03:52.637</created_date>
+ <modified_user>-</modified_user>
+ <modified_date>2026/03/10 18:03:52.637</modified_date>
+ </info>
+ <notepads>
+ </notepads>
+ <order>
+ <hop>
+ <from>Data grid</from>
+ <to>String operations</to>
+ <enabled>Y</enabled>
+ </hop>
+ <hop>
+ <from>String operations</from>
+ <to>Validate</to>
+ <enabled>Y</enabled>
+ </hop>
+ <hop>
+ <from>Data grid 2</from>
+ <to>String operations 2</to>
+ <enabled>Y</enabled>
+ </hop>
+ <hop>
+ <from>String operations 2</from>
+ <to>Validate 2</to>
+ <enabled>Y</enabled>
+ </hop>
+ </order>
+ <transform>
+ <name>Data grid</name>
+ <type>DataGrid</type>
+ <description/>
+ <distribute>Y</distribute>
+ <custom_distribution/>
+ <copies>1</copies>
+ <partitioning>
+ <method>none</method>
+ <schema_name/>
+ </partitioning>
+ <data>
+ <line>
+ <item> Apache Hop </item>
+ <item>APACHE HOP</item>
+ <item>Apache Hop</item>
+ <item>apache hop</item>
+ <item><name>Apache Hop</name></item>
+ <item>123Apache Hop456</item>
+ <item>Apache
+Hop</item>
+ </line>
+ </data>
+ <fields>
+ <field>
+ <length>-1</length>
+ <precision>-1</precision>
+ <currency/>
+ <set_empty_string>N</set_empty_string>
+ <name>s1</name>
+ <format/>
+ <group/>
+ <decimal/>
+ <type>String</type>
+ </field>
+ <field>
+ <length>-1</length>
+ <precision>-1</precision>
+ <currency/>
+ <set_empty_string>N</set_empty_string>
+ <name>s2</name>
+ <format/>
+ <group/>
+ <decimal/>
+ <type>String</type>
+ </field>
+ <field>
+ <length>-1</length>
+ <precision>-1</precision>
+ <currency/>
+ <set_empty_string>N</set_empty_string>
+ <name>s3</name>
+ <format/>
+ <group/>
+ <decimal/>
+ <type>String</type>
+ </field>
+ <field>
+ <length>-1</length>
+ <precision>-1</precision>
+ <currency/>
+ <set_empty_string>N</set_empty_string>
+ <name>s4</name>
+ <format/>
+ <group/>
+ <decimal/>
+ <type>String</type>
+ </field>
+ <field>
+ <length>-1</length>
+ <precision>-1</precision>
+ <currency/>
+ <set_empty_string>N</set_empty_string>
+ <name>s5</name>
+ <format/>
+ <group/>
+ <decimal/>
+ <type>String</type>
+ </field>
+ <field>
+ <length>-1</length>
+ <precision>-1</precision>
+ <currency/>
+ <set_empty_string>N</set_empty_string>
+ <name>s6</name>
+ <format/>
+ <group/>
+ <decimal/>
+ <type>String</type>
+ </field>
+ <field>
+ <length>-1</length>
+ <precision>-1</precision>
+ <currency/>
+ <set_empty_string>N</set_empty_string>
+ <name>s7</name>
+ <format/>
+ <group/>
+ <decimal/>
+ <type>String</type>
+ </field>
+ </fields>
+ <attributes/>
+ <GUI>
+ <xloc>96</xloc>
+ <yloc>64</yloc>
+ </GUI>
+ </transform>
+ <transform>
+ <name>String operations</name>
+ <type>StringOperations</type>
+ <description/>
+ <distribute>Y</distribute>
+ <custom_distribution/>
+ <copies>1</copies>
+ <partitioning>
+ <method>none</method>
+ <schema_name/>
+ </partitioning>
+ <fields>
+ <field>
+ <in_stream_name>s1</in_stream_name>
+ <out_stream_name/>
+ <trim_type>both</trim_type>
+ <lower_upper>none</lower_upper>
+ <padding_type>none</padding_type>
+ <pad_char/>
+ <pad_len/>
+ <init_cap>no</init_cap>
+ <mask_xml>none</mask_xml>
+ <digits>none</digits>
+ <remove_special_characters>none</remove_special_characters>
+ </field>
+ <field>
+ <in_stream_name>s2</in_stream_name>
+ <out_stream_name/>
+ <trim_type>none</trim_type>
+ <lower_upper>lower</lower_upper>
+ <padding_type>none</padding_type>
+ <pad_char/>
+ <pad_len/>
+ <init_cap>no</init_cap>
+ <mask_xml>none</mask_xml>
+ <digits>none</digits>
+ <remove_special_characters>none</remove_special_characters>
+ </field>
+ <field>
+ <in_stream_name>s3</in_stream_name>
+ <out_stream_name/>
+ <trim_type>none</trim_type>
+ <lower_upper>none</lower_upper>
+ <padding_type>right</padding_type>
+ <pad_char>20</pad_char>
+ <pad_len>-</pad_len>
+ <init_cap>no</init_cap>
+ <mask_xml>none</mask_xml>
+ <digits>none</digits>
+ <remove_special_characters>none</remove_special_characters>
+ </field>
+ <field>
+ <in_stream_name>s4</in_stream_name>
+ <out_stream_name/>
+ <trim_type>none</trim_type>
+ <lower_upper>none</lower_upper>
+ <padding_type>none</padding_type>
+ <pad_char/>
+ <pad_len/>
+ <init_cap>yes</init_cap>
+ <mask_xml>none</mask_xml>
+ <digits>none</digits>
+ <remove_special_characters>none</remove_special_characters>
+ </field>
+ <field>
+ <in_stream_name>s5</in_stream_name>
+ <out_stream_name/>
+ <trim_type>none</trim_type>
+ <lower_upper>none</lower_upper>
+ <padding_type>none</padding_type>
+ <pad_char/>
+ <pad_len/>
+ <init_cap>no</init_cap>
+ <mask_xml>escapexml</mask_xml>
+ <digits>none</digits>
+ <remove_special_characters>none</remove_special_characters>
+ </field>
+ <field>
+ <in_stream_name>s6</in_stream_name>
+ <out_stream_name/>
+ <trim_type>none</trim_type>
+ <lower_upper>none</lower_upper>
+ <padding_type>none</padding_type>
+ <pad_char/>
+ <pad_len/>
+ <init_cap>no</init_cap>
+ <mask_xml>none</mask_xml>
+ <digits>remove_digits</digits>
+ <remove_special_characters>none</remove_special_characters>
+ </field>
+ <field>
+ <in_stream_name>s7</in_stream_name>
+ <out_stream_name/>
+ <trim_type>none</trim_type>
+ <lower_upper>none</lower_upper>
+ <padding_type>none</padding_type>
+ <pad_char/>
+ <pad_len/>
+ <init_cap>no</init_cap>
+ <mask_xml>none</mask_xml>
+ <digits>none</digits>
+ <remove_special_characters>lf</remove_special_characters>
+ </field>
+ </fields>
+ <attributes/>
+ <GUI>
+ <xloc>224</xloc>
+ <yloc>64</yloc>
+ </GUI>
+ </transform>
+ <transform>
+ <name>Validate</name>
+ <type>Dummy</type>
+ <description/>
+ <distribute>Y</distribute>
+ <custom_distribution/>
+ <copies>1</copies>
+ <partitioning>
+ <method>none</method>
+ <schema_name/>
+ </partitioning>
+ <attributes/>
+ <GUI>
+ <xloc>368</xloc>
+ <yloc>64</yloc>
+ </GUI>
+ </transform>
+ <transform>
+ <name>Data grid 2</name>
+ <type>DataGrid</type>
+ <description/>
+ <distribute>Y</distribute>
+ <custom_distribution/>
+ <copies>1</copies>
+ <partitioning>
+ <method>none</method>
+ <schema_name/>
+ </partitioning>
+ <data>
+ <line>
+ <item> Apache Hop </item>
+ <item>apache hop</item>
+ <item>Apache Hop</item>
+ <item>apache hop</item>
+ <item><name>Apache Hop</name></item>
+ <item>123Apache Hop456</item>
+ <item>Apache- Hop</item>
+ </line>
+ </data>
+ <fields>
+ <field>
+ <length>-1</length>
+ <precision>-1</precision>
+ <currency/>
+ <set_empty_string>N</set_empty_string>
+ <name>s1</name>
+ <format/>
+ <group/>
+ <decimal/>
+ <type>String</type>
+ </field>
+ <field>
+ <length>-1</length>
+ <precision>-1</precision>
+ <currency/>
+ <set_empty_string>N</set_empty_string>
+ <name>s2</name>
+ <format/>
+ <group/>
+ <decimal/>
+ <type>String</type>
+ </field>
+ <field>
+ <length>-1</length>
+ <precision>-1</precision>
+ <currency/>
+ <set_empty_string>N</set_empty_string>
+ <name>s3</name>
+ <format/>
+ <group/>
+ <decimal/>
+ <type>String</type>
+ </field>
+ <field>
+ <length>-1</length>
+ <precision>-1</precision>
+ <currency/>
+ <set_empty_string>N</set_empty_string>
+ <name>s4</name>
+ <format/>
+ <group/>
+ <decimal/>
+ <type>String</type>
+ </field>
+ <field>
+ <length>-1</length>
+ <precision>-1</precision>
+ <currency/>
+ <set_empty_string>N</set_empty_string>
+ <name>s5</name>
+ <format/>
+ <group/>
+ <decimal/>
+ <type>String</type>
+ </field>
+ <field>
+ <length>-1</length>
+ <precision>-1</precision>
+ <currency/>
+ <set_empty_string>N</set_empty_string>
+ <name>s6</name>
+ <format/>
+ <group/>
+ <decimal/>
+ <type>String</type>
+ </field>
+ <field>
+ <length>-1</length>
+ <precision>-1</precision>
+ <currency/>
+ <set_empty_string>N</set_empty_string>
+ <name>s7</name>
+ <format/>
+ <group/>
+ <decimal/>
+ <type>String</type>
+ </field>
+ </fields>
+ <attributes/>
+ <GUI>
+ <xloc>96</xloc>
+ <yloc>160</yloc>
+ </GUI>
+ </transform>
+ <transform>
+ <name>String operations 2</name>
+ <type>StringOperations</type>
+ <description/>
+ <distribute>Y</distribute>
+ <custom_distribution/>
+ <copies>1</copies>
+ <partitioning>
+ <method>none</method>
+ <schema_name/>
+ </partitioning>
+ <fields>
+ <field>
+ <in_stream_name>s1</in_stream_name>
+ <out_stream_name/>
+ <trim_type>both</trim_type>
+ <lower_upper>none</lower_upper>
+ <padding_type>none</padding_type>
+ <pad_char/>
+ <pad_len/>
+ <init_cap>no</init_cap>
+ <mask_xml>none</mask_xml>
+ <digits>none</digits>
+ <remove_special_characters>none</remove_special_characters>
+ </field>
+ <field>
+ <in_stream_name>s2</in_stream_name>
+ <out_stream_name/>
+ <trim_type>none</trim_type>
+ <lower_upper>upper</lower_upper>
+ <padding_type>none</padding_type>
+ <pad_char/>
+ <pad_len/>
+ <init_cap>no</init_cap>
+ <mask_xml>none</mask_xml>
+ <digits>none</digits>
+ <remove_special_characters>none</remove_special_characters>
+ </field>
+ <field>
+ <in_stream_name>s3</in_stream_name>
+ <out_stream_name/>
+ <trim_type>none</trim_type>
+ <lower_upper>none</lower_upper>
+ <padding_type>left</padding_type>
+ <pad_char>20</pad_char>
+ <pad_len>-</pad_len>
+ <init_cap>no</init_cap>
+ <mask_xml>none</mask_xml>
+ <digits>none</digits>
+ <remove_special_characters>none</remove_special_characters>
+ </field>
+ <field>
+ <in_stream_name>s4</in_stream_name>
+ <out_stream_name/>
+ <trim_type>none</trim_type>
+ <lower_upper>none</lower_upper>
+ <padding_type>none</padding_type>
+ <pad_char/>
+ <pad_len/>
+ <init_cap>yes</init_cap>
+ <mask_xml>none</mask_xml>
+ <digits>none</digits>
+ <remove_special_characters>none</remove_special_characters>
+ </field>
+ <field>
+ <in_stream_name>s5</in_stream_name>
+ <out_stream_name/>
+ <trim_type>none</trim_type>
+ <lower_upper>none</lower_upper>
+ <padding_type>none</padding_type>
+ <pad_char/>
+ <pad_len/>
+ <init_cap>no</init_cap>
+ <mask_xml>cdata</mask_xml>
+ <digits>none</digits>
+ <remove_special_characters>none</remove_special_characters>
+ </field>
+ <field>
+ <in_stream_name>s6</in_stream_name>
+ <out_stream_name/>
+ <trim_type>none</trim_type>
+ <lower_upper>none</lower_upper>
+ <padding_type>none</padding_type>
+ <pad_char/>
+ <pad_len/>
+ <init_cap>no</init_cap>
+ <mask_xml>none</mask_xml>
+ <digits>digits_only</digits>
+ <remove_special_characters>none</remove_special_characters>
+ </field>
+ <field>
+ <in_stream_name>s7</in_stream_name>
+ <out_stream_name/>
+ <trim_type>none</trim_type>
+ <lower_upper>none</lower_upper>
+ <padding_type>none</padding_type>
+ <pad_char/>
+ <pad_len/>
+ <init_cap>no</init_cap>
+ <mask_xml>none</mask_xml>
+ <digits>none</digits>
+ <remove_special_characters>espace</remove_special_characters>
+ </field>
+ </fields>
+ <attributes/>
+ <GUI>
+ <xloc>224</xloc>
+ <yloc>160</yloc>
+ </GUI>
+ </transform>
+ <transform>
+ <name>Validate 2</name>
+ <type>Dummy</type>
+ <description/>
+ <distribute>Y</distribute>
+ <custom_distribution/>
+ <copies>1</copies>
+ <partitioning>
+ <method>none</method>
+ <schema_name/>
+ </partitioning>
+ <attributes/>
+ <GUI>
+ <xloc>368</xloc>
+ <yloc>160</yloc>
+ </GUI>
+ </transform>
+ <transform_error_handling>
+ </transform_error_handling>
+ <attributes/>
+</pipeline>
diff --git a/integration-tests/transforms/datasets/golden-string-operations.csv
b/integration-tests/transforms/datasets/golden-string-operations.csv
new file mode 100644
index 0000000000..1c4d9dc3ad
--- /dev/null
+++ b/integration-tests/transforms/datasets/golden-string-operations.csv
@@ -0,0 +1,2 @@
+s1,s2,s3,s4,s5,s6,s7
+Apache Hop,apache hop,Apache Hop,Apache Hop,<name>Apache
Hop</name>,Apache Hop,Apache Hop
diff --git
a/integration-tests/transforms/datasets/golden-string-operations2.csv
b/integration-tests/transforms/datasets/golden-string-operations2.csv
new file mode 100644
index 0000000000..08ccfc1367
--- /dev/null
+++ b/integration-tests/transforms/datasets/golden-string-operations2.csv
@@ -0,0 +1,2 @@
+s1,s2,s3,s4,s5,s6,s7
+Apache Hop,APACHE HOP,Apache Hop,Apache Hop,<![CDATA[<name>Apache
Hop</name>]]>,123456,Apache-Hop
diff --git a/integration-tests/transforms/main-0086-string-operations.hwf
b/integration-tests/transforms/main-0086-string-operations.hwf
new file mode 100644
index 0000000000..4fb869f2dd
--- /dev/null
+++ b/integration-tests/transforms/main-0086-string-operations.hwf
@@ -0,0 +1,80 @@
+<?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.
+
+-->
+<workflow>
+ <name>main-0086-string-operations</name>
+ <name_sync_with_filename>Y</name_sync_with_filename>
+ <description/>
+ <extended_description/>
+ <workflow_version/>
+ <created_user>-</created_user>
+ <created_date>2025/12/07 14:10:31.342</created_date>
+ <modified_user>-</modified_user>
+ <modified_date>2025/12/07 14:10:31.342</modified_date>
+ <parameters>
+ </parameters>
+ <actions>
+ <action>
+ <name>Start</name>
+ <description/>
+ <type>SPECIAL</type>
+ <attributes/>
+ <DayOfMonth>1</DayOfMonth>
+ <doNotWaitOnFirstExecution>N</doNotWaitOnFirstExecution>
+ <hour>12</hour>
+ <intervalMinutes>60</intervalMinutes>
+ <intervalSeconds>0</intervalSeconds>
+ <minutes>0</minutes>
+ <repeat>N</repeat>
+ <schedulerType>0</schedulerType>
+ <weekDay>1</weekDay>
+ <parallel>N</parallel>
+ <xloc>80</xloc>
+ <yloc>64</yloc>
+ <attributes_hac/>
+ </action>
+ <action>
+ <name>Run 0086 tests</name>
+ <description/>
+ <type>RunPipelineTests</type>
+ <attributes/>
+ <test_names>
+ <test_name>
+ <name>0086-string-operations UNIT</name>
+ </test_name>
+ </test_names>
+ <parallel>N</parallel>
+ <xloc>256</xloc>
+ <yloc>64</yloc>
+ <attributes_hac/>
+ </action>
+ </actions>
+ <hops>
+ <hop>
+ <from>Start</from>
+ <to>Run 0086 tests</to>
+ <enabled>Y</enabled>
+ <evaluation>Y</evaluation>
+ <unconditional>Y</unconditional>
+ </hop>
+ </hops>
+ <notepads>
+ </notepads>
+ <attributes/>
+</workflow>
diff --git
a/integration-tests/transforms/metadata/dataset/golden-string-operations.json
b/integration-tests/transforms/metadata/dataset/golden-string-operations.json
new file mode 100644
index 0000000000..36c7be969d
--- /dev/null
+++
b/integration-tests/transforms/metadata/dataset/golden-string-operations.json
@@ -0,0 +1,64 @@
+{
+ "base_filename": "golden-string-operations.csv",
+ "name": "golden-string-operations",
+ "description": "",
+ "dataset_fields": [
+ {
+ "field_comment": "",
+ "field_length": -1,
+ "field_type": 2,
+ "field_precision": -1,
+ "field_name": "s1",
+ "field_format": ""
+ },
+ {
+ "field_comment": "",
+ "field_length": -1,
+ "field_type": 2,
+ "field_precision": -1,
+ "field_name": "s2",
+ "field_format": ""
+ },
+ {
+ "field_comment": "",
+ "field_length": 0,
+ "field_type": 2,
+ "field_precision": -1,
+ "field_name": "s3",
+ "field_format": ""
+ },
+ {
+ "field_comment": "",
+ "field_length": -1,
+ "field_type": 2,
+ "field_precision": -1,
+ "field_name": "s4",
+ "field_format": ""
+ },
+ {
+ "field_comment": "",
+ "field_length": -1,
+ "field_type": 2,
+ "field_precision": -1,
+ "field_name": "s5",
+ "field_format": ""
+ },
+ {
+ "field_comment": "",
+ "field_length": -1,
+ "field_type": 2,
+ "field_precision": -1,
+ "field_name": "s6",
+ "field_format": ""
+ },
+ {
+ "field_comment": "",
+ "field_length": -1,
+ "field_type": 2,
+ "field_precision": -1,
+ "field_name": "s7",
+ "field_format": ""
+ }
+ ],
+ "folder_name": ""
+}
\ No newline at end of file
diff --git
a/integration-tests/transforms/metadata/dataset/golden-string-operations2.json
b/integration-tests/transforms/metadata/dataset/golden-string-operations2.json
new file mode 100644
index 0000000000..89e5a82c64
--- /dev/null
+++
b/integration-tests/transforms/metadata/dataset/golden-string-operations2.json
@@ -0,0 +1,64 @@
+{
+ "base_filename": "golden-string-operations2.csv",
+ "name": "golden-string-operations2",
+ "description": "",
+ "dataset_fields": [
+ {
+ "field_comment": "",
+ "field_length": -1,
+ "field_type": 2,
+ "field_precision": -1,
+ "field_name": "s1",
+ "field_format": ""
+ },
+ {
+ "field_comment": "",
+ "field_length": -1,
+ "field_type": 2,
+ "field_precision": -1,
+ "field_name": "s2",
+ "field_format": ""
+ },
+ {
+ "field_comment": "",
+ "field_length": 0,
+ "field_type": 2,
+ "field_precision": -1,
+ "field_name": "s3",
+ "field_format": ""
+ },
+ {
+ "field_comment": "",
+ "field_length": -1,
+ "field_type": 2,
+ "field_precision": -1,
+ "field_name": "s4",
+ "field_format": ""
+ },
+ {
+ "field_comment": "",
+ "field_length": -1,
+ "field_type": 2,
+ "field_precision": -1,
+ "field_name": "s5",
+ "field_format": ""
+ },
+ {
+ "field_comment": "",
+ "field_length": -1,
+ "field_type": 2,
+ "field_precision": -1,
+ "field_name": "s6",
+ "field_format": ""
+ },
+ {
+ "field_comment": "",
+ "field_length": -1,
+ "field_type": 2,
+ "field_precision": -1,
+ "field_name": "s7",
+ "field_format": ""
+ }
+ ],
+ "folder_name": ""
+}
\ No newline at end of file
diff --git
a/integration-tests/transforms/metadata/unit-test/0086-string-operations
UNIT.json
b/integration-tests/transforms/metadata/unit-test/0086-string-operations
UNIT.json
new file mode 100644
index 0000000000..28d172102e
--- /dev/null
+++ b/integration-tests/transforms/metadata/unit-test/0086-string-operations
UNIT.json
@@ -0,0 +1,101 @@
+{
+ "database_replacements": [],
+ "autoOpening": true,
+ "description": "",
+ "persist_filename": "",
+ "test_type": "UNIT_TEST",
+ "variableValues": [],
+ "basePath": "${HOP_UNIT_TESTS_FOLDER}",
+ "golden_data_sets": [
+ {
+ "field_mappings": [
+ {
+ "transform_field": "s1",
+ "data_set_field": "s1"
+ },
+ {
+ "transform_field": "s2",
+ "data_set_field": "s2"
+ },
+ {
+ "transform_field": "s3",
+ "data_set_field": "s3"
+ },
+ {
+ "transform_field": "s4",
+ "data_set_field": "s4"
+ },
+ {
+ "transform_field": "s5",
+ "data_set_field": "s5"
+ },
+ {
+ "transform_field": "s6",
+ "data_set_field": "s6"
+ },
+ {
+ "transform_field": "s7",
+ "data_set_field": "s7"
+ }
+ ],
+ "field_order": [
+ "s1",
+ "s2",
+ "s3",
+ "s4",
+ "s5",
+ "s6",
+ "s7"
+ ],
+ "data_set_name": "golden-string-operations",
+ "transform_name": "Validate"
+ },
+ {
+ "field_mappings": [
+ {
+ "transform_field": "s1",
+ "data_set_field": "s1"
+ },
+ {
+ "transform_field": "s2",
+ "data_set_field": "s2"
+ },
+ {
+ "transform_field": "s3",
+ "data_set_field": "s3"
+ },
+ {
+ "transform_field": "s4",
+ "data_set_field": "s4"
+ },
+ {
+ "transform_field": "s5",
+ "data_set_field": "s5"
+ },
+ {
+ "transform_field": "s6",
+ "data_set_field": "s6"
+ },
+ {
+ "transform_field": "s7",
+ "data_set_field": "s7"
+ }
+ ],
+ "field_order": [
+ "s1",
+ "s2",
+ "s3",
+ "s4",
+ "s5",
+ "s6",
+ "s7"
+ ],
+ "data_set_name": "golden-string-operations2",
+ "transform_name": "Validate 2"
+ }
+ ],
+ "input_data_sets": [],
+ "name": "0086-string-operations UNIT",
+ "trans_test_tweaks": [],
+ "pipeline_filename": "./0086-string-operations.hpl"
+}
\ No newline at end of file
diff --git
a/plugins/transforms/stringoperations/src/main/java/org/apache/hop/pipeline/transforms/stringoperations/StringOperations.java
b/plugins/transforms/stringoperations/src/main/java/org/apache/hop/pipeline/transforms/stringoperations/StringOperations.java
index f885dab8d4..cb439a6dc3 100644
---
a/plugins/transforms/stringoperations/src/main/java/org/apache/hop/pipeline/transforms/stringoperations/StringOperations.java
+++
b/plugins/transforms/stringoperations/src/main/java/org/apache/hop/pipeline/transforms/stringoperations/StringOperations.java
@@ -20,8 +20,8 @@ package org.apache.hop.pipeline.transforms.stringoperations;
import org.apache.hop.core.Const;
import org.apache.hop.core.exception.HopException;
import org.apache.hop.core.exception.HopTransformException;
-import org.apache.hop.core.row.IRowMeta;
import org.apache.hop.core.row.IValueMeta;
+import org.apache.hop.core.row.RowDataUtil;
import org.apache.hop.core.row.ValueDataUtil;
import org.apache.hop.core.util.Utils;
import org.apache.hop.i18n.BaseMessages;
@@ -29,8 +29,9 @@ import org.apache.hop.pipeline.Pipeline;
import org.apache.hop.pipeline.PipelineMeta;
import org.apache.hop.pipeline.transform.BaseTransform;
import org.apache.hop.pipeline.transform.TransformMeta;
+import org.jetbrains.annotations.Nullable;
-/** Apply certain operations too string. */
+/** Apply certain operations to string. */
public class StringOperations extends BaseTransform<StringOperationsMeta,
StringOperationsData> {
private static final Class<?> PKG = StringOperationsMeta.class;
@@ -44,170 +45,127 @@ public class StringOperations extends
BaseTransform<StringOperationsMeta, String
super(transformMeta, meta, data, copyNr, pipelineMeta, pipeline);
}
- private String processString(
- String string,
- int trimType,
- int lowerUpper,
- int padType,
- String padChar,
- int padLen,
- int iniCap,
- int maskHTML,
- int digits,
- int removeSpecialCharacters) {
- String rcode = string;
+ private String processString(String string,
StringOperationsMeta.StringOperation operation) {
+ String processed = processStringTrim(operation.getTrimType(), string);
+ processed = processStringLowerUpper(operation.getLowerUpper(), processed);
+ processed =
+ processStringPadding(
+ operation.getPaddingType(),
+ operation.getPadChar(),
+ Const.toInt(operation.getPadLen(), -1),
+ processed);
+ processed = processStringInitCap(operation.getInitCap(), processed);
+ processed = processStringMaskXml(operation.getMaskXml(), processed);
+ processed = processStringDigits(operation.getDigits(), processed);
+ processed =
processStringRemoveSpecialCharacters(operation.getRemoveSpecialChars(),
processed);
+
+ return processed;
+ }
- // Trim ?
- if (!Utils.isEmpty(rcode)) {
- switch (trimType) {
- case StringOperationsMeta.TRIM_RIGHT:
- rcode = Const.rtrim(rcode);
- break;
- case StringOperationsMeta.TRIM_LEFT:
- rcode = Const.ltrim(rcode);
- break;
- case StringOperationsMeta.TRIM_BOTH:
- rcode = Const.trim(rcode);
- break;
- default:
- break;
- }
- }
- // Lower/Upper ?
- if (!Utils.isEmpty(rcode)) {
- switch (lowerUpper) {
- case StringOperationsMeta.LOWER_UPPER_LOWER:
- rcode = rcode.toLowerCase();
- break;
- case StringOperationsMeta.LOWER_UPPER_UPPER:
- rcode = rcode.toUpperCase();
- break;
- default:
- break;
- }
+ private static @Nullable String processStringRemoveSpecialCharacters(
+ StringOperationsMeta.RemoveSpecialChars removeSpecialCharacters, String
string) {
+
+ if (!Utils.isEmpty(string)) {
+ return switch (removeSpecialCharacters) {
+ case NONE -> string;
+ case CR -> Const.removeCR(string);
+ case LF -> Const.removeLF(string);
+ case CRLF -> Const.removeCRLF(string);
+ case TAB -> Const.removeTAB(string);
+ case SPACE -> string.replace(" ", "");
+ };
}
+ return string;
+ }
- // pad String?
- if (!Utils.isEmpty(rcode)) {
- switch (padType) {
- case StringOperationsMeta.PADDING_LEFT:
- rcode = Const.lpad(rcode, padChar, padLen);
- break;
- case StringOperationsMeta.PADDING_RIGHT:
- rcode = Const.rpad(rcode, padChar, padLen);
- break;
- default:
- break;
- }
+ private static @Nullable String processStringDigits(
+ StringOperationsMeta.Digits digits, String string) {
+ if (!Utils.isEmpty(string)) {
+ return switch (digits) {
+ case NONE -> string;
+ case DIGITS_ONLY -> Const.getDigitsOnly(string);
+ case DIGITS_REMOVE -> Const.removeDigits(string);
+ };
}
+ return string;
+ }
- // InitCap ?
- if (!Utils.isEmpty(rcode)) {
- switch (iniCap) {
- case StringOperationsMeta.INIT_CAP_NO:
- break;
- case StringOperationsMeta.INIT_CAP_YES:
- rcode = ValueDataUtil.initCap(rcode);
- break;
- default:
- break;
- }
+ private static @Nullable String processStringMaskXml(
+ StringOperationsMeta.MaskXml maskXml, String string) {
+ if (!Utils.isEmpty(string)) {
+ return switch (maskXml) {
+ case NONE -> string;
+ case ESCAPE_XML -> Const.escapeXml(string);
+ case CDATA -> Const.protectXmlCdata(string);
+ case UNESCAPE_XML -> Const.unEscapeXml(string);
+ case ESCAPE_HTML -> Const.escapeHtml(string);
+ case UNESCAPE_HTML -> Const.unEscapeHtml(string);
+ case ESCAPE_SQL -> Const.escapeSql(string);
+ };
}
+ return string;
+ }
- // escape ?
- if (!Utils.isEmpty(rcode)) {
- switch (maskHTML) {
- case StringOperationsMeta.MASK_ESCAPE_XML:
- rcode = Const.escapeXml(rcode);
- break;
- case StringOperationsMeta.MASK_CDATA:
- rcode = Const.protectXmlCdata(rcode);
- break;
- case StringOperationsMeta.MASK_UNESCAPE_XML:
- rcode = Const.unEscapeXml(rcode);
- break;
- case StringOperationsMeta.MASK_ESCAPE_HTML:
- rcode = Const.escapeHtml(rcode);
- break;
- case StringOperationsMeta.MASK_UNESCAPE_HTML:
- rcode = Const.unEscapeHtml(rcode);
- break;
- case StringOperationsMeta.MASK_ESCAPE_SQL:
- rcode = Const.escapeSql(rcode);
- break;
- default:
- break;
- }
+ private static @Nullable String processStringInitCap(
+ StringOperationsMeta.InitCap iniCap, String string) {
+ if (!Utils.isEmpty(string)) {
+ return switch (iniCap) {
+ case NO -> string;
+ case YES -> ValueDataUtil.initCap(string);
+ };
}
+ return string;
+ }
- // digits only or remove digits ?
- if (!Utils.isEmpty(rcode)) {
- switch (digits) {
- case StringOperationsMeta.DIGITS_NONE:
- break;
- case StringOperationsMeta.DIGITS_ONLY:
- rcode = Const.getDigitsOnly(rcode);
- break;
- case StringOperationsMeta.DIGITS_REMOVE:
- rcode = Const.removeDigits(rcode);
- break;
- default:
- break;
- }
+ private static @Nullable String processStringPadding(
+ StringOperationsMeta.Padding padType, String padChar, int padLen, String
string) {
+ if (!Utils.isEmpty(string)) {
+ return switch (padType) {
+ case LEFT -> Const.lpad(string, padChar, padLen);
+ case RIGHT -> Const.rpad(string, padChar, padLen);
+ case NONE -> string;
+ };
}
+ return string;
+ }
- // remove special characters ?
- if (!Utils.isEmpty(rcode)) {
- switch (removeSpecialCharacters) {
- case StringOperationsMeta.REMOVE_SPECIAL_CHARACTERS_NONE:
- break;
- case StringOperationsMeta.REMOVE_SPECIAL_CHARACTERS_CR:
- rcode = Const.removeCR(rcode);
- break;
- case StringOperationsMeta.REMOVE_SPECIAL_CHARACTERS_LF:
- rcode = Const.removeLF(rcode);
- break;
- case StringOperationsMeta.REMOVE_SPECIAL_CHARACTERS_CRLF:
- rcode = Const.removeCRLF(rcode);
- break;
- case StringOperationsMeta.REMOVE_SPECIAL_CHARACTERS_TAB:
- rcode = Const.removeTAB(rcode);
- break;
- case StringOperationsMeta.REMOVE_SPECIAL_CHARACTERS_ESPACE:
- rcode = rcode.replace(" ", "");
- break;
- default:
- break;
- }
+ private static @Nullable String processStringLowerUpper(
+ StringOperationsMeta.LowerUpper lowerUpper, String string) {
+ if (!Utils.isEmpty(string)) {
+ return switch (lowerUpper) {
+ case NONE -> string;
+ case LOWER -> string.toLowerCase();
+ case UPPER -> string.toUpperCase();
+ };
}
+ return string;
+ }
- return rcode;
+ private static @Nullable String processStringTrim(
+ StringOperationsMeta.TrimType trimType, String string) {
+ if (!Utils.isEmpty(string)) {
+ return switch (trimType) {
+ case RIGHT -> Const.rtrim(string);
+ case LEFT -> Const.ltrim(string);
+ case BOTH -> Const.trim(string);
+ case NONE -> string;
+ };
+ }
+ return string;
}
- private Object[] processRow(IRowMeta rowMeta, Object[] row) throws
HopException {
+ private Object[] performStringOperations(Object[] row) throws HopException {
+ Object[] rowData = RowDataUtil.createResizedCopy(row,
data.outputRowMeta.size());
- Object[] rowData = new Object[data.outputRowMeta.size()];
- // Copy the input fields.
- System.arraycopy(row, 0, rowData, 0, rowMeta.size());
int j = 0; // Index into "new fields" area, past the first
{data.inputFieldsNr} records
- for (int i = 0; i < data.nrFieldsInStream; i++) {
+ for (int i = 0; i < meta.getOperations().size(); i++) {
+ StringOperationsMeta.StringOperation operation =
meta.getOperations().get(i);
if (data.inStreamNrs[i] >= 0) {
// Get source value
String value = getInputRowMeta().getString(row, data.inStreamNrs[i]);
// Apply String operations and return result value
- value =
- processString(
- value,
- data.trimOperators[i],
- data.lowerUpperOperators[i],
- data.padType[i],
- data.padChar[i],
- data.padLen[i],
- data.initCap[i],
- data.maskHTML[i],
- data.digits[i],
- data.removeSpecialCharacters[i]);
- if (Utils.isEmpty(data.outStreamNrs[i])) {
+ value = processString(value, operation);
+ if (Utils.isEmpty(operation.getFieldOutStream())) {
// Update field
rowData[data.inStreamNrs[i]] = value;
data.outputRowMeta
@@ -215,7 +173,7 @@ public class StringOperations extends
BaseTransform<StringOperationsMeta, String
.setStorageType(IValueMeta.STORAGE_TYPE_NORMAL);
} else {
// create a new Field
- rowData[data.inputFieldsNr + j] = value;
+ rowData[getInputRowMeta().size() + j] = value;
j++;
}
}
@@ -225,7 +183,6 @@ public class StringOperations extends
BaseTransform<StringOperationsMeta, String
@Override
public boolean processRow() throws HopException {
-
Object[] r = getRow(); // Get row from input rowset & set row busy!
if (r == null) {
// no more input to be expected...
@@ -235,90 +192,11 @@ public class StringOperations extends
BaseTransform<StringOperationsMeta, String
if (first) {
first = false;
-
- // What's the format of the output row?
- data.outputRowMeta = getInputRowMeta().clone();
- data.inputFieldsNr = data.outputRowMeta.size();
- meta.getFields(data.outputRowMeta, getTransformName(), null, null, this,
metadataProvider);
- data.nrFieldsInStream = meta.getFieldInStream().length;
- data.inStreamNrs = new int[data.nrFieldsInStream];
- for (int i = 0; i < meta.getFieldInStream().length; i++) {
- data.inStreamNrs[i] =
getInputRowMeta().indexOfValue(meta.getFieldInStream()[i]);
- if (data.inStreamNrs[i] < 0) { // couldn't find field!
-
- throw new HopTransformException(
- BaseMessages.getString(
- PKG, "StringOperations.Exception.FieldRequired",
meta.getFieldInStream()[i]));
- }
- // check field type
- if (!getInputRowMeta().getValueMeta(data.inStreamNrs[i]).isString()) {
- throw new HopTransformException(
- BaseMessages.getString(
- PKG,
- "StringOperations.Exception.FieldTypeNotString",
- meta.getFieldInStream()[i]));
- }
- }
-
- data.outStreamNrs = new String[data.nrFieldsInStream];
- for (int i = 0; i < meta.getFieldInStream().length; i++) {
- data.outStreamNrs[i] = meta.getFieldOutStream()[i];
- }
-
- // Keep track of the trim operators locally for a very small
- // optimization.
- data.trimOperators = new int[data.nrFieldsInStream];
- for (int i = 0; i < meta.getFieldInStream().length; i++) {
- data.trimOperators[i] = meta.getTrimType()[i];
- }
- // lower Upper
- data.lowerUpperOperators = new int[data.nrFieldsInStream];
- for (int i = 0; i < meta.getFieldInStream().length; i++) {
- data.lowerUpperOperators[i] = meta.getLowerUpper()[i];
- }
-
- // padding type?
- data.padType = new int[data.nrFieldsInStream];
- for (int i = 0; i < meta.getFieldInStream().length; i++) {
- data.padType[i] = meta.getPaddingType()[i];
- }
-
- // padding char
- data.padChar = new String[data.nrFieldsInStream];
- for (int i = 0; i < meta.getFieldInStream().length; i++) {
- data.padChar[i] = resolve(meta.getPadChar()[i]);
- }
-
- // padding len
- data.padLen = new int[data.nrFieldsInStream];
- for (int i = 0; i < meta.getFieldInStream().length; i++) {
- data.padLen[i] = Const.toInt(resolve(meta.getPadLen()[i]), 0);
- }
- // InitCap?
- data.initCap = new int[data.nrFieldsInStream];
- for (int i = 0; i < meta.getFieldInStream().length; i++) {
- data.initCap[i] = meta.getInitCap()[i];
- }
- // MaskXML?
- data.maskHTML = new int[data.nrFieldsInStream];
- for (int i = 0; i < meta.getFieldInStream().length; i++) {
- data.maskHTML[i] = meta.getMaskXML()[i];
- }
- // digits?
- data.digits = new int[data.nrFieldsInStream];
- for (int i = 0; i < meta.getFieldInStream().length; i++) {
- data.digits[i] = meta.getDigits()[i];
- }
- // remove special characters?
- data.removeSpecialCharacters = new int[data.nrFieldsInStream];
- for (int i = 0; i < meta.getFieldInStream().length; i++) {
- data.removeSpecialCharacters[i] = meta.getRemoveSpecialCharacters()[i];
- }
- } // end if first
+ firstProcessRow();
+ }
try {
- Object[] output = processRow(getInputRowMeta(), r);
-
+ Object[] output = performStringOperations(r);
putRow(data.outputRowMeta, output);
if (checkFeedback(getLinesRead()) && isDetailed()) {
@@ -326,12 +204,9 @@ public class StringOperations extends
BaseTransform<StringOperationsMeta, String
BaseMessages.getString(PKG, "StringOperations.Log.LineNumber") +
getLinesRead());
}
} catch (HopException e) {
-
- boolean sendToErrorRow = false;
- String errorMessage = null;
+ String errorMessage;
if (getTransformMeta().isDoingErrorHandling()) {
- sendToErrorRow = true;
errorMessage = e.toString();
} else {
logError(
@@ -341,28 +216,33 @@ public class StringOperations extends
BaseTransform<StringOperationsMeta, String
setOutputDone(); // signal end to receiver(s)
return false;
}
- if (sendToErrorRow) {
- // Simply add this row to the error row
- putError(getInputRowMeta(), r, 1, errorMessage, null,
"StringOperations001");
- }
+ // Simply add this row to the error row
+ putError(getInputRowMeta(), r, 1, errorMessage, null,
"StringOperations001");
}
return true;
}
- @Override
- public boolean init() {
- boolean rCode = true;
-
- if (super.init()) {
-
- return rCode;
+ private void firstProcessRow() throws HopTransformException {
+ // What's the format of the output row?
+ data.outputRowMeta = getInputRowMeta().clone();
+ meta.getFields(data.outputRowMeta, getTransformName(), null, null, this,
metadataProvider);
+ data.inStreamNrs = new int[meta.getOperations().size()];
+ for (int i = 0; i < meta.getOperations().size(); i++) {
+ StringOperationsMeta.StringOperation operation =
meta.getOperations().get(i);
+ data.inStreamNrs[i] =
getInputRowMeta().indexOfValue(operation.getFieldInStream());
+ if (data.inStreamNrs[i] < 0) { // couldn't find field!
+ throw new HopTransformException(
+ BaseMessages.getString(
+ PKG, "StringOperations.Exception.FieldRequired",
operation.getFieldInStream()));
+ }
+ // check field type
+ if (!getInputRowMeta().getValueMeta(data.inStreamNrs[i]).isString()) {
+ throw new HopTransformException(
+ BaseMessages.getString(
+ PKG,
+ "StringOperations.Exception.FieldTypeNotString",
+ operation.getFieldInStream()));
+ }
}
- return false;
- }
-
- @Override
- public void dispose() {
-
- super.dispose();
}
}
diff --git
a/plugins/transforms/stringoperations/src/main/java/org/apache/hop/pipeline/transforms/stringoperations/StringOperationsData.java
b/plugins/transforms/stringoperations/src/main/java/org/apache/hop/pipeline/transforms/stringoperations/StringOperationsData.java
index 24eaf6dd2a..7c08705273 100644
---
a/plugins/transforms/stringoperations/src/main/java/org/apache/hop/pipeline/transforms/stringoperations/StringOperationsData.java
+++
b/plugins/transforms/stringoperations/src/main/java/org/apache/hop/pipeline/transforms/stringoperations/StringOperationsData.java
@@ -27,38 +27,10 @@ public class StringOperationsData extends BaseTransformData
implements ITransfor
public int[] inStreamNrs; // string infields
- public String[] outStreamNrs;
-
- /** Runtime trim operators */
- public int[] trimOperators;
-
- /** Runtime trim operators */
- public int[] lowerUpperOperators;
-
- public int[] padType;
-
- public String[] padChar;
-
- public int[] padLen;
-
- public int[] initCap;
-
- public int[] maskHTML;
-
- public int[] digits;
-
- public int[] removeSpecialCharacters;
-
public IRowMeta outputRowMeta;
- public int inputFieldsNr;
-
- public int nrFieldsInStream;
-
/** Default constructor. */
public StringOperationsData() {
super();
- this.inputFieldsNr = 0;
- this.nrFieldsInStream = 0;
}
}
diff --git
a/plugins/transforms/stringoperations/src/main/java/org/apache/hop/pipeline/transforms/stringoperations/StringOperationsDialog.java
b/plugins/transforms/stringoperations/src/main/java/org/apache/hop/pipeline/transforms/stringoperations/StringOperationsDialog.java
index 8b35336f88..346348be9d 100644
---
a/plugins/transforms/stringoperations/src/main/java/org/apache/hop/pipeline/transforms/stringoperations/StringOperationsDialog.java
+++
b/plugins/transforms/stringoperations/src/main/java/org/apache/hop/pipeline/transforms/stringoperations/StringOperationsDialog.java
@@ -19,6 +19,7 @@ package org.apache.hop.pipeline.transforms.stringoperations;
import java.util.ArrayList;
import java.util.List;
+import org.apache.hop.core.Const;
import org.apache.hop.core.exception.HopException;
import org.apache.hop.core.row.IRowMeta;
import org.apache.hop.core.row.IValueMeta;
@@ -86,8 +87,75 @@ public class StringOperationsDialog extends
BaseTransformDialog {
fdlKey.top = new FormAttachment(wSpacer, margin);
wlKey.setLayoutData(fdlKey);
+ buildColumnsForFields();
+
+ wFields =
+ new TableView(
+ variables,
+ shell,
+ SWT.BORDER | SWT.FULL_SELECTION | SWT.MULTI | SWT.V_SCROLL |
SWT.H_SCROLL,
+ ciKey,
+ 1,
+ lsMod,
+ props);
+
+ FormData fdKey = new FormData();
+ fdKey.left = new FormAttachment(0, 0);
+ fdKey.top = new FormAttachment(wlKey, margin);
+ fdKey.right = new FormAttachment(100, -margin);
+ fdKey.bottom = new FormAttachment(wOk, -margin);
+ wFields.setLayoutData(fdKey);
+
+ getData();
+
+ findFieldsInBackground(display);
+
+ input.setChanged(changed);
+ focusTransformName();
+ BaseDialog.defaultShellHandling(shell, c -> ok(), c -> cancel());
+
+ return transformName;
+ }
+
+ private void findFieldsInBackground(Display display) {
+ final Runnable runnable =
+ () -> {
+ TransformMeta transformMeta =
pipelineMeta.findTransform(transformName);
+ if (transformMeta == null) {
+ return;
+ }
+ try {
+ IRowMeta row = pipelineMeta.getPrevTransformFields(variables,
transformMeta);
+ if (row != null) {
+ // Remember these fields...
+ for (int i = 0; i < row.size(); i++) {
+ inputFields.add(row.getValueMeta(i).getName());
+ }
+
+ setComboBoxes();
+ }
+
+ // Dislay in red missing field names
+ display.asyncExec(
+ () -> {
+ if (!wFields.isDisposed()) {
+ for (int i = 0; i < wFields.table.getItemCount(); i++) {
+ TableItem it = wFields.table.getItem(i);
+ if (!Utils.isEmpty(it.getText(1)) &&
(!inputFields.contains(it.getText(1)))) {
+
it.setBackground(GuiResource.getInstance().getColorRed());
+ }
+ }
+ }
+ });
+ } catch (HopException e) {
+ logError("Error getting fields from incoming stream!", e);
+ }
+ };
+ new Thread(runnable).start();
+ }
+
+ private void buildColumnsForFields() {
int nrFieldCols = 11;
- int nrFieldRows = (input.getFieldInStream() != null ?
input.getFieldInStream().length : 1);
ciKey = new ColumnInfo[nrFieldCols];
ciKey[0] =
@@ -105,19 +173,19 @@ public class StringOperationsDialog extends
BaseTransformDialog {
new ColumnInfo(
BaseMessages.getString(PKG,
"StringOperationsDialog.ColumnInfo.Trim"),
ColumnInfo.COLUMN_TYPE_CCOMBO,
- StringOperationsMeta.trimTypeDesc,
+ StringOperationsMeta.TrimType.getDescriptions(),
true);
ciKey[3] =
new ColumnInfo(
BaseMessages.getString(PKG,
"StringOperationsDialog.ColumnInfo.LowerUpper"),
ColumnInfo.COLUMN_TYPE_CCOMBO,
- StringOperationsMeta.lowerUpperDesc,
+ StringOperationsMeta.LowerUpper.getDescriptions(),
true);
ciKey[4] =
new ColumnInfo(
BaseMessages.getString(PKG,
"StringOperationsDialog.ColumnInfo.Padding"),
ColumnInfo.COLUMN_TYPE_CCOMBO,
- StringOperationsMeta.paddingDesc,
+ StringOperationsMeta.Padding.getDescriptions(),
true);
ciKey[5] =
new ColumnInfo(
@@ -133,23 +201,23 @@ public class StringOperationsDialog extends
BaseTransformDialog {
new ColumnInfo(
BaseMessages.getString(PKG,
"StringOperationsDialog.ColumnInfo.InitCap"),
ColumnInfo.COLUMN_TYPE_CCOMBO,
- StringOperationsMeta.initCapDesc);
+ StringOperationsMeta.InitCap.getDescriptions());
ciKey[8] =
new ColumnInfo(
BaseMessages.getString(PKG,
"StringOperationsDialog.ColumnInfo.MaskXML"),
ColumnInfo.COLUMN_TYPE_CCOMBO,
- StringOperationsMeta.maskXMLDesc);
+ StringOperationsMeta.MaskXml.getDescriptions());
ciKey[9] =
new ColumnInfo(
BaseMessages.getString(PKG,
"StringOperationsDialog.ColumnInfo.Digits"),
ColumnInfo.COLUMN_TYPE_CCOMBO,
- StringOperationsMeta.digitsDesc);
+ StringOperationsMeta.Digits.getDescriptions());
ciKey[10] =
new ColumnInfo(
BaseMessages.getString(
PKG,
"StringOperationsDialog.ColumnInfo.RemoveSpecialCharacters"),
ColumnInfo.COLUMN_TYPE_CCOMBO,
- StringOperationsMeta.removeSpecialCharactersDesc);
+ StringOperationsMeta.RemoveSpecialChars.getDescriptions());
ciKey[1].setToolTip(
BaseMessages.getString(PKG,
"StringOperationsDialog.ColumnInfo.OutStreamField.Tooltip"));
@@ -158,71 +226,6 @@ public class StringOperationsDialog extends
BaseTransformDialog {
ciKey[5].setUsingVariables(true);
ciKey[6].setUsingVariables(true);
ciKey[7].setUsingVariables(true);
-
- wFields =
- new TableView(
- variables,
- shell,
- SWT.BORDER | SWT.FULL_SELECTION | SWT.MULTI | SWT.V_SCROLL |
SWT.H_SCROLL,
- ciKey,
- nrFieldRows,
- lsMod,
- props);
-
- FormData fdKey = new FormData();
- fdKey.left = new FormAttachment(0, 0);
- fdKey.top = new FormAttachment(wlKey, margin);
- fdKey.right = new FormAttachment(100, -margin);
- fdKey.bottom = new FormAttachment(wOk, -margin);
- wFields.setLayoutData(fdKey);
-
- getData();
-
- //
- // Search the fields in the background
- //
-
- final Runnable runnable =
- () -> {
- TransformMeta transformMeta =
pipelineMeta.findTransform(transformName);
- if (transformMeta != null) {
- try {
- IRowMeta row = pipelineMeta.getPrevTransformFields(variables,
transformMeta);
- if (row != null) {
- // Remember these fields...
- for (int i = 0; i < row.size(); i++) {
- inputFields.add(row.getValueMeta(i).getName());
- }
-
- setComboBoxes();
- }
-
- // Dislay in red missing field names
- display.asyncExec(
- () -> {
- if (!wFields.isDisposed()) {
- for (int i = 0; i < wFields.table.getItemCount(); i++) {
- TableItem it = wFields.table.getItem(i);
- if (!Utils.isEmpty(it.getText(1))
- && (!inputFields.contains(it.getText(1)))) {
-
it.setBackground(GuiResource.getInstance().getColorRed());
- }
- }
- }
- });
-
- } catch (HopException e) {
- logError("Error getting fields from incoming stream!", e);
- }
- }
- };
- new Thread(runnable).start();
-
- input.setChanged(changed);
- focusTransformName();
- BaseDialog.defaultShellHandling(shell, c -> ok(), c -> cancel());
-
- return transformName;
}
protected void setComboBoxes() {
@@ -232,32 +235,19 @@ public class StringOperationsDialog extends
BaseTransformDialog {
/** Copy information from the meta-data input to the dialog fields. */
public void getData() {
- if (input.getFieldInStream() != null) {
- for (int i = 0; i < input.getFieldInStream().length; i++) {
- TableItem item = wFields.table.getItem(i);
- if (input.getFieldInStream()[i] != null) {
- item.setText(1, input.getFieldInStream()[i]);
- }
- if (input.getFieldOutStream()[i] != null) {
- item.setText(2, input.getFieldOutStream()[i]);
- }
- item.setText(3,
StringOperationsMeta.getTrimTypeDesc(input.getTrimType()[i]));
- item.setText(4,
StringOperationsMeta.getLowerUpperDesc(input.getLowerUpper()[i]));
- item.setText(5,
StringOperationsMeta.getPaddingDesc(input.getPaddingType()[i]));
- if (input.getPadChar()[i] != null) {
- item.setText(6, input.getPadChar()[i]);
- }
- if (input.getPadLen()[i] != null) {
- item.setText(7, input.getPadLen()[i]);
- }
- item.setText(8,
StringOperationsMeta.getInitCapDesc(input.getInitCap()[i]));
- item.setText(9,
StringOperationsMeta.getMaskXMLDesc(input.getMaskXML()[i]));
- item.setText(10,
StringOperationsMeta.getDigitsDesc(input.getDigits()[i]));
- item.setText(
- 11,
- StringOperationsMeta.getRemoveSpecialCharactersDesc(
- input.getRemoveSpecialCharacters()[i]));
- }
+ for (StringOperationsMeta.StringOperation operation :
input.getOperations()) {
+ TableItem item = new TableItem(wFields.table, SWT.NONE);
+ item.setText(1, Const.NVL(operation.getFieldInStream(), ""));
+ item.setText(2, Const.NVL(operation.getFieldOutStream(), ""));
+ item.setText(3, operation.getTrimType().getDescription());
+ item.setText(4, operation.getLowerUpper().getDescription());
+ item.setText(5, operation.getPaddingType().getDescription());
+ item.setText(6, Const.NVL(operation.getPadChar(), ""));
+ item.setText(7, Const.NVL(operation.getPadLen(), ""));
+ item.setText(8, operation.getInitCap().getDescription());
+ item.setText(9, operation.getMaskXml().getDescription());
+ item.setText(10, operation.getDigits().getDescription());
+ item.setText(11, operation.getRemoveSpecialChars().getDescription());
}
wFields.setRowNums();
@@ -270,30 +260,23 @@ public class StringOperationsDialog extends
BaseTransformDialog {
dispose();
}
- private void getInfo(StringOperationsMeta inf) {
- int nrkeys = wFields.nrNonEmpty();
-
- inf.allocate(nrkeys);
- if (isDebug()) {
- logDebug(
- BaseMessages.getString(
- PKG, "StringOperationsDialog.Log.FoundFields",
String.valueOf(nrkeys)));
- }
-
- for (int i = 0; i < nrkeys; i++) {
- TableItem item = wFields.getNonEmpty(i);
- inf.getFieldInStream()[i] = item.getText(1);
- inf.getFieldOutStream()[i] = item.getText(2);
- inf.getTrimType()[i] =
StringOperationsMeta.getTrimTypeByDesc(item.getText(3));
- inf.getLowerUpper()[i] =
StringOperationsMeta.getLowerUpperByDesc(item.getText(4));
- inf.getPaddingType()[i] =
StringOperationsMeta.getPaddingByDesc(item.getText(5));
- inf.getPadChar()[i] = item.getText(6);
- inf.getPadLen()[i] = item.getText(7);
- inf.getInitCap()[i] =
StringOperationsMeta.getInitCapByDesc(item.getText(8));
- inf.getMaskXML()[i] =
StringOperationsMeta.getMaskXMLByDesc(item.getText(9));
- inf.getDigits()[i] =
StringOperationsMeta.getDigitsByDesc(item.getText(10));
- inf.getRemoveSpecialCharacters()[i] =
-
StringOperationsMeta.getRemoveSpecialCharactersByDesc(item.getText(11));
+ private void getInfo(StringOperationsMeta m) {
+ m.getOperations().clear();
+ for (TableItem item : wFields.getNonEmptyItems()) {
+ StringOperationsMeta.StringOperation o = new
StringOperationsMeta.StringOperation();
+ o.setFieldInStream(item.getText(1));
+ o.setFieldOutStream(item.getText(2));
+
o.setTrimType(StringOperationsMeta.TrimType.lookupDescription(item.getText(3)));
+
o.setLowerUpper(StringOperationsMeta.LowerUpper.lookupDescription(item.getText(4)));
+
o.setPaddingType(StringOperationsMeta.Padding.lookupDescription(item.getText(5)));
+ o.setPadChar(item.getText(6));
+ o.setPadLen(item.getText(7));
+
o.setInitCap(StringOperationsMeta.InitCap.lookupDescription(item.getText(8)));
+
o.setMaskXml(StringOperationsMeta.MaskXml.lookupDescription(item.getText(9)));
+
o.setDigits(StringOperationsMeta.Digits.lookupDescription(item.getText(10)));
+ o.setRemoveSpecialChars(
+
StringOperationsMeta.RemoveSpecialChars.lookupDescription(item.getText(11)));
+ m.getOperations().add(o);
}
transformName = wTransformName.getText(); // return value
diff --git
a/plugins/transforms/stringoperations/src/main/java/org/apache/hop/pipeline/transforms/stringoperations/StringOperationsMeta.java
b/plugins/transforms/stringoperations/src/main/java/org/apache/hop/pipeline/transforms/stringoperations/StringOperationsMeta.java
index eecf2b205d..5b79086e33 100644
---
a/plugins/transforms/stringoperations/src/main/java/org/apache/hop/pipeline/transforms/stringoperations/StringOperationsMeta.java
+++
b/plugins/transforms/stringoperations/src/main/java/org/apache/hop/pipeline/transforms/stringoperations/StringOperationsMeta.java
@@ -17,27 +17,32 @@
package org.apache.hop.pipeline.transforms.stringoperations;
+import java.util.ArrayList;
+import java.util.HashSet;
import java.util.List;
+import java.util.Set;
+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.row.IValueMeta;
+import org.apache.hop.core.row.value.ValueMetaBase;
import org.apache.hop.core.row.value.ValueMetaString;
import org.apache.hop.core.util.Utils;
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.IEnumHasCodeAndDescription;
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;
+import org.jetbrains.annotations.NotNull;
@Transform(
id = "StringOperations",
@@ -48,476 +53,34 @@ import org.w3c.dom.Node;
keywords = "i18n::StringOperationsMeta.keyword",
documentationUrl = "/pipeline/transforms/stringoperations.html")
@InjectionSupported(localizationPrefix = "StringOperationsDialog.Injection.")
+@Getter
+@Setter
public class StringOperationsMeta
extends BaseTransformMeta<StringOperations, StringOperationsData> {
private static final Class<?> PKG = StringOperationsMeta.class;
public static final String CONST_SPACES = " ";
- /** which field in input stream to compare with? */
- @Injection(name = "SOURCEFIELDS")
- private String[] fieldInStream;
-
- /** output field */
- @Injection(name = "TARGETFIELDS")
- private String[] fieldOutStream;
-
- /** Trim type */
- @Injection(name = "TRIMTYPE")
- private int[] trimType;
-
- /** Lower/Upper type */
- @Injection(name = "LOWERUPPER")
- private int[] lowerUpper;
-
- /** InitCap */
- @Injection(name = "INITCAP")
- private int[] initCap;
-
- @Injection(name = "MASKXML")
- private int[] maskXML;
-
- @Injection(name = "DIGITS")
- private int[] digits;
-
- @Injection(name = "SPECIALCHARS")
- private int[] remove_special_characters;
-
- /** padding type */
- @Injection(name = "PADDING")
- private int[] paddingType;
-
- /** Pad length */
- @Injection(name = "PADLEN")
- private String[] padLen;
-
- @Injection(name = "PADCHAR")
- private String[] padChar;
-
- /** The trim type codes */
- public static final String[] trimTypeCode = {"none", "left", "right",
"both"};
-
- public static final int TRIM_NONE = 0;
-
- public static final int TRIM_LEFT = 1;
-
- public static final int TRIM_RIGHT = 2;
-
- public static final int TRIM_BOTH = 3;
-
- /** The trim description */
- public static final String[] trimTypeDesc = {
- BaseMessages.getString(PKG, "StringOperationsMeta.TrimType.None"),
- BaseMessages.getString(PKG, "StringOperationsMeta.TrimType.Left"),
- BaseMessages.getString(PKG, "StringOperationsMeta.TrimType.Right"),
- BaseMessages.getString(PKG, "StringOperationsMeta.TrimType.Both")
- };
-
- /** The lower upper codes */
- public static final String[] lowerUpperCode = {"none", "lower", "upper"};
-
- public static final int LOWER_UPPER_NONE = 0;
-
- public static final int LOWER_UPPER_LOWER = 1;
-
- public static final int LOWER_UPPER_UPPER = 2;
-
- /** The lower upper description */
- public static final String[] lowerUpperDesc = {
- BaseMessages.getString(PKG, "StringOperationsMeta.LowerUpper.None"),
- BaseMessages.getString(PKG, "StringOperationsMeta.LowerUpper.Lower"),
- BaseMessages.getString(PKG, "StringOperationsMeta.LowerUpper.Upper")
- };
-
- public static final String[] initCapDesc =
- new String[] {
- BaseMessages.getString(PKG, "System.Combo.No"),
- BaseMessages.getString(PKG, "System.Combo.Yes")
- };
-
- public static final String[] initCapCode = {"no", "yes"};
-
- public static final int INIT_CAP_NO = 0;
-
- public static final int INIT_CAP_YES = 1;
-
- // digits
- public static final String[] digitsCode = {"none", "digits_only",
"remove_digits"};
-
- public static final int DIGITS_NONE = 0;
-
- public static final int DIGITS_ONLY = 1;
-
- public static final int DIGITS_REMOVE = 2;
-
- public static final String[] digitsDesc =
- new String[] {
- BaseMessages.getString(PKG, "StringOperationsMeta.Digits.None"),
- BaseMessages.getString(PKG, "StringOperationsMeta.Digits.Only"),
- BaseMessages.getString(PKG, "StringOperationsMeta.Digits.Remove")
- };
-
- // mask XML
-
- public static final String[] maskXMLDesc =
- new String[] {
- BaseMessages.getString(PKG, "StringOperationsMeta.MaskXML.None"),
- BaseMessages.getString(PKG, "StringOperationsMeta.MaskXML.EscapeXML"),
- BaseMessages.getString(PKG, "StringOperationsMeta.MaskXML.CDATA"),
- BaseMessages.getString(PKG,
"StringOperationsMeta.MaskXML.UnEscapeXML"),
- BaseMessages.getString(PKG, "StringOperationsMeta.MaskXML.EscapeSQL"),
- BaseMessages.getString(PKG, "StringOperationsMeta.MaskXML.EscapeHTML"),
- BaseMessages.getString(PKG,
"StringOperationsMeta.MaskXML.UnEscapeHTML"),
- };
-
- public static final String[] maskXMLCode = {
- "none", "escapexml", "cdata", "unescapexml", "escapesql", "escapehtml",
"unescapehtml"
- };
-
- public static final int MASK_NONE = 0;
- public static final int MASK_ESCAPE_XML = 1;
- public static final int MASK_CDATA = 2;
- public static final int MASK_UNESCAPE_XML = 3;
- public static final int MASK_ESCAPE_SQL = 4;
- public static final int MASK_ESCAPE_HTML = 5;
- public static final int MASK_UNESCAPE_HTML = 6;
-
- // remove special characters
- public static final String[] removeSpecialCharactersCode = {
- "none", "cr", "lf", "crlf", "tab", "espace"
- };
-
- public static final int REMOVE_SPECIAL_CHARACTERS_NONE = 0;
-
- public static final int REMOVE_SPECIAL_CHARACTERS_CR = 1;
-
- public static final int REMOVE_SPECIAL_CHARACTERS_LF = 2;
-
- public static final int REMOVE_SPECIAL_CHARACTERS_CRLF = 3;
-
- public static final int REMOVE_SPECIAL_CHARACTERS_TAB = 4;
-
- public static final int REMOVE_SPECIAL_CHARACTERS_ESPACE = 5;
-
- public static final String[] removeSpecialCharactersDesc =
- new String[] {
- BaseMessages.getString(PKG,
"StringOperationsMeta.RemoveSpecialCharacters.None"),
- BaseMessages.getString(PKG,
"StringOperationsMeta.RemoveSpecialCharacters.CR"),
- BaseMessages.getString(PKG,
"StringOperationsMeta.RemoveSpecialCharacters.LF"),
- BaseMessages.getString(PKG,
"StringOperationsMeta.RemoveSpecialCharacters.CRLF"),
- BaseMessages.getString(PKG,
"StringOperationsMeta.RemoveSpecialCharacters.TAB"),
- BaseMessages.getString(PKG,
"StringOperationsMeta.RemoveSpecialCharacters.Space")
- };
-
- /** The padding description */
- public static final String[] paddingDesc = {
- BaseMessages.getString(PKG, "StringOperationsMeta.Padding.None"),
- BaseMessages.getString(PKG, "StringOperationsMeta.Padding.Left"),
- BaseMessages.getString(PKG, "StringOperationsMeta.Padding.Right")
- };
-
- public static final String[] paddingCode = {"none", "left", "right"};
-
- public static final int PADDING_NONE = 0;
-
- public static final int PADDING_LEFT = 1;
-
- public static final int PADDING_RIGHT = 2;
+ @HopMetadataProperty(
+ groupKey = "fields",
+ key = "field",
+ injectionGroupKey = "FIELDS",
+ injectionKey = "FIELD")
+ private List<StringOperation> operations;
public StringOperationsMeta() {
- super(); // allocate BaseTransformMeta
- }
-
- /**
- * @return Returns the fieldInStream.
- */
- public String[] getFieldInStream() {
- return fieldInStream;
- }
-
- /**
- * @param keyStream The fieldInStream to set.
- */
- public void setFieldInStream(String[] keyStream) {
- this.fieldInStream = keyStream;
- }
-
- /**
- * @return Returns the fieldOutStream.
- */
- public String[] getFieldOutStream() {
- return fieldOutStream;
- }
-
- /**
- * @param keyStream The fieldOutStream to set.
- */
- public void setFieldOutStream(String[] keyStream) {
- this.fieldOutStream = keyStream;
- }
-
- public String[] getPadLen() {
- return padLen;
+ super();
+ this.operations = new ArrayList<>();
}
- public void setPadLen(String[] value) {
- padLen = value;
- }
-
- public String[] getPadChar() {
- return padChar;
- }
-
- public void setPadChar(String[] value) {
- padChar = value;
- }
-
- public int[] getTrimType() {
- return trimType;
- }
-
- public void setTrimType(int[] trimType) {
- this.trimType = trimType;
- }
-
- public int[] getLowerUpper() {
- return lowerUpper;
- }
-
- public void setLowerUpper(int[] lowerUpper) {
- this.lowerUpper = lowerUpper;
- }
-
- public int[] getInitCap() {
- return initCap;
- }
-
- public void setInitCap(int[] value) {
- initCap = value;
- }
-
- public int[] getMaskXML() {
- return maskXML;
- }
-
- public void setMaskXML(int[] value) {
- maskXML = value;
- }
-
- public int[] getDigits() {
- return digits;
- }
-
- public void setDigits(int[] value) {
- digits = value;
- }
-
- public int[] getRemoveSpecialCharacters() {
- return remove_special_characters;
- }
-
- public void setRemoveSpecialCharacters(int[] value) {
- remove_special_characters = value;
- }
-
- public int[] getPaddingType() {
- return paddingType;
- }
-
- public void setPaddingType(int[] value) {
- paddingType = value;
- }
-
- @Override
- public void loadXml(Node transformNode, IHopMetadataProvider
metadataProvider)
- throws HopXmlException {
- readData(transformNode, metadataProvider);
- }
-
- public void allocate(int nrkeys) {
- fieldInStream = new String[nrkeys];
- fieldOutStream = new String[nrkeys];
- trimType = new int[nrkeys];
- lowerUpper = new int[nrkeys];
- paddingType = new int[nrkeys];
- padChar = new String[nrkeys];
- padLen = new String[nrkeys];
- initCap = new int[nrkeys];
- maskXML = new int[nrkeys];
- digits = new int[nrkeys];
- remove_special_characters = new int[nrkeys];
+ public StringOperationsMeta(StringOperationsMeta m) {
+ this();
+ m.operations.forEach(op -> this.operations.add(new StringOperation(op)));
}
@Override
public Object clone() {
- StringOperationsMeta retval = (StringOperationsMeta) super.clone();
- int nrkeys = fieldInStream.length;
-
- retval.allocate(nrkeys);
- System.arraycopy(fieldInStream, 0, retval.fieldInStream, 0, nrkeys);
- System.arraycopy(fieldOutStream, 0, retval.fieldOutStream, 0, nrkeys);
- System.arraycopy(trimType, 0, retval.trimType, 0, nrkeys);
- System.arraycopy(lowerUpper, 0, retval.lowerUpper, 0, nrkeys);
- System.arraycopy(paddingType, 0, retval.paddingType, 0, nrkeys);
- System.arraycopy(padChar, 0, retval.padChar, 0, nrkeys);
- System.arraycopy(padLen, 0, retval.padLen, 0, nrkeys);
- System.arraycopy(initCap, 0, retval.initCap, 0, nrkeys);
- System.arraycopy(maskXML, 0, retval.maskXML, 0, nrkeys);
- System.arraycopy(digits, 0, retval.digits, 0, nrkeys);
- System.arraycopy(remove_special_characters, 0,
retval.remove_special_characters, 0, nrkeys);
-
- return retval;
- }
-
- private void readData(Node transformNode, IHopMetadataProvider
metadataProvider)
- throws HopXmlException {
- try {
- int nrkeys;
-
- Node lookup = XmlHandler.getSubNode(transformNode, "fields");
- nrkeys = XmlHandler.countNodes(lookup, "field");
- allocate(nrkeys);
-
- for (int i = 0; i < nrkeys; i++) {
- Node fnode = XmlHandler.getSubNodeByNr(lookup, "field", i);
-
- fieldInStream[i] = Const.NVL(XmlHandler.getTagValue(fnode,
"in_stream_name"), "");
- fieldOutStream[i] = Const.NVL(XmlHandler.getTagValue(fnode,
"out_stream_name"), "");
-
- trimType[i] =
getTrimTypeByCode(Const.NVL(XmlHandler.getTagValue(fnode, "trim_type"), ""));
- lowerUpper[i] =
- getLowerUpperByCode(Const.NVL(XmlHandler.getTagValue(fnode,
"lower_upper"), ""));
- paddingType[i] =
- getPaddingByCode(Const.NVL(XmlHandler.getTagValue(fnode,
"padding_type"), ""));
- padChar[i] = Const.NVL(XmlHandler.getTagValue(fnode, "pad_char"), "");
- padLen[i] = Const.NVL(XmlHandler.getTagValue(fnode, "pad_len"), "");
- initCap[i] = getInitCapByCode(Const.NVL(XmlHandler.getTagValue(fnode,
"init_cap"), ""));
- maskXML[i] = getMaskXMLByCode(Const.NVL(XmlHandler.getTagValue(fnode,
"mask_xml"), ""));
- digits[i] = getDigitsByCode(Const.NVL(XmlHandler.getTagValue(fnode,
"digits"), ""));
- remove_special_characters[i] =
- getRemoveSpecialCharactersByCode(
- Const.NVL(XmlHandler.getTagValue(fnode,
"remove_special_characters"), ""));
- }
- } catch (Exception e) {
- throw new HopXmlException(
- BaseMessages.getString(
- PKG,
"StringOperationsMeta.Exception.UnableToReadTransformMetaFromXML"),
- e);
- }
- }
-
- @Override
- public void setDefault() {
- fieldInStream = null;
- fieldOutStream = null;
- allocate(0);
- }
-
- @Override
- public String getXml() {
- StringBuilder retval = new StringBuilder(500);
-
- retval.append(" <fields>").append(Const.CR);
-
- for (int i = 0; i < fieldInStream.length; i++) {
- // defaults when not present
- String lPadChar = (padChar.length == 0 || padChar.length <= i) ? "" :
padChar[i];
- String lPadLen = (padLen.length == 0 || padLen.length <= i) ? "" :
padLen[i];
-
- retval.append(" <field>").append(Const.CR);
- retval
- .append(CONST_SPACES)
- .append(XmlHandler.addTagValue("in_stream_name", fieldInStream[i]));
-
- retval
- .append(CONST_SPACES)
- .append(
- XmlHandler.addTagValue(
- "out_stream_name",
- (fieldOutStream == null
- || fieldOutStream.length == 0
- || fieldOutStream.length <= i)
- ? ""
- : !Utils.isEmpty(fieldOutStream[i]) ? fieldOutStream[i]
: ""));
- retval
- .append(CONST_SPACES)
- .append(
- XmlHandler.addTagValue(
- "trim_type",
- (trimType == null || trimType.length == 0 || trimType.length
<= i)
- ? ""
- : getTrimTypeCode(trimType[i])));
- retval
- .append(CONST_SPACES)
- .append(
- XmlHandler.addTagValue(
- "lower_upper",
- (lowerUpper == null || lowerUpper.length == 0 ||
lowerUpper.length <= i)
- ? ""
- : getLowerUpperCode(lowerUpper[i])));
- retval
- .append(CONST_SPACES)
- .append(
- XmlHandler.addTagValue(
- "padding_type",
- (paddingType == null || paddingType.length == 0 ||
paddingType.length <= i)
- ? ""
- : getPaddingCode(paddingType[i])));
- retval
- .append(CONST_SPACES)
- .append(
- XmlHandler.addTagValue(
- "pad_char",
- (padChar == null || padChar.length == 0 || padChar.length <=
i)
- ? ""
- : padChar[i]));
- retval
- .append(CONST_SPACES)
- .append(
- XmlHandler.addTagValue(
- "pad_len",
- (padLen == null || padLen.length == 0 || padLen.length <= i)
? "" : padLen[i]));
- retval
- .append(CONST_SPACES)
- .append(
- XmlHandler.addTagValue(
- "init_cap",
- (initCap == null || initCap.length == 0 || initCap.length <=
i)
- ? ""
- : getInitCapCode(initCap[i])));
- retval
- .append(CONST_SPACES)
- .append(
- XmlHandler.addTagValue(
- "mask_xml",
- (maskXML == null || maskXML.length == 0 || maskXML.length <=
i)
- ? ""
- : getMaskXMLCode(maskXML[i])));
- retval
- .append(CONST_SPACES)
- .append(
- XmlHandler.addTagValue(
- "digits",
- (digits == null || digits.length == 0 || digits.length <= i)
- ? ""
- : getDigitsCode(digits[i])));
- retval
- .append(CONST_SPACES)
- .append(
- XmlHandler.addTagValue(
- "remove_special_characters",
- (remove_special_characters == null
- || remove_special_characters.length == 0
- || remove_special_characters.length <= i)
- ? ""
- :
getRemoveSpecialCharactersCode(remove_special_characters[i])));
-
- retval.append(" </field>").append(Const.CR);
- }
-
- retval.append(" </fields>").append(Const.CR);
-
- return retval.toString();
+ return new StringOperationsMeta(this);
}
@Override
@@ -530,9 +93,9 @@ public class StringOperationsMeta
IHopMetadataProvider metadataProvider)
throws HopTransformException {
// Add new field?
- for (int i = 0; i < fieldOutStream.length; i++) {
+ for (StringOperation operation : operations) {
IValueMeta v;
- String outputField = variables.resolve(fieldOutStream[i]);
+ String outputField = variables.resolve(operation.fieldOutStream);
if (!Utils.isEmpty(outputField)) {
// Add a new field
v = new ValueMetaString(outputField);
@@ -540,14 +103,13 @@ public class StringOperationsMeta
v.setOrigin(name);
inputRowMeta.addValueMeta(v);
} else {
- v = inputRowMeta.searchValueMeta(fieldInStream[i]);
+ v = inputRowMeta.searchValueMeta(operation.fieldInStream);
if (v == null) {
continue;
}
v.setStorageType(IValueMeta.STORAGE_TYPE_NORMAL);
- int paddingType = getPaddingType()[i];
- if (paddingType == PADDING_LEFT || paddingType == PADDING_RIGHT) {
- int padLen = Const.toInt(variables.resolve(getPadLen()[i]), 0);
+ if (operation.paddingType == Padding.LEFT || operation.paddingType ==
Padding.RIGHT) {
+ int padLen = Const.toInt(variables.resolve(operation.padLen), 0);
if (padLen > v.getLength()) {
// alter meta data
v.setLength(padLen);
@@ -561,7 +123,7 @@ public class StringOperationsMeta
public void check(
List<ICheckResult> remarks,
PipelineMeta pipelineMeta,
- TransformMeta transforminfo,
+ TransformMeta transformMeta,
IRowMeta prev,
String[] input,
String[] output,
@@ -569,103 +131,139 @@ public class StringOperationsMeta
IVariables variables,
IHopMetadataProvider metadataProvider) {
- CheckResult cr;
- String errorMessage = "";
- boolean first = true;
- boolean errorFound = false;
+ if (checkNoInputReceived(remarks, transformMeta, prev)) {
+ return;
+ }
+ StringBuilder errorMessage = checkMissingFields(remarks, transformMeta,
prev);
+ checkAllFieldsAreStrings(remarks, transformMeta, prev, errorMessage);
+ checkMissingInputFields(remarks, transformMeta);
+ checkDistinctInputFields(remarks, transformMeta);
+ }
+ private static boolean checkNoInputReceived(
+ List<ICheckResult> remarks, TransformMeta transformMeta, IRowMeta prev) {
+ CheckResult cr;
if (prev == null) {
-
- errorMessage +=
- BaseMessages.getString(PKG,
"StringOperationsMeta.CheckResult.NoInputReceived")
- + Const.CR;
- cr = new CheckResult(ICheckResult.TYPE_RESULT_ERROR, errorMessage,
transforminfo);
+ cr =
+ new CheckResult(
+ ICheckResult.TYPE_RESULT_ERROR,
+ BaseMessages.getString(PKG,
"StringOperationsMeta.CheckResult.NoInputReceived")
+ + Const.CR,
+ transformMeta);
remarks.add(cr);
- } else {
+ // Nothing more to do.
+ //
+ return true;
+ }
+ return false;
+ }
- for (String field : fieldInStream) {
- IValueMeta v = prev.searchValueMeta(field);
- if (v == null) {
- if (first) {
- first = false;
- errorMessage +=
- BaseMessages.getString(
- PKG,
"StringOperationsMeta.CheckResult.MissingInStreamFields")
- + Const.CR;
- }
- errorFound = true;
- errorMessage += "\t\t" + field + Const.CR;
- }
- }
- if (errorFound) {
- cr = new CheckResult(ICheckResult.TYPE_RESULT_ERROR, errorMessage,
transforminfo);
- } else {
+ private void checkDistinctInputFields(List<ICheckResult> remarks,
TransformMeta transformMeta) {
+ CheckResult cr;
+ // Check if all input fields are distinct.
+ Set<String> inFields = new HashSet<>();
+ for (StringOperation operation : operations) {
+ if (inFields.contains(operation.fieldInStream)) {
cr =
new CheckResult(
- ICheckResult.TYPE_RESULT_OK,
- BaseMessages.getString(PKG,
"StringOperationsMeta.CheckResult.FoundInStreamFields"),
- transforminfo);
- }
- remarks.add(cr);
-
- // Check whether all are strings
- first = true;
- errorFound = false;
- for (String field : fieldInStream) {
- IValueMeta v = prev.searchValueMeta(field);
- if (v != null && v.getType() != IValueMeta.TYPE_STRING) {
- if (first) {
- first = false;
- errorMessage +=
+ ICheckResult.TYPE_RESULT_ERROR,
BaseMessages.getString(
- PKG,
"StringOperationsMeta.CheckResult.OperationOnNonStringFields")
- + Const.CR;
- }
- errorFound = true;
- errorMessage += "\t\t" + field + Const.CR;
- }
+ PKG,
+ "StringOperationsMeta.CheckResult.FieldInputError",
+ operation.fieldInStream),
+ transformMeta);
+ remarks.add(cr);
}
- if (errorFound) {
- cr = new CheckResult(ICheckResult.TYPE_RESULT_ERROR, errorMessage,
transforminfo);
- } else {
+ inFields.add(operation.fieldInStream);
+ }
+ }
+
+ private void checkMissingInputFields(List<ICheckResult> remarks,
TransformMeta transformMeta) {
+ CheckResult cr;
+ int idx = 1;
+ for (StringOperation operation : operations) {
+ if (Utils.isEmpty(operation.fieldInStream)) {
cr =
new CheckResult(
- ICheckResult.TYPE_RESULT_OK,
+ ICheckResult.TYPE_RESULT_ERROR,
BaseMessages.getString(
- PKG,
"StringOperationsMeta.CheckResult.AllOperationsOnStringFields"),
- transforminfo);
+ PKG,
+ "StringOperationsMeta.CheckResult.InStreamFieldMissing",
+ Integer.toString(idx)),
+ transformMeta);
+ remarks.add(cr);
}
- remarks.add(cr);
+ idx++;
+ }
+ }
- if (fieldInStream.length > 0) {
- for (int idx = 0; idx < fieldInStream.length; idx++) {
- if (Utils.isEmpty(fieldInStream[idx])) {
- cr =
- new CheckResult(
- ICheckResult.TYPE_RESULT_ERROR,
- BaseMessages.getString(
- PKG,
-
"StringOperationsMeta.CheckResult.InStreamFieldMissing",
- Integer.toString(idx + 1)),
- transforminfo);
- remarks.add(cr);
- }
+ private void checkAllFieldsAreStrings(
+ List<ICheckResult> remarks,
+ TransformMeta transformMeta,
+ IRowMeta prev,
+ StringBuilder errorMessage) {
+ boolean first;
+ boolean errorFound;
+ CheckResult cr;
+ // Check whether all are strings
+ first = true;
+ errorFound = false;
+ for (StringOperation operation : operations) {
+ IValueMeta v = prev.searchValueMeta(operation.fieldInStream);
+ if (v != null && v.getType() != IValueMeta.TYPE_STRING) {
+ if (first) {
+ first = false;
+ errorMessage
+ .append(
+ BaseMessages.getString(
+ PKG,
"StringOperationsMeta.CheckResult.OperationOnNonStringFields"))
+ .append(Const.CR);
}
+ errorFound = true;
+
errorMessage.append("\t\t").append(operation.fieldInStream).append(Const.CR);
}
+ }
+ if (errorFound) {
+ cr = new CheckResult(ICheckResult.TYPE_RESULT_ERROR,
errorMessage.toString(), transformMeta);
+ } else {
+ cr =
+ new CheckResult(
+ ICheckResult.TYPE_RESULT_OK,
+ BaseMessages.getString(
+ PKG,
"StringOperationsMeta.CheckResult.AllOperationsOnStringFields"),
+ transformMeta);
+ }
+ remarks.add(cr);
+ }
- // Check if all input fields are distinct.
- for (int idx = 0; idx < fieldInStream.length; idx++) {
- for (int jdx = 0; jdx < fieldInStream.length; jdx++) {
- if (fieldInStream[idx].equals(fieldInStream[jdx]) && idx != jdx &&
idx < jdx) {
- errorMessage =
+ private @NotNull StringBuilder checkMissingFields(
+ List<ICheckResult> remarks, TransformMeta transformMeta, IRowMeta prev) {
+ CheckResult cr;
+ boolean errorFound = false;
+ StringBuilder errorMessage = new StringBuilder();
+ for (StringOperation operation : operations) {
+ IValueMeta v = prev.searchValueMeta(operation.fieldInStream);
+ if (v == null) {
+ errorMessage
+ .append(
BaseMessages.getString(
- PKG, "StringOperationsMeta.CheckResult.FieldInputError",
fieldInStream[idx]);
- cr = new CheckResult(ICheckResult.TYPE_RESULT_ERROR, errorMessage,
transforminfo);
- remarks.add(cr);
- }
- }
+ PKG,
"StringOperationsMeta.CheckResult.MissingInStreamFields"))
+ .append(Const.CR);
}
+ errorFound = true;
+
errorMessage.append("\t\t").append(operation.fieldInStream).append(Const.CR);
}
+ if (errorFound) {
+ cr = new CheckResult(ICheckResult.TYPE_RESULT_ERROR,
errorMessage.toString(), transformMeta);
+ } else {
+ cr =
+ new CheckResult(
+ ICheckResult.TYPE_RESULT_OK,
+ BaseMessages.getString(PKG,
"StringOperationsMeta.CheckResult.FoundInStreamFields"),
+ transformMeta);
+ }
+ remarks.add(cr);
+ return errorMessage;
}
@Override
@@ -673,297 +271,288 @@ public class StringOperationsMeta
return true;
}
- private static String getTrimTypeCode(int i) {
- if (i < 0 || i >= trimTypeCode.length) {
- return trimTypeCode[0];
- }
- return trimTypeCode[i];
- }
-
- private static String getLowerUpperCode(int i) {
- if (i < 0 || i >= lowerUpperCode.length) {
- return lowerUpperCode[0];
- }
- return lowerUpperCode[i];
- }
-
- private static String getInitCapCode(int i) {
- if (i < 0 || i >= initCapCode.length) {
- return initCapCode[0];
- }
- return initCapCode[i];
- }
-
- private static String getMaskXMLCode(int i) {
- if (i < 0 || i >= maskXMLCode.length) {
- return maskXMLCode[0];
- }
- return maskXMLCode[i];
- }
-
- private static String getDigitsCode(int i) {
- if (i < 0 || i >= digitsCode.length) {
- return digitsCode[0];
- }
- return digitsCode[i];
- }
-
- private static String getRemoveSpecialCharactersCode(int i) {
- if (i < 0 || i >= removeSpecialCharactersCode.length) {
- return removeSpecialCharactersCode[0];
- }
- return removeSpecialCharactersCode[i];
- }
-
- private static String getPaddingCode(int i) {
- if (i < 0 || i >= paddingCode.length) {
- return paddingCode[0];
- }
- return paddingCode[i];
- }
-
- public static String getTrimTypeDesc(int i) {
- if (i < 0 || i >= trimTypeDesc.length) {
- return trimTypeDesc[0];
- }
- return trimTypeDesc[i];
- }
-
- public static String getLowerUpperDesc(int i) {
- if (i < 0 || i >= lowerUpperDesc.length) {
- return lowerUpperDesc[0];
- }
- return lowerUpperDesc[i];
- }
-
- public static String getInitCapDesc(int i) {
- if (i < 0 || i >= initCapDesc.length) {
- return initCapDesc[0];
- }
- return initCapDesc[i];
- }
-
- public static String getMaskXMLDesc(int i) {
- if (i < 0 || i >= maskXMLDesc.length) {
- return maskXMLDesc[0];
- }
- return maskXMLDesc[i];
- }
-
- public static String getDigitsDesc(int i) {
- if (i < 0 || i >= digitsDesc.length) {
- return digitsDesc[0];
- }
- return digitsDesc[i];
- }
-
- public static String getRemoveSpecialCharactersDesc(int i) {
- if (i < 0 || i >= removeSpecialCharactersDesc.length) {
- return removeSpecialCharactersDesc[0];
- }
- return removeSpecialCharactersDesc[i];
- }
+ @Getter
+ @Setter
+ public static class StringOperation {
+ /** which field in input stream to compare with? */
+ @HopMetadataProperty(
+ key = "in_stream_name",
+ injectionKey = "SOURCEFIELDS",
+ injectionKeyDescription =
"StringOperationsDialog.Injection.SOURCEFIELDS")
+ private String fieldInStream;
+
+ /** output field */
+ @HopMetadataProperty(
+ key = "out_stream_name",
+ injectionKey = "TARGETFIELDS",
+ injectionKeyDescription =
"StringOperationsDialog.Injection.TARGETFIELDS")
+ private String fieldOutStream;
+
+ /** Trim type */
+ @HopMetadataProperty(
+ key = "trim_type",
+ storeWithCode = true,
+ injectionKey = "TRIMTYPE",
+ injectionKeyDescription = "StringOperationsDialog.Injection.TRIMTYPE")
+ private TrimType trimType;
+
+ /** Lower/Upper type */
+ @HopMetadataProperty(
+ key = "lower_upper",
+ storeWithCode = true,
+ injectionKey = "LOWERUPPER",
+ injectionKeyDescription =
"StringOperationsDialog.Injection.LOWERUPPER")
+ private LowerUpper lowerUpper;
+
+ /** InitCap */
+ @HopMetadataProperty(
+ key = "init_cap",
+ storeWithCode = true,
+ injectionKey = "INITCAP",
+ injectionKeyDescription = "StringOperationsDialog.Injection.INITCAP")
+ private InitCap initCap;
+
+ @HopMetadataProperty(
+ key = "mask_xml",
+ storeWithCode = true,
+ injectionKey = "MASKXML",
+ injectionKeyDescription = "StringOperationsDialog.Injection.MASKXML")
+ private MaskXml maskXml;
+
+ @HopMetadataProperty(
+ key = "digits",
+ storeWithCode = true,
+ injectionKey = "DIGITS",
+ injectionKeyDescription = "StringOperationsDialog.Injection.DIGITS")
+ private Digits digits;
+
+ @HopMetadataProperty(
+ key = "remove_special_characters",
+ storeWithCode = true,
+ injectionKey = "SPECIALCHARS",
+ injectionKeyDescription =
"StringOperationsDialog.Injection.SPECIALCHARS")
+ private RemoveSpecialChars removeSpecialChars;
+
+ /** padding type */
+ @HopMetadataProperty(
+ key = "padding_type",
+ storeWithCode = true,
+ injectionKey = "PADDING",
+ injectionKeyDescription = "StringOperationsDialog.Injection.PADDING")
+ private Padding paddingType;
+
+ /** Pad length */
+ @HopMetadataProperty(
+ key = "pad_len",
+ injectionKey = "PADLEN",
+ injectionKeyDescription = "StringOperationsDialog.Injection.PADLEN")
+ private String padLen;
+
+ @HopMetadataProperty(
+ key = "pad_char",
+ injectionKey = "PADCHAR",
+ injectionKeyDescription = "StringOperationsDialog.Injection.PADCHAR")
+ private String padChar;
+
+ public StringOperation() {
+ this.trimType = TrimType.NONE;
+ this.lowerUpper = LowerUpper.NONE;
+ this.initCap = InitCap.NO;
+ this.maskXml = MaskXml.NONE;
+ this.paddingType = Padding.NONE;
+ this.removeSpecialChars = RemoveSpecialChars.NONE;
+ this.digits = Digits.NONE;
+ }
+
+ public StringOperation(StringOperation op) {
+ this();
+ this.digits = op.digits;
+ this.fieldInStream = op.fieldInStream;
+ this.fieldOutStream = op.fieldOutStream;
+ this.initCap = op.initCap;
+ this.lowerUpper = op.lowerUpper;
+ this.maskXml = op.maskXml;
+ this.padChar = op.padChar;
+ this.paddingType = op.paddingType;
+ this.padLen = op.padLen;
+ this.removeSpecialChars = op.removeSpecialChars;
+ this.trimType = op.trimType;
+ }
+ }
+
+ @Getter
+ public enum TrimType implements IEnumHasCodeAndDescription {
+ NONE(ValueMetaBase.trimTypeCode[0], ValueMetaBase.trimTypeDesc[0]),
+ LEFT(ValueMetaBase.trimTypeCode[1], ValueMetaBase.trimTypeDesc[1]),
+ RIGHT(ValueMetaBase.trimTypeCode[2], ValueMetaBase.trimTypeDesc[2]),
+ BOTH(ValueMetaBase.trimTypeCode[3], ValueMetaBase.trimTypeDesc[3]),
+ ;
+ private final String code;
+ private final String description;
+
+ TrimType(String code, String description) {
+ this.code = code;
+ this.description = description;
+ }
- public static String getPaddingDesc(int i) {
- if (i < 0 || i >= paddingDesc.length) {
- return paddingDesc[0];
+ public static String[] getDescriptions() {
+ return IEnumHasCodeAndDescription.getDescriptions(TrimType.class);
}
- return paddingDesc[i];
- }
- private static int getTrimTypeByCode(String tt) {
- if (tt == null) {
- return 0;
+ public static TrimType lookupDescription(String description) {
+ return IEnumHasCodeAndDescription.lookupDescription(TrimType.class,
description, NONE);
}
-
- for (int i = 0; i < trimTypeCode.length; i++) {
- if (trimTypeCode[i].equalsIgnoreCase(tt)) {
- return i;
- }
- }
- return 0;
}
- private static int getLowerUpperByCode(String tt) {
- if (tt == null) {
- return 0;
- }
+ @Getter
+ public enum LowerUpper implements IEnumHasCodeAndDescription {
+ NONE("none", BaseMessages.getString(PKG,
"StringOperationsMeta.LowerUpper.None")),
+ LOWER("lower", BaseMessages.getString(PKG,
"StringOperationsMeta.LowerUpper.Lower")),
+ UPPER("upper", BaseMessages.getString(PKG,
"StringOperationsMeta.LowerUpper.Upper")),
+ ;
+ private final String code;
+ private final String description;
- for (int i = 0; i < lowerUpperCode.length; i++) {
- if (lowerUpperCode[i].equalsIgnoreCase(tt)) {
- return i;
- }
+ LowerUpper(String code, String description) {
+ this.code = code;
+ this.description = description;
}
- return 0;
- }
- private static int getInitCapByCode(String tt) {
- if (tt == null) {
- return 0;
+ public static String[] getDescriptions() {
+ return IEnumHasCodeAndDescription.getDescriptions(LowerUpper.class);
}
- for (int i = 0; i < initCapCode.length; i++) {
- if (initCapCode[i].equalsIgnoreCase(tt)) {
- return i;
- }
+ public static LowerUpper lookupDescription(String description) {
+ return IEnumHasCodeAndDescription.lookupDescription(LowerUpper.class,
description, NONE);
}
- return 0;
}
- private static int getMaskXMLByCode(String tt) {
- if (tt == null) {
- return 0;
- }
+ @Getter
+ public enum InitCap implements IEnumHasCodeAndDescription {
+ NO("no", BaseMessages.getString("System.Combo.No")),
+ YES("yes", BaseMessages.getString("System.Combo.Yes")),
+ ;
+ private final String code;
+ private final String description;
- for (int i = 0; i < maskXMLCode.length; i++) {
- if (maskXMLCode[i].equalsIgnoreCase(tt)) {
- return i;
- }
+ InitCap(String code, String description) {
+ this.code = code;
+ this.description = description;
}
- return 0;
- }
- private static int getDigitsByCode(String tt) {
- if (tt == null) {
- return 0;
+ public static String[] getDescriptions() {
+ return IEnumHasCodeAndDescription.getDescriptions(InitCap.class);
}
- for (int i = 0; i < digitsCode.length; i++) {
- if (digitsCode[i].equalsIgnoreCase(tt)) {
- return i;
- }
+ public static InitCap lookupDescription(String description) {
+ return IEnumHasCodeAndDescription.lookupDescription(InitCap.class,
description, NO);
}
- return 0;
}
- private static int getRemoveSpecialCharactersByCode(String tt) {
- if (tt == null) {
- return 0;
- }
+ @Getter
+ public enum Digits implements IEnumHasCodeAndDescription {
+ NONE("none", BaseMessages.getString(PKG,
"StringOperationsMeta.Digits.None")),
+ DIGITS_ONLY("digits_only", BaseMessages.getString(PKG,
"StringOperationsMeta.Digits.Only")),
+ DIGITS_REMOVE(
+ "remove_digits", BaseMessages.getString(PKG,
"StringOperationsMeta.Digits.Remove")),
+ ;
+ private final String code;
+ private final String description;
- for (int i = 0; i < removeSpecialCharactersCode.length; i++) {
- if (removeSpecialCharactersCode[i].equalsIgnoreCase(tt)) {
- return i;
- }
+ Digits(String code, String description) {
+ this.code = code;
+ this.description = description;
}
- return 0;
- }
- private static int getPaddingByCode(String tt) {
- if (tt == null) {
- return 0;
+ public static String[] getDescriptions() {
+ return IEnumHasCodeAndDescription.getDescriptions(Digits.class);
}
- for (int i = 0; i < paddingCode.length; i++) {
- if (paddingCode[i].equalsIgnoreCase(tt)) {
- return i;
- }
+ public static Digits lookupDescription(String description) {
+ return IEnumHasCodeAndDescription.lookupDescription(Digits.class,
description, NONE);
}
- return 0;
}
- public static int getTrimTypeByDesc(String tt) {
- if (tt == null) {
- return 0;
- }
-
- for (int i = 0; i < trimTypeDesc.length; i++) {
- if (trimTypeDesc[i].equalsIgnoreCase(tt)) {
- return i;
- }
- }
-
- // If this fails, try to match using the code.
- return getTrimTypeByCode(tt);
- }
+ @Getter
+ public enum MaskXml implements IEnumHasCodeAndDescription {
+ NONE("none", BaseMessages.getString(PKG,
"StringOperationsMeta.MaskXML.None")),
+ ESCAPE_XML("escapexml", BaseMessages.getString(PKG,
"StringOperationsMeta.MaskXML.EscapeXML")),
+ CDATA("cdata", BaseMessages.getString(PKG,
"StringOperationsMeta.MaskXML.CDATA")),
+ UNESCAPE_XML(
+ "unescapexml", BaseMessages.getString(PKG,
"StringOperationsMeta.MaskXML.UnEscapeXML")),
+ ESCAPE_SQL("escapesql", BaseMessages.getString(PKG,
"StringOperationsMeta.MaskXML.EscapeSQL")),
+ ESCAPE_HTML(
+ "escapehtml", BaseMessages.getString(PKG,
"StringOperationsMeta.MaskXML.EscapeHTML")),
+ UNESCAPE_HTML(
+ "unescapehtml", BaseMessages.getString(PKG,
"StringOperationsMeta.MaskXML.UnEscapeHTML")),
+ ;
- public static int getLowerUpperByDesc(String tt) {
- if (tt == null) {
- return 0;
- }
+ private final String code;
+ private final String description;
- for (int i = 0; i < lowerUpperDesc.length; i++) {
- if (lowerUpperDesc[i].equalsIgnoreCase(tt)) {
- return i;
- }
+ MaskXml(String code, String description) {
+ this.code = code;
+ this.description = description;
}
- // If this fails, try to match using the code.
- return getLowerUpperByCode(tt);
- }
-
- public static int getInitCapByDesc(String tt) {
- if (tt == null) {
- return 0;
+ public static String[] getDescriptions() {
+ return IEnumHasCodeAndDescription.getDescriptions(MaskXml.class);
}
- for (int i = 0; i < initCapDesc.length; i++) {
- if (initCapDesc[i].equalsIgnoreCase(tt)) {
- return i;
- }
+ public static MaskXml lookupDescription(String description) {
+ return IEnumHasCodeAndDescription.lookupDescription(MaskXml.class,
description, NONE);
}
-
- // If this fails, try to match using the code.
- return getInitCapByCode(tt);
}
- public static int getMaskXMLByDesc(String tt) {
- if (tt == null) {
- return 0;
- }
+ @Getter
+ public enum RemoveSpecialChars implements IEnumHasCodeAndDescription {
+ NONE("none", BaseMessages.getString(PKG,
"StringOperationsMeta.RemoveSpecialCharacters.None")),
+ CR("cr", BaseMessages.getString(PKG,
"StringOperationsMeta.RemoveSpecialCharacters.CR")),
+ LF("lf", BaseMessages.getString(PKG,
"StringOperationsMeta.RemoveSpecialCharacters.LF")),
+ CRLF("crlf", BaseMessages.getString(PKG,
"StringOperationsMeta.RemoveSpecialCharacters.CRLF")),
+ TAB("tab", BaseMessages.getString(PKG,
"StringOperationsMeta.RemoveSpecialCharacters.TAB")),
+ SPACE(
+ "espace",
+ BaseMessages.getString(PKG,
"StringOperationsMeta.RemoveSpecialCharacters.Space")),
+ ;
+ private final String code;
+ private final String description;
- for (int i = 0; i < maskXMLDesc.length; i++) {
- if (maskXMLDesc[i].equalsIgnoreCase(tt)) {
- return i;
- }
+ RemoveSpecialChars(String code, String description) {
+ this.code = code;
+ this.description = description;
}
- // If this fails, try to match using the code.
- return getMaskXMLByCode(tt);
- }
-
- public static int getDigitsByDesc(String tt) {
- if (tt == null) {
- return 0;
+ public static String[] getDescriptions() {
+ return
IEnumHasCodeAndDescription.getDescriptions(RemoveSpecialChars.class);
}
- for (int i = 0; i < digitsDesc.length; i++) {
- if (digitsDesc[i].equalsIgnoreCase(tt)) {
- return i;
- }
+ public static RemoveSpecialChars lookupDescription(String description) {
+ return IEnumHasCodeAndDescription.lookupDescription(
+ RemoveSpecialChars.class, description, NONE);
}
-
- // If this fails, try to match using the code.
- return getDigitsByCode(tt);
}
- public static int getRemoveSpecialCharactersByDesc(String tt) {
- if (tt == null) {
- return 0;
- }
+ @Getter
+ public enum Padding implements IEnumHasCodeAndDescription {
+ NONE("none", BaseMessages.getString(PKG,
"StringOperationsMeta.Padding.None")),
+ LEFT("left", BaseMessages.getString(PKG,
"StringOperationsMeta.Padding.Left")),
+ RIGHT("right", BaseMessages.getString(PKG,
"StringOperationsMeta.Padding.Right")),
+ ;
+ private final String code;
+ private final String description;
- for (int i = 0; i < removeSpecialCharactersDesc.length; i++) {
- if (removeSpecialCharactersDesc[i].equalsIgnoreCase(tt)) {
- return i;
- }
+ Padding(String code, String description) {
+ this.code = code;
+ this.description = description;
}
- // If this fails, try to match using the code.
- return getRemoveSpecialCharactersByCode(tt);
- }
-
- public static int getPaddingByDesc(String tt) {
- if (tt == null) {
- return 0;
+ public static String[] getDescriptions() {
+ return IEnumHasCodeAndDescription.getDescriptions(Padding.class);
}
- for (int i = 0; i < paddingDesc.length; i++) {
- if (paddingDesc[i].equalsIgnoreCase(tt)) {
- return i;
- }
+ public static Padding lookupDescription(String description) {
+ return IEnumHasCodeAndDescription.lookupDescription(Padding.class,
description, NONE);
}
-
- // If this fails, try to match using the code.
- return getPaddingByCode(tt);
}
}
diff --git
a/plugins/transforms/stringoperations/src/test/java/org/apache/hop/pipeline/transforms/stringoperations/StringOperationsMetaTest.java
b/plugins/transforms/stringoperations/src/test/java/org/apache/hop/pipeline/transforms/stringoperations/StringOperationsMetaTest.java
index b69af50f9f..f1f1a47049 100644
---
a/plugins/transforms/stringoperations/src/test/java/org/apache/hop/pipeline/transforms/stringoperations/StringOperationsMetaTest.java
+++
b/plugins/transforms/stringoperations/src/test/java/org/apache/hop/pipeline/transforms/stringoperations/StringOperationsMetaTest.java
@@ -18,136 +18,151 @@
package org.apache.hop.pipeline.transforms.stringoperations;
import static org.junit.jupiter.api.Assertions.assertEquals;
-import static org.mockito.Mockito.mock;
+import static org.junit.jupiter.api.Assertions.assertFalse;
+import static org.junit.jupiter.api.Assertions.assertNotNull;
+import static org.junit.jupiter.api.Assertions.assertTrue;
-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 org.apache.hop.core.plugins.PluginRegistry;
-import org.apache.hop.core.row.IRowMeta;
-import org.apache.hop.core.row.IValueMeta;
-import org.apache.hop.core.row.RowMeta;
-import org.apache.hop.core.row.value.ValueMetaString;
-import org.apache.hop.core.variables.IVariables;
-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.junit.jupiter.api.BeforeEach;
+import java.nio.file.Files;
+import java.nio.file.Path;
+import java.nio.file.Paths;
+import java.util.Objects;
+import org.apache.commons.lang.StringUtils;
+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.Test;
-import org.junit.jupiter.api.extension.RegisterExtension;
-/** User: Dzmitry Stsiapanau Date: 2/3/14 Time: 5:41 PM */
-class StringOperationsMetaTest implements IInitializer<ITransformMeta> {
- LoadSaveTester loadSaveTester;
- Class<StringOperationsMeta> testMetaClass = StringOperationsMeta.class;
-
- @RegisterExtension
- static RestoreHopEngineEnvironmentExtension env = new
RestoreHopEngineEnvironmentExtension();
-
- @BeforeEach
- void setUpLoadSave() throws Exception {
- HopEnvironment.init();
- PluginRegistry.init();
- List<String> attributes =
- Arrays.asList(
- "padLen",
- "padChar",
- "fieldInStream",
- "fieldOutStream",
- "trimType",
- "lowerUpper",
- "initCap",
- "maskXML",
- "digits",
- "removeSpecialCharacters",
- "paddingType");
+class StringOperationsMetaTest {
+ @Test
+ void testLoadSave() throws Exception {
+ Path path =
Paths.get(Objects.requireNonNull(getClass().getResource("/transform.xml")).toURI());
+ String xml = Files.readString(path);
+ StringOperationsMeta meta = new StringOperationsMeta();
+ XmlMetadataUtil.deSerializeFromXml(
+ XmlHandler.loadXmlString(xml, TransformMeta.XML_TAG),
+ StringOperationsMeta.class,
+ meta,
+ new MemoryMetadataProvider());
- IFieldLoadSaveValidator<String[]> stringArrayLoadSaveValidator =
- new ArrayLoadSaveValidator<>(new StringLoadSaveValidator(), 5);
+ validate(meta);
- Map<String, IFieldLoadSaveValidator<?>> attrValidatorMap = new HashMap<>();
- attrValidatorMap.put("padLen", stringArrayLoadSaveValidator);
- attrValidatorMap.put("padChar", stringArrayLoadSaveValidator);
- attrValidatorMap.put("fieldInStream", stringArrayLoadSaveValidator);
- attrValidatorMap.put("fieldOutStream", stringArrayLoadSaveValidator);
- attrValidatorMap.put(
- "trimType", new PrimitiveIntArrayLoadSaveValidator(new
IntLoadSaveValidator(4), 5));
- attrValidatorMap.put(
- "lowerUpper",
- new PrimitiveIntArrayLoadSaveValidator(
- new
IntLoadSaveValidator(StringOperationsMeta.lowerUpperCode.length), 5));
- attrValidatorMap.put(
- "initCap",
- new PrimitiveIntArrayLoadSaveValidator(
- new IntLoadSaveValidator(StringOperationsMeta.initCapCode.length),
5));
- attrValidatorMap.put(
- "maskXML",
- new PrimitiveIntArrayLoadSaveValidator(
- new IntLoadSaveValidator(StringOperationsMeta.maskXMLCode.length),
5));
- attrValidatorMap.put(
- "digits",
- new PrimitiveIntArrayLoadSaveValidator(
- new IntLoadSaveValidator(StringOperationsMeta.digitsCode.length),
5));
- attrValidatorMap.put(
- "removeSpecialCharacters",
- new PrimitiveIntArrayLoadSaveValidator(
- new
IntLoadSaveValidator(StringOperationsMeta.removeSpecialCharactersCode.length),
5));
- attrValidatorMap.put(
- "paddingType",
- new PrimitiveIntArrayLoadSaveValidator(
- new IntLoadSaveValidator(StringOperationsMeta.paddingCode.length),
5));
+ // Do a round trip:
+ //
+ String xmlCopy =
+ XmlHandler.openTag(TransformMeta.XML_TAG)
+ + XmlMetadataUtil.serializeObjectToXml(meta)
+ + XmlHandler.closeTag(TransformMeta.XML_TAG);
+ StringOperationsMeta metaCopy = new StringOperationsMeta();
+ XmlMetadataUtil.deSerializeFromXml(
+ XmlHandler.loadXmlString(xmlCopy, TransformMeta.XML_TAG),
+ StringOperationsMeta.class,
+ metaCopy,
+ new MemoryMetadataProvider());
+ validate(metaCopy);
+ }
- Map<String, IFieldLoadSaveValidator<?>> typeValidatorMap = new HashMap<>();
+ private static void validate(StringOperationsMeta meta) {
+ assertNotNull(meta.getOperations());
+ assertFalse(meta.getOperations().isEmpty());
+ assertEquals(4, meta.getOperations().size());
+ StringOperationsMeta.StringOperation o1 = meta.getOperations().get(0);
+ assertEquals("desc_t", o1.getFieldInStream());
+ assertEquals("desc_trimmed", o1.getFieldOutStream());
+ assertEquals(StringOperationsMeta.TrimType.BOTH, o1.getTrimType());
+ assertEquals(StringOperationsMeta.LowerUpper.NONE, o1.getLowerUpper());
+ assertEquals(StringOperationsMeta.Padding.NONE, o1.getPaddingType());
+ assertTrue(StringUtils.isEmpty(o1.getPadChar()));
+ assertTrue(StringUtils.isEmpty(o1.getPadLen()));
+ assertEquals(StringOperationsMeta.InitCap.NO, o1.getInitCap());
+ assertEquals(StringOperationsMeta.MaskXml.NONE, o1.getMaskXml());
+ assertEquals(StringOperationsMeta.Digits.NONE, o1.getDigits());
+ assertEquals(StringOperationsMeta.RemoveSpecialChars.NONE,
o1.getRemoveSpecialChars());
- loadSaveTester =
- new LoadSaveTester(
- testMetaClass,
- attributes,
- new HashMap<>(),
- new HashMap<>(),
- attrValidatorMap,
- typeValidatorMap,
- this);
- }
+ StringOperationsMeta.StringOperation o2 = meta.getOperations().get(1);
+ assertEquals("desc_u", o2.getFieldInStream());
+ assertEquals("desc_upper", o2.getFieldOutStream());
+ assertEquals(StringOperationsMeta.TrimType.NONE, o2.getTrimType());
+ assertEquals(StringOperationsMeta.LowerUpper.UPPER, o2.getLowerUpper());
+ assertEquals(StringOperationsMeta.Padding.NONE, o2.getPaddingType());
+ assertTrue(StringUtils.isEmpty(o2.getPadChar()));
+ assertTrue(StringUtils.isEmpty(o2.getPadLen()));
+ assertEquals(StringOperationsMeta.InitCap.NO, o2.getInitCap());
+ assertEquals(StringOperationsMeta.MaskXml.NONE, o2.getMaskXml());
+ assertEquals(StringOperationsMeta.Digits.NONE, o2.getDigits());
+ assertEquals(StringOperationsMeta.RemoveSpecialChars.NONE,
o2.getRemoveSpecialChars());
- // Call the allocate method on the LoadSaveTester meta class
- @Override
- public void modify(ITransformMeta someMeta) {
- if (someMeta instanceof StringOperationsMeta) {
- ((StringOperationsMeta) someMeta).allocate(5);
- }
- }
+ StringOperationsMeta.StringOperation o3 = meta.getOperations().get(2);
+ assertEquals("desc_p", o3.getFieldInStream());
+ assertEquals("desc_padded", o3.getFieldOutStream());
+ assertEquals(StringOperationsMeta.TrimType.NONE, o3.getTrimType());
+ assertEquals(StringOperationsMeta.LowerUpper.NONE, o3.getLowerUpper());
+ assertEquals(StringOperationsMeta.Padding.LEFT, o3.getPaddingType());
+ assertEquals("#", o3.getPadChar());
+ assertEquals("25", o3.getPadLen());
+ assertEquals(StringOperationsMeta.InitCap.NO, o3.getInitCap());
+ assertEquals(StringOperationsMeta.MaskXml.NONE, o3.getMaskXml());
+ assertEquals(StringOperationsMeta.Digits.NONE, o3.getDigits());
+ assertEquals(StringOperationsMeta.RemoveSpecialChars.NONE,
o3.getRemoveSpecialChars());
- @Test
- void testSerialization() throws HopException {
- loadSaveTester.testSerialization();
+ StringOperationsMeta.StringOperation o4 = meta.getOperations().get(3);
+ assertEquals("desc_i", o4.getFieldInStream());
+ assertEquals("desc_initcapped", o4.getFieldOutStream());
+ assertEquals(StringOperationsMeta.TrimType.NONE, o4.getTrimType());
+ assertEquals(StringOperationsMeta.LowerUpper.NONE, o4.getLowerUpper());
+ assertEquals(StringOperationsMeta.Padding.NONE, o4.getPaddingType());
+ assertTrue(StringUtils.isEmpty(o2.getPadChar()));
+ assertTrue(StringUtils.isEmpty(o2.getPadLen()));
+ assertEquals(StringOperationsMeta.InitCap.YES, o4.getInitCap());
+ assertEquals(StringOperationsMeta.MaskXml.NONE, o4.getMaskXml());
+ assertEquals(StringOperationsMeta.Digits.NONE, o4.getDigits());
+ assertEquals(StringOperationsMeta.RemoveSpecialChars.NONE,
o4.getRemoveSpecialChars());
}
@Test
- void testGetFields() throws Exception {
+ void testLoadSave2() throws Exception {
+ Path path =
+
Paths.get(Objects.requireNonNull(getClass().getResource("/transform2.xml")).toURI());
+ String xml = Files.readString(path);
StringOperationsMeta meta = new StringOperationsMeta();
- meta.allocate(1);
- meta.setFieldInStream(new String[] {"field1"});
+ XmlMetadataUtil.deSerializeFromXml(
+ XmlHandler.loadXmlString(xml, TransformMeta.XML_TAG),
+ StringOperationsMeta.class,
+ meta,
+ new MemoryMetadataProvider());
- IRowMeta iRowMeta = new RowMeta();
- IValueMeta valueMeta = new ValueMetaString("field1");
- valueMeta.setStorageMetadata(new ValueMetaString("field1"));
- valueMeta.setStorageType(IValueMeta.STORAGE_TYPE_BINARY_STRING);
- iRowMeta.addValueMeta(valueMeta);
+ validate2(meta);
+
+ // Do a round trip:
+ //
+ String xmlCopy =
+ XmlHandler.openTag(TransformMeta.XML_TAG)
+ + XmlMetadataUtil.serializeObjectToXml(meta)
+ + XmlHandler.closeTag(TransformMeta.XML_TAG);
+ StringOperationsMeta metaCopy = new StringOperationsMeta();
+ XmlMetadataUtil.deSerializeFromXml(
+ XmlHandler.loadXmlString(xmlCopy, TransformMeta.XML_TAG),
+ StringOperationsMeta.class,
+ metaCopy,
+ new MemoryMetadataProvider());
+ validate2(metaCopy);
+ }
- IVariables variables = mock(IVariables.class);
- meta.getFields(iRowMeta, "STRING_OPERATIONS", null, null, variables, null);
- IRowMeta expectedRowMeta = new RowMeta();
- expectedRowMeta.addValueMeta(new ValueMetaString("field1"));
- assertEquals(expectedRowMeta.toString(), iRowMeta.toString());
+ private void validate2(StringOperationsMeta meta) {
+ assertNotNull(meta.getOperations());
+ assertFalse(meta.getOperations().isEmpty());
+ assertEquals(1, meta.getOperations().size());
+ StringOperationsMeta.StringOperation o1 = meta.getOperations().get(0);
+ assertEquals("in_field", o1.getFieldInStream());
+ assertEquals("out_field", o1.getFieldOutStream());
+ assertEquals(StringOperationsMeta.TrimType.BOTH, o1.getTrimType());
+ assertEquals(StringOperationsMeta.LowerUpper.UPPER, o1.getLowerUpper());
+ assertEquals(StringOperationsMeta.Padding.RIGHT, o1.getPaddingType());
+ assertEquals(" ", o1.getPadChar());
+ assertEquals("20", o1.getPadLen());
+ assertEquals(StringOperationsMeta.InitCap.YES, o1.getInitCap());
+ assertEquals(StringOperationsMeta.MaskXml.UNESCAPE_XML, o1.getMaskXml());
+ assertEquals(StringOperationsMeta.Digits.DIGITS_REMOVE, o1.getDigits());
+ assertEquals(StringOperationsMeta.RemoveSpecialChars.CRLF,
o1.getRemoveSpecialChars());
}
}
diff --git
a/plugins/transforms/stringoperations/src/test/java/org/apache/hop/pipeline/transforms/stringoperations/StringOperationsTest.java
b/plugins/transforms/stringoperations/src/test/java/org/apache/hop/pipeline/transforms/stringoperations/StringOperationsTest.java
deleted file mode 100644
index 2015abdac4..0000000000
---
a/plugins/transforms/stringoperations/src/test/java/org/apache/hop/pipeline/transforms/stringoperations/StringOperationsTest.java
+++ /dev/null
@@ -1,149 +0,0 @@
-/*
- * 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.stringoperations;
-
-import static org.junit.jupiter.api.Assertions.assertTrue;
-import static org.mockito.ArgumentMatchers.any;
-import static org.mockito.Mockito.doReturn;
-import static org.mockito.Mockito.mock;
-import static org.mockito.Mockito.when;
-
-import org.apache.hop.core.IRowSet;
-import org.apache.hop.core.QueueRowSet;
-import org.apache.hop.core.exception.HopException;
-import org.apache.hop.core.exception.HopValueException;
-import org.apache.hop.core.logging.ILoggingObject;
-import org.apache.hop.core.row.IValueMeta;
-import org.apache.hop.core.row.RowMeta;
-import org.apache.hop.core.row.value.ValueMetaString;
-import org.apache.hop.pipeline.transforms.mock.TransformMockHelper;
-import org.junit.jupiter.api.AfterEach;
-import org.junit.jupiter.api.BeforeEach;
-import org.junit.jupiter.api.Disabled;
-import org.junit.jupiter.api.Test;
-
-/**
- * Tests for StringOperations transform
- *
- * @see StringOperations
- */
-class StringOperationsTest {
- private static TransformMockHelper<StringOperationsMeta,
StringOperationsData> smh;
-
- @BeforeEach
- void setup() throws Exception {
- smh =
- new TransformMockHelper<>(
- "StringOperations", StringOperationsMeta.class,
StringOperationsData.class);
- when(smh.logChannelFactory.create(any(), any(ILoggingObject.class)))
- .thenReturn(smh.iLogChannel);
- when(smh.pipeline.isRunning()).thenReturn(true);
- }
-
- @AfterEach
- void cleanUp() {
- smh.cleanUp();
- }
-
- private IRowSet mockInputRowSet() {
- ValueMetaString valueMeta = new ValueMetaString("Value");
- valueMeta.setStorageType(IValueMeta.STORAGE_TYPE_BINARY_STRING);
- valueMeta.setStorageMetadata(new ValueMetaString("Value"));
-
- RowMeta inputRowMeta = new RowMeta();
- inputRowMeta.addValueMeta(valueMeta);
-
- IRowSet inputRowSet = smh.getMockInputRowSet(new Object[][] {{" Value
".getBytes()}});
- doReturn(inputRowMeta).when(inputRowSet).getRowMeta();
-
- return inputRowSet;
- }
-
- private StringOperationsMeta mockTransformMeta() {
- StringOperationsMeta meta = mock(StringOperationsMeta.class);
- doReturn(new String[] {"Value"}).when(meta).getFieldInStream();
- doReturn(new String[] {""}).when(meta).getFieldOutStream();
- doReturn(new int[]
{StringOperationsMeta.TRIM_BOTH}).when(meta).getTrimType();
- doReturn(new int[]
{StringOperationsMeta.LOWER_UPPER_NONE}).when(meta).getLowerUpper();
- doReturn(new int[]
{StringOperationsMeta.PADDING_NONE}).when(meta).getPaddingType();
- doReturn(new String[] {""}).when(meta).getPadChar();
- doReturn(new String[] {""}).when(meta).getPadLen();
- doReturn(new int[]
{StringOperationsMeta.INIT_CAP_NO}).when(meta).getInitCap();
- doReturn(new int[]
{StringOperationsMeta.MASK_NONE}).when(meta).getMaskXML();
- doReturn(new int[]
{StringOperationsMeta.DIGITS_NONE}).when(meta).getDigits();
- doReturn(new int[] {StringOperationsMeta.REMOVE_SPECIAL_CHARACTERS_NONE})
- .when(meta)
- .getRemoveSpecialCharacters();
-
- return meta;
- }
-
- private StringOperationsData mockTransformData() {
- return mock(StringOperationsData.class);
- }
-
- private boolean verifyOutput(Object[][] expectedRows, IRowSet outputRowSet)
- throws HopValueException {
- if (expectedRows.length == outputRowSet.size()) {
- for (Object[] expectedRow : expectedRows) {
- Object[] row = outputRowSet.getRow();
- if (expectedRow.length == outputRowSet.getRowMeta().size()) {
- for (int j = 0; j < expectedRow.length; j++) {
- if
(!expectedRow[j].equals(outputRowSet.getRowMeta().getString(row, j))) {
- return false;
- }
- }
- return true;
- }
- }
- }
- return false;
- }
-
- @Test
- @Disabled("This test needs to be reviewed")
- void testProcessBinaryInput() throws HopException {
- StringOperations transform =
- new StringOperations(
- smh.transformMeta,
- smh.iTransformMeta,
- smh.iTransformData,
- 0,
- smh.pipelineMeta,
- smh.pipeline);
- transform.addRowSetToInputRowSets(mockInputRowSet());
-
- IRowSet outputRowSet = new QueueRowSet();
- transform.addRowSetToOutputRowSets(outputRowSet);
-
- StringOperationsMeta meta = mockTransformMeta();
- StringOperationsData data = mockTransformData();
-
- transform.init();
-
- boolean processResult;
-
- do {
- processResult = transform.init();
- } while (processResult);
-
- assertTrue(outputRowSet.isDone());
-
- assertTrue(verifyOutput(new Object[][] {{"Value"}}, outputRowSet),
"Unexpected output");
- }
-}
diff --git
a/plugins/transforms/stringoperations/src/test/resources/transform.xml
b/plugins/transforms/stringoperations/src/test/resources/transform.xml
new file mode 100644
index 0000000000..341862b96b
--- /dev/null
+++ b/plugins/transforms/stringoperations/src/test/resources/transform.xml
@@ -0,0 +1,74 @@
+<!--
+ ~ 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>
+ <in_stream_name>desc_t</in_stream_name>
+ <out_stream_name>desc_trimmed</out_stream_name>
+ <trim_type>both</trim_type>
+ <lower_upper>none</lower_upper>
+ <padding_type>none</padding_type>
+ <pad_char/>
+ <pad_len/>
+ <init_cap>no</init_cap>
+ <mask_xml>none</mask_xml>
+ <digits>none</digits>
+ <remove_special_characters>none</remove_special_characters>
+ </field>
+ <field>
+ <in_stream_name>desc_u</in_stream_name>
+ <out_stream_name>desc_upper</out_stream_name>
+ <trim_type>none</trim_type>
+ <lower_upper>upper</lower_upper>
+ <padding_type>none</padding_type>
+ <pad_char/>
+ <pad_len/>
+ <init_cap>no</init_cap>
+ <mask_xml>none</mask_xml>
+ <digits>none</digits>
+ <remove_special_characters>none</remove_special_characters>
+ </field>
+ <field>
+ <in_stream_name>desc_p</in_stream_name>
+ <out_stream_name>desc_padded</out_stream_name>
+ <trim_type>none</trim_type>
+ <lower_upper>none</lower_upper>
+ <padding_type>left</padding_type>
+ <pad_char>#</pad_char>
+ <pad_len>25</pad_len>
+ <init_cap>no</init_cap>
+ <mask_xml>none</mask_xml>
+ <digits>none</digits>
+ <remove_special_characters>none</remove_special_characters>
+ </field>
+ <field>
+ <in_stream_name>desc_i</in_stream_name>
+ <out_stream_name>desc_initcapped</out_stream_name>
+ <trim_type>none</trim_type>
+ <lower_upper>none</lower_upper>
+ <padding_type>none</padding_type>
+ <pad_char/>
+ <pad_len/>
+ <init_cap>yes</init_cap>
+ <mask_xml>none</mask_xml>
+ <digits>none</digits>
+ <remove_special_characters>none</remove_special_characters>
+ </field>
+ </fields>
+</transform>
diff --git
a/plugins/transforms/stringoperations/src/test/resources/transform2.xml
b/plugins/transforms/stringoperations/src/test/resources/transform2.xml
new file mode 100644
index 0000000000..7d4caaf9bc
--- /dev/null
+++ b/plugins/transforms/stringoperations/src/test/resources/transform2.xml
@@ -0,0 +1,35 @@
+<!--
+ ~ 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>
+ <in_stream_name>in_field</in_stream_name>
+ <out_stream_name>out_field</out_stream_name>
+ <trim_type>both</trim_type>
+ <lower_upper>upper</lower_upper>
+ <padding_type>right</padding_type>
+ <pad_char> </pad_char>
+ <pad_len>20</pad_len>
+ <init_cap>yes</init_cap>
+ <mask_xml>unescapexml</mask_xml>
+ <digits>remove_digits</digits>
+ <remove_special_characters>crlf</remove_special_characters>
+ </field>
+ </fields>
+</transform>
\ No newline at end of file