You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@hop.apache.org by ha...@apache.org on 2026/03/19 07:26:51 UTC
(hop) branch main updated: Issue 1874 (#6824)
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 a6c41ebd0f Issue 1874 (#6824)
a6c41ebd0f is described below
commit a6c41ebd0fb613cbbbb84b4045a1fc208133cb4a
Author: Matt Casters <ma...@gmail.com>
AuthorDate: Thu Mar 19 08:26:46 2026 +0100
Issue 1874 (#6824)
* Issues #1874 (JavaScript XML cleanup, MDI test, warning fixes, removed "added classes", added script type injection option)
* Issues #1874 (JavaScript XML cleanup, MDI test, warning fixes, removed "added classes", added script type injection option)
* Issues #1874 (warning fixes)
* Issues #1874 (warning fixes)
---
integration-tests/mdi/0043-javascript-template.hpl | 74 ++
integration-tests/mdi/0043-javascript-validate.hpl | 420 ++++++++++
integration-tests/mdi/0043-javascript.hpl | 426 ++++++++++
.../mdi/datasets/golden-javascript-fields.csv | 4 +
.../mdi/datasets/golden-javascript-scripts.csv | 4 +
.../mdi/datasets/golden-javascript.csv | 2 +
integration-tests/mdi/files/javascript.xml | 65 ++
integration-tests/mdi/main-0043-javascript.hwf | 113 +++
integration-tests/mdi/main-0087-javascript.hwf | 58 ++
.../metadata/dataset/golden-javascript-fields.json | 56 ++
.../dataset/golden-javascript-scripts.json | 32 +
.../mdi/metadata/dataset/golden-javascript.json | 16 +
.../unit-test/0043-javascript-validate UNIT.json | 82 ++
.../transforms/0087-javascript-basics.hpl | 215 +++++
.../datasets/golden-javascript-basic.csv | 11 +
.../transforms/main-0087-javascript.hwf | 162 ++++
.../metadata/dataset/golden-javascript-basic.json | 48 ++
.../unit-test/0087-javascript-basics UNIT.json | 44 ++
.../transforms/javascript/ScriptValues.java | 391 +++++----
.../javascript/ScriptValuesAddedFunctions.java | 5 +-
.../transforms/javascript/ScriptValuesData.java | 4 +-
.../transforms/javascript/ScriptValuesDialog.java | 176 ++---
.../transforms/javascript/ScriptValuesMeta.java | 877 +++++++--------------
.../transforms/javascript/ScriptValuesScript.java | 88 +--
.../javascript/messages/messages_en_US.properties | 1 +
.../javascript/ScriptValuesMetaInjectionTest.java | 106 ---
.../javascript/ScriptValuesMetaTest.java | 251 ++----
.../transforms/javascript/ScriptValuesTest.java | 59 +-
.../javascript/src/test/resources/javascript.xml | 65 ++
29 files changed, 2551 insertions(+), 1304 deletions(-)
diff --git a/integration-tests/mdi/0043-javascript-template.hpl b/integration-tests/mdi/0043-javascript-template.hpl
new file mode 100644
index 0000000000..374d386de0
--- /dev/null
+++ b/integration-tests/mdi/0043-javascript-template.hpl
@@ -0,0 +1,74 @@
+<?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>0043-javascript-template</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/18 15:31:56.005</created_date>
+ <modified_user>-</modified_user>
+ <modified_date>2026/03/18 15:31:56.005</modified_date>
+ </info>
+ <notepads>
+ </notepads>
+ <order>
+ </order>
+ <transform>
+ <name>JavaScript</name>
+ <type>ScriptValueMod</type>
+ <description/>
+ <distribute>Y</distribute>
+ <custom_distribution/>
+ <copies>1</copies>
+ <partitioning>
+ <method>none</method>
+ <schema_name/>
+ </partitioning>
+ <fields>
+</fields>
+ <jsScripts>
+ <jsScript>
+ <jsScript_name>Script 1</jsScript_name>
+ <jsScript_script>//Script here
+
+</jsScript_script>
+ <jsScript_type>0</jsScript_type>
+ </jsScript>
+ </jsScripts>
+ <optimizationLevel>9</optimizationLevel>
+ <attributes/>
+ <GUI>
+ <xloc>128</xloc>
+ <yloc>96</yloc>
+ </GUI>
+ </transform>
+ <transform_error_handling>
+ </transform_error_handling>
+ <attributes/>
+</pipeline>
diff --git a/integration-tests/mdi/0043-javascript-validate.hpl b/integration-tests/mdi/0043-javascript-validate.hpl
new file mode 100644
index 0000000000..cb46027215
--- /dev/null
+++ b/integration-tests/mdi/0043-javascript-validate.hpl
@@ -0,0 +1,420 @@
+<?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>0043-javascript-validate</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/18 17:22:17.510</created_date>
+ <modified_user>-</modified_user>
+ <modified_date>2026/03/18 17:22:17.510</modified_date>
+ </info>
+ <notepads>
+ </notepads>
+ <order>
+ <hop>
+ <from>/tmp/javascript.hpl</from>
+ <to>validate</to>
+ <enabled>Y</enabled>
+ </hop>
+ <hop>
+ <from>/tmp/javascript.hpl scripts</from>
+ <to>validate scripts</to>
+ <enabled>Y</enabled>
+ </hop>
+ <hop>
+ <from>/tmp/javascript.hpl fields</from>
+ <to>validate fields</to>
+ <enabled>Y</enabled>
+ </hop>
+ </order>
+ <transform>
+ <name>/tmp/javascript.hpl</name>
+ <type>getXMLData</type>
+ <description/>
+ <distribute>Y</distribute>
+ <custom_distribution/>
+ <copies>1</copies>
+ <partitioning>
+ <method>none</method>
+ <schema_name/>
+ </partitioning>
+ <IsAFile>N</IsAFile>
+ <IsIgnoreEmptyFile>N</IsIgnoreEmptyFile>
+ <IsInFields>N</IsInFields>
+ <XmlField/>
+ <addresultfile>N</addresultfile>
+ <doNotFailIfNoFile>Y</doNotFailIfNoFile>
+ <encoding>UTF-8</encoding>
+ <extensionFieldName/>
+ <fields>
+ <field>
+ <currency/>
+ <decimal/>
+ <element_type>Node</element_type>
+ <format/>
+ <group/>
+ <length>-1</length>
+ <name>optimizationLevel</name>
+ <precision>-1</precision>
+ <repeat>N</repeat>
+ <result_type>valueof</result_type>
+ <trim_type>none</trim_type>
+ <type>Integer</type>
+ <xPath>optimizationLevel</xPath>
+ </field>
+ </fields>
+ <file>
+ <exclude_filemask/>
+ <file_required>N</file_required>
+ <filemask/>
+ <include_subfolders>N</include_subfolders>
+ <name>${java.io.tmpdir}/javascript.hpl</name>
+ </file>
+ <hiddenFieldName/>
+ <ignorecomments>N</ignorecomments>
+ <include>N</include>
+ <include_field/>
+ <lastModificationTimeFieldName/>
+ <limit>0</limit>
+ <loopxpath>/pipeline/transform</loopxpath>
+ <namespaceaware>N</namespaceaware>
+ <pathFieldName/>
+ <prunePath/>
+ <readurl>N</readurl>
+ <rootUriNameFieldName/>
+ <rownum>N</rownum>
+ <rownum_field/>
+ <shortFileFieldName/>
+ <sizeFieldName/>
+ <uriNameFieldName/>
+ <usetoken>N</usetoken>
+ <validating>N</validating>
+ <attributes/>
+ <GUI>
+ <xloc>96</xloc>
+ <yloc>48</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>384</xloc>
+ <yloc>48</yloc>
+ </GUI>
+ </transform>
+ <transform>
+ <name>/tmp/javascript.hpl scripts</name>
+ <type>getXMLData</type>
+ <description/>
+ <distribute>Y</distribute>
+ <custom_distribution/>
+ <copies>1</copies>
+ <partitioning>
+ <method>none</method>
+ <schema_name/>
+ </partitioning>
+ <IsAFile>N</IsAFile>
+ <IsIgnoreEmptyFile>N</IsIgnoreEmptyFile>
+ <IsInFields>N</IsInFields>
+ <XmlField/>
+ <addresultfile>N</addresultfile>
+ <doNotFailIfNoFile>Y</doNotFailIfNoFile>
+ <encoding>UTF-8</encoding>
+ <extensionFieldName/>
+ <fields>
+ <field>
+ <currency/>
+ <decimal/>
+ <element_type>Node</element_type>
+ <format/>
+ <group/>
+ <length>-1</length>
+ <name>jsScript_type</name>
+ <precision>-1</precision>
+ <repeat>N</repeat>
+ <result_type>valueof</result_type>
+ <trim_type>none</trim_type>
+ <type>Integer</type>
+ <xPath>jsScript_type</xPath>
+ </field>
+ <field>
+ <currency/>
+ <decimal/>
+ <element_type>Node</element_type>
+ <format/>
+ <group/>
+ <length>-1</length>
+ <name>jsScript_name</name>
+ <precision>-1</precision>
+ <repeat>N</repeat>
+ <result_type>valueof</result_type>
+ <trim_type>none</trim_type>
+ <type>String</type>
+ <xPath>jsScript_name</xPath>
+ </field>
+ <field>
+ <currency/>
+ <decimal/>
+ <element_type>Node</element_type>
+ <format/>
+ <group/>
+ <length>-1</length>
+ <name>jsScript_script</name>
+ <precision>-1</precision>
+ <repeat>N</repeat>
+ <result_type>valueof</result_type>
+ <trim_type>none</trim_type>
+ <type>String</type>
+ <xPath>jsScript_script</xPath>
+ </field>
+ </fields>
+ <file>
+ <exclude_filemask/>
+ <file_required>N</file_required>
+ <filemask/>
+ <include_subfolders>N</include_subfolders>
+ <name>${java.io.tmpdir}/javascript.hpl</name>
+ </file>
+ <hiddenFieldName/>
+ <ignorecomments>N</ignorecomments>
+ <include>N</include>
+ <include_field/>
+ <lastModificationTimeFieldName/>
+ <limit>0</limit>
+ <loopxpath>/pipeline/transform/jsScripts/jsScript</loopxpath>
+ <namespaceaware>N</namespaceaware>
+ <pathFieldName/>
+ <prunePath/>
+ <readurl>N</readurl>
+ <rootUriNameFieldName/>
+ <rownum>N</rownum>
+ <rownum_field/>
+ <shortFileFieldName/>
+ <sizeFieldName/>
+ <uriNameFieldName/>
+ <usetoken>N</usetoken>
+ <validating>N</validating>
+ <attributes/>
+ <GUI>
+ <xloc>96</xloc>
+ <yloc>128</yloc>
+ </GUI>
+ </transform>
+ <transform>
+ <name>validate scripts</name>
+ <type>Dummy</type>
+ <description/>
+ <distribute>Y</distribute>
+ <custom_distribution/>
+ <copies>1</copies>
+ <partitioning>
+ <method>none</method>
+ <schema_name/>
+ </partitioning>
+ <attributes/>
+ <GUI>
+ <xloc>384</xloc>
+ <yloc>128</yloc>
+ </GUI>
+ </transform>
+ <transform>
+ <name>/tmp/javascript.hpl fields</name>
+ <type>getXMLData</type>
+ <description/>
+ <distribute>Y</distribute>
+ <custom_distribution/>
+ <copies>1</copies>
+ <partitioning>
+ <method>none</method>
+ <schema_name/>
+ </partitioning>
+ <IsAFile>N</IsAFile>
+ <IsIgnoreEmptyFile>N</IsIgnoreEmptyFile>
+ <IsInFields>N</IsInFields>
+ <XmlField/>
+ <addresultfile>N</addresultfile>
+ <doNotFailIfNoFile>Y</doNotFailIfNoFile>
+ <encoding>UTF-8</encoding>
+ <extensionFieldName/>
+ <fields>
+ <field>
+ <currency/>
+ <decimal/>
+ <element_type>Node</element_type>
+ <format/>
+ <group/>
+ <length>-1</length>
+ <name>name</name>
+ <precision>-1</precision>
+ <repeat>N</repeat>
+ <result_type>valueof</result_type>
+ <trim_type>none</trim_type>
+ <type>String</type>
+ <xPath>name</xPath>
+ </field>
+ <field>
+ <currency/>
+ <decimal/>
+ <element_type>Node</element_type>
+ <format/>
+ <group/>
+ <length>-1</length>
+ <name>rename</name>
+ <precision>-1</precision>
+ <repeat>N</repeat>
+ <result_type>valueof</result_type>
+ <trim_type>none</trim_type>
+ <type>String</type>
+ <xPath>rename</xPath>
+ </field>
+ <field>
+ <currency/>
+ <decimal/>
+ <element_type>Node</element_type>
+ <format/>
+ <group/>
+ <length>-1</length>
+ <name>type</name>
+ <precision>-1</precision>
+ <repeat>N</repeat>
+ <result_type>valueof</result_type>
+ <trim_type>none</trim_type>
+ <type>String</type>
+ <xPath>type</xPath>
+ </field>
+ <field>
+ <currency/>
+ <decimal/>
+ <element_type>Node</element_type>
+ <format/>
+ <group/>
+ <length>-1</length>
+ <name>length</name>
+ <precision>-1</precision>
+ <repeat>N</repeat>
+ <result_type>valueof</result_type>
+ <trim_type>none</trim_type>
+ <type>Integer</type>
+ <xPath>length</xPath>
+ </field>
+ <field>
+ <currency/>
+ <decimal/>
+ <element_type>Node</element_type>
+ <format/>
+ <group/>
+ <length>-1</length>
+ <name>precision</name>
+ <precision>-1</precision>
+ <repeat>N</repeat>
+ <result_type>valueof</result_type>
+ <trim_type>none</trim_type>
+ <type>Integer</type>
+ <xPath>precision</xPath>
+ </field>
+ <field>
+ <currency/>
+ <decimal/>
+ <element_type>Node</element_type>
+ <format/>
+ <group/>
+ <length>-1</length>
+ <name>replace</name>
+ <precision>-1</precision>
+ <repeat>N</repeat>
+ <result_type>valueof</result_type>
+ <trim_type>none</trim_type>
+ <type>String</type>
+ <xPath>replace</xPath>
+ </field>
+ </fields>
+ <file>
+ <exclude_filemask/>
+ <file_required>N</file_required>
+ <filemask/>
+ <include_subfolders>N</include_subfolders>
+ <name>${java.io.tmpdir}/javascript.hpl</name>
+ </file>
+ <hiddenFieldName/>
+ <ignorecomments>N</ignorecomments>
+ <include>N</include>
+ <include_field/>
+ <lastModificationTimeFieldName/>
+ <limit>0</limit>
+ <loopxpath>/pipeline/transform/fields/field</loopxpath>
+ <namespaceaware>N</namespaceaware>
+ <pathFieldName/>
+ <prunePath/>
+ <readurl>N</readurl>
+ <rootUriNameFieldName/>
+ <rownum>N</rownum>
+ <rownum_field/>
+ <shortFileFieldName/>
+ <sizeFieldName/>
+ <uriNameFieldName/>
+ <usetoken>N</usetoken>
+ <validating>N</validating>
+ <attributes/>
+ <GUI>
+ <xloc>96</xloc>
+ <yloc>208</yloc>
+ </GUI>
+ </transform>
+ <transform>
+ <name>validate fields</name>
+ <type>Dummy</type>
+ <description/>
+ <distribute>Y</distribute>
+ <custom_distribution/>
+ <copies>1</copies>
+ <partitioning>
+ <method>none</method>
+ <schema_name/>
+ </partitioning>
+ <attributes/>
+ <GUI>
+ <xloc>384</xloc>
+ <yloc>208</yloc>
+ </GUI>
+ </transform>
+ <transform_error_handling>
+ </transform_error_handling>
+ <attributes/>
+</pipeline>
diff --git a/integration-tests/mdi/0043-javascript.hpl b/integration-tests/mdi/0043-javascript.hpl
new file mode 100644
index 0000000000..a2cb08b380
--- /dev/null
+++ b/integration-tests/mdi/0043-javascript.hpl
@@ -0,0 +1,426 @@
+<?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>0043-javascript</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/18 17:15:02.536</created_date>
+ <modified_user>-</modified_user>
+ <modified_date>2026/03/18 17:15:02.536</modified_date>
+ </info>
+ <notepads>
+ </notepads>
+ <order>
+ <hop>
+ <from>files/javascript.xml</from>
+ <to>/tmp/0043-javascript-template.hpl</to>
+ <enabled>Y</enabled>
+ </hop>
+ <hop>
+ <from>files/javascript.xml scripts</from>
+ <to>/tmp/0043-javascript-template.hpl</to>
+ <enabled>Y</enabled>
+ </hop>
+ <hop>
+ <from>files/javascript.xml fields</from>
+ <to>/tmp/0043-javascript-template.hpl</to>
+ <enabled>Y</enabled>
+ </hop>
+ </order>
+ <transform>
+ <name>/tmp/0043-javascript-template.hpl</name>
+ <type>MetaInject</type>
+ <description/>
+ <distribute>Y</distribute>
+ <custom_distribution/>
+ <copies>1</copies>
+ <partitioning>
+ <method>none</method>
+ <schema_name/>
+ </partitioning>
+ <filename>${PROJECT_HOME}/0043-javascript-template.hpl</filename>
+ <run_configuration>local</run_configuration>
+ <source_transform/>
+ <source_output_fields> </source_output_fields>
+ <target_file>${java.io.tmpdir}/javascript.hpl</target_file>
+ <create_parent_folder>Y</create_parent_folder>
+ <no_execution>Y</no_execution>
+ <allow_empty_stream_on_execution>N</allow_empty_stream_on_execution>
+ <stream_source_transform/>
+ <stream_target_transform/>
+ <mappings>
+ <mapping>
+ <target_transform_name>JavaScript</target_transform_name>
+ <target_attribute_key>SCRIPT_NAME</target_attribute_key>
+ <target_detail>Y</target_detail>
+ <source_transform>files/javascript.xml scripts</source_transform>
+ <source_field>jsScript_name</source_field>
+ </mapping>
+ <mapping>
+ <target_transform_name>JavaScript</target_transform_name>
+ <target_attribute_key>SCRIPT_TYPE</target_attribute_key>
+ <target_detail>Y</target_detail>
+ <source_transform>files/javascript.xml scripts</source_transform>
+ <source_field>jsScript_type</source_field>
+ </mapping>
+ <mapping>
+ <target_transform_name>JavaScript</target_transform_name>
+ <target_attribute_key>FIELD_PRECISION</target_attribute_key>
+ <target_detail>Y</target_detail>
+ <source_transform>files/javascript.xml fields</source_transform>
+ <source_field>precision</source_field>
+ </mapping>
+ <mapping>
+ <target_transform_name>JavaScript</target_transform_name>
+ <target_attribute_key>SCRIPT</target_attribute_key>
+ <target_detail>Y</target_detail>
+ <source_transform>files/javascript.xml scripts</source_transform>
+ <source_field>jsScript_script</source_field>
+ </mapping>
+ <mapping>
+ <target_transform_name>JavaScript</target_transform_name>
+ <target_attribute_key>FIELD_RENAME_TO</target_attribute_key>
+ <target_detail>Y</target_detail>
+ <source_transform>files/javascript.xml fields</source_transform>
+ <source_field>rename</source_field>
+ </mapping>
+ <mapping>
+ <target_transform_name>JavaScript</target_transform_name>
+ <target_attribute_key>FIELD_TYPE</target_attribute_key>
+ <target_detail>Y</target_detail>
+ <source_transform>files/javascript.xml fields</source_transform>
+ <source_field>type</source_field>
+ </mapping>
+ <mapping>
+ <target_transform_name>JavaScript</target_transform_name>
+ <target_attribute_key>FIELD_LENGTH</target_attribute_key>
+ <target_detail>Y</target_detail>
+ <source_transform>files/javascript.xml fields</source_transform>
+ <source_field>length</source_field>
+ </mapping>
+ <mapping>
+ <target_transform_name>JavaScript</target_transform_name>
+ <target_attribute_key>FIELD_REPLACE</target_attribute_key>
+ <target_detail>Y</target_detail>
+ <source_transform>files/javascript.xml fields</source_transform>
+ <source_field>replace</source_field>
+ </mapping>
+ <mapping>
+ <target_transform_name>JavaScript</target_transform_name>
+ <target_attribute_key>FIELD_NAME</target_attribute_key>
+ <target_detail>Y</target_detail>
+ <source_transform>files/javascript.xml fields</source_transform>
+ <source_field>name</source_field>
+ </mapping>
+ <mapping>
+ <target_transform_name>JavaScript</target_transform_name>
+ <target_attribute_key>OPTIMIZATION_LEVEL</target_attribute_key>
+ <target_detail>N</target_detail>
+ <source_transform>files/javascript.xml</source_transform>
+ <source_field>optimizationLevel</source_field>
+ </mapping>
+ </mappings>
+ <attributes/>
+ <GUI>
+ <xloc>416</xloc>
+ <yloc>48</yloc>
+ </GUI>
+ </transform>
+ <transform>
+ <name>files/javascript.xml</name>
+ <type>getXMLData</type>
+ <description/>
+ <distribute>Y</distribute>
+ <custom_distribution/>
+ <copies>1</copies>
+ <partitioning>
+ <method>none</method>
+ <schema_name/>
+ </partitioning>
+ <IsAFile>N</IsAFile>
+ <IsIgnoreEmptyFile>N</IsIgnoreEmptyFile>
+ <IsInFields>N</IsInFields>
+ <addresultfile>N</addresultfile>
+ <doNotFailIfNoFile>Y</doNotFailIfNoFile>
+ <encoding>UTF-8</encoding>
+ <fields>
+ <field>
+ <currency/>
+ <decimal/>
+ <element_type>Node</element_type>
+ <format/>
+ <group/>
+ <length>-1</length>
+ <name>optimizationLevel</name>
+ <precision>-1</precision>
+ <repeat>N</repeat>
+ <result_type>valueof</result_type>
+ <trim_type>none</trim_type>
+ <type>String</type>
+ <xPath>optimizationLevel</xPath>
+ </field>
+ </fields>
+ <file>
+ <file_required>N</file_required>
+ <include_subfolders>N</include_subfolders>
+ <name>${PROJECT_HOME}/files/javascript.xml</name>
+ </file>
+ <ignorecomments>N</ignorecomments>
+ <include>N</include>
+ <limit>0</limit>
+ <loopxpath>/transform</loopxpath>
+ <namespaceaware>N</namespaceaware>
+ <readurl>N</readurl>
+ <rownum>N</rownum>
+ <usetoken>N</usetoken>
+ <validating>N</validating>
+ <attributes/>
+ <GUI>
+ <xloc>96</xloc>
+ <yloc>48</yloc>
+ </GUI>
+ </transform>
+ <transform>
+ <name>files/javascript.xml fields</name>
+ <type>getXMLData</type>
+ <description/>
+ <distribute>Y</distribute>
+ <custom_distribution/>
+ <copies>1</copies>
+ <partitioning>
+ <method>none</method>
+ <schema_name/>
+ </partitioning>
+ <IsAFile>N</IsAFile>
+ <IsIgnoreEmptyFile>N</IsIgnoreEmptyFile>
+ <IsInFields>N</IsInFields>
+ <addresultfile>N</addresultfile>
+ <doNotFailIfNoFile>Y</doNotFailIfNoFile>
+ <encoding>UTF-8</encoding>
+ <fields>
+ <field>
+ <currency/>
+ <decimal/>
+ <element_type>Node</element_type>
+ <format/>
+ <group/>
+ <length>-1</length>
+ <name>name</name>
+ <precision>-1</precision>
+ <repeat>N</repeat>
+ <result_type>valueof</result_type>
+ <trim_type>none</trim_type>
+ <type>String</type>
+ <xPath>name</xPath>
+ </field>
+ <field>
+ <currency/>
+ <decimal/>
+ <element_type>Node</element_type>
+ <format/>
+ <group/>
+ <length>-1</length>
+ <name>rename</name>
+ <precision>-1</precision>
+ <repeat>N</repeat>
+ <result_type>valueof</result_type>
+ <trim_type>none</trim_type>
+ <type>String</type>
+ <xPath>rename</xPath>
+ </field>
+ <field>
+ <currency/>
+ <decimal/>
+ <element_type>Node</element_type>
+ <format/>
+ <group/>
+ <length>-1</length>
+ <name>type</name>
+ <precision>-1</precision>
+ <repeat>N</repeat>
+ <result_type>valueof</result_type>
+ <trim_type>none</trim_type>
+ <type>String</type>
+ <xPath>type</xPath>
+ </field>
+ <field>
+ <currency/>
+ <decimal/>
+ <element_type>Node</element_type>
+ <format/>
+ <group/>
+ <length>-1</length>
+ <name>length</name>
+ <precision>-1</precision>
+ <repeat>N</repeat>
+ <result_type>valueof</result_type>
+ <trim_type>none</trim_type>
+ <type>Integer</type>
+ <xPath>length</xPath>
+ </field>
+ <field>
+ <currency/>
+ <decimal/>
+ <element_type>Node</element_type>
+ <format/>
+ <group/>
+ <length>-1</length>
+ <name>precision</name>
+ <precision>-1</precision>
+ <repeat>N</repeat>
+ <result_type>valueof</result_type>
+ <trim_type>none</trim_type>
+ <type>Integer</type>
+ <xPath>precision</xPath>
+ </field>
+ <field>
+ <currency/>
+ <decimal/>
+ <element_type>Node</element_type>
+ <format/>
+ <group/>
+ <length>-1</length>
+ <name>replace</name>
+ <precision>-1</precision>
+ <repeat>N</repeat>
+ <result_type>valueof</result_type>
+ <trim_type>none</trim_type>
+ <type>String</type>
+ <xPath>replace</xPath>
+ </field>
+ </fields>
+ <file>
+ <file_required>N</file_required>
+ <include_subfolders>N</include_subfolders>
+ <name>${PROJECT_HOME}/files/javascript.xml</name>
+ </file>
+ <ignorecomments>N</ignorecomments>
+ <include>N</include>
+ <limit>0</limit>
+ <loopxpath>/transform/fields/field</loopxpath>
+ <namespaceaware>N</namespaceaware>
+ <readurl>N</readurl>
+ <rownum>N</rownum>
+ <usetoken>N</usetoken>
+ <validating>N</validating>
+ <attributes/>
+ <GUI>
+ <xloc>96</xloc>
+ <yloc>128</yloc>
+ </GUI>
+ </transform>
+ <transform>
+ <name>files/javascript.xml scripts</name>
+ <type>getXMLData</type>
+ <description/>
+ <distribute>Y</distribute>
+ <custom_distribution/>
+ <copies>1</copies>
+ <partitioning>
+ <method>none</method>
+ <schema_name/>
+ </partitioning>
+ <IsAFile>N</IsAFile>
+ <IsIgnoreEmptyFile>N</IsIgnoreEmptyFile>
+ <IsInFields>N</IsInFields>
+ <addresultfile>N</addresultfile>
+ <doNotFailIfNoFile>Y</doNotFailIfNoFile>
+ <encoding>UTF-8</encoding>
+ <fields>
+ <field>
+ <currency/>
+ <decimal/>
+ <element_type>Node</element_type>
+ <format/>
+ <group/>
+ <length>-1</length>
+ <name>jsScript_type</name>
+ <precision>-1</precision>
+ <repeat>N</repeat>
+ <result_type>valueof</result_type>
+ <trim_type>none</trim_type>
+ <type>Integer</type>
+ <xPath>jsScript_type</xPath>
+ </field>
+ <field>
+ <currency/>
+ <decimal/>
+ <element_type>Node</element_type>
+ <format/>
+ <group/>
+ <length>-1</length>
+ <name>jsScript_name</name>
+ <precision>-1</precision>
+ <repeat>N</repeat>
+ <result_type>valueof</result_type>
+ <trim_type>none</trim_type>
+ <type>String</type>
+ <xPath>jsScript_name</xPath>
+ </field>
+ <field>
+ <currency/>
+ <decimal/>
+ <element_type>Node</element_type>
+ <format/>
+ <group/>
+ <length>-1</length>
+ <name>jsScript_script</name>
+ <precision>-1</precision>
+ <repeat>N</repeat>
+ <result_type>valueof</result_type>
+ <trim_type>none</trim_type>
+ <type>String</type>
+ <xPath>jsScript_script</xPath>
+ </field>
+ </fields>
+ <file>
+ <file_required>N</file_required>
+ <include_subfolders>N</include_subfolders>
+ <name>${PROJECT_HOME}/files/javascript.xml</name>
+ </file>
+ <ignorecomments>N</ignorecomments>
+ <include>N</include>
+ <limit>0</limit>
+ <loopxpath>/transform/jsScripts/jsScript</loopxpath>
+ <namespaceaware>N</namespaceaware>
+ <readurl>N</readurl>
+ <rownum>N</rownum>
+ <usetoken>N</usetoken>
+ <validating>N</validating>
+ <attributes/>
+ <GUI>
+ <xloc>96</xloc>
+ <yloc>208</yloc>
+ </GUI>
+ </transform>
+ <transform_error_handling>
+ </transform_error_handling>
+ <attributes/>
+</pipeline>
diff --git a/integration-tests/mdi/datasets/golden-javascript-fields.csv b/integration-tests/mdi/datasets/golden-javascript-fields.csv
new file mode 100644
index 0000000000..47ef304fe0
--- /dev/null
+++ b/integration-tests/mdi/datasets/golden-javascript-fields.csv
@@ -0,0 +1,4 @@
+name,rename,type,length,precision,replace
+f1,renamedF1,String,100,-1,Y
+f2,renamedF2,Integer,7,-1,Y
+f3,renamedF3,Number,9,2,Y
diff --git a/integration-tests/mdi/datasets/golden-javascript-scripts.csv b/integration-tests/mdi/datasets/golden-javascript-scripts.csv
new file mode 100644
index 0000000000..215e1d1c6e
--- /dev/null
+++ b/integration-tests/mdi/datasets/golden-javascript-scripts.csv
@@ -0,0 +1,4 @@
+jsScript_type,jsScript_name,jsScript_script
+1,startScript,startScript
+0,transformScript,transformScript
+2,endScript,endScript
diff --git a/integration-tests/mdi/datasets/golden-javascript.csv b/integration-tests/mdi/datasets/golden-javascript.csv
new file mode 100644
index 0000000000..28a22d82f2
--- /dev/null
+++ b/integration-tests/mdi/datasets/golden-javascript.csv
@@ -0,0 +1,2 @@
+optimizationLevel
+2
diff --git a/integration-tests/mdi/files/javascript.xml b/integration-tests/mdi/files/javascript.xml
new file mode 100644
index 0000000000..964c6d5e31
--- /dev/null
+++ b/integration-tests/mdi/files/javascript.xml
@@ -0,0 +1,65 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+ ~ Licensed to the Apache Software Foundation (ASF) under one or more
+ ~ contributor license agreements. See the NOTICE file distributed with
+ ~ this work for additional information regarding copyright ownership.
+ ~ The ASF licenses this file to You under the Apache License, Version 2.0
+ ~ (the "License"); you may not use this file except in compliance with
+ ~ the License. You may obtain a copy of the License at
+ ~
+ ~ http://www.apache.org/licenses/LICENSE-2.0
+ ~
+ ~ Unless required by applicable law or agreed to in writing, software
+ ~ distributed under the License is distributed on an "AS IS" BASIS,
+ ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ ~ See the License for the specific language governing permissions and
+ ~ limitations under the License.
+ ~
+ -->
+
+<transform>
+ <optimizationLevel>2</optimizationLevel>
+ <jsScripts>
+ <jsScript>
+ <jsScript_type>1</jsScript_type>
+ <jsScript_name>startScript</jsScript_name>
+ <jsScript_script>startScript</jsScript_script>
+ </jsScript>
+ <jsScript>
+ <jsScript_type>0</jsScript_type>
+ <jsScript_name>transformScript</jsScript_name>
+ <jsScript_script>transformScript</jsScript_script>
+ </jsScript>
+ <jsScript>
+ <jsScript_type>2</jsScript_type>
+ <jsScript_name>endScript</jsScript_name>
+ <jsScript_script>endScript</jsScript_script>
+ </jsScript>
+ </jsScripts>
+ <fields>
+ <field>
+ <name>f1</name>
+ <rename>renamedF1</rename>
+ <type>String</type>
+ <length>100</length>
+ <precision>-1</precision>
+ <replace>Y</replace>
+ </field>
+ <field>
+ <name>f2</name>
+ <rename>renamedF2</rename>
+ <type>Integer</type>
+ <length>7</length>
+ <precision>-1</precision>
+ <replace>Y</replace>
+ </field>
+ <field>
+ <name>f3</name>
+ <rename>renamedF3</rename>
+ <type>Number</type>
+ <length>9</length>
+ <precision>2</precision>
+ <replace>Y</replace>
+ </field>
+ </fields>
+</transform>
diff --git a/integration-tests/mdi/main-0043-javascript.hwf b/integration-tests/mdi/main-0043-javascript.hwf
new file mode 100644
index 0000000000..099298b6b0
--- /dev/null
+++ b/integration-tests/mdi/main-0043-javascript.hwf
@@ -0,0 +1,113 @@
+<?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-0043-javascript</name>
+ <name_sync_with_filename>Y</name_sync_with_filename>
+ <description/>
+ <extended_description/>
+ <workflow_version/>
+ <created_user>-</created_user>
+ <created_date>2026/03/18 15:31:43.347</created_date>
+ <modified_user>-</modified_user>
+ <modified_date>2026/03/18 15:31:43.347</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>0043-javascript</name>
+ <description/>
+ <type>PIPELINE</type>
+ <attributes/>
+ <add_date>N</add_date>
+ <add_time>N</add_time>
+ <clear_files>N</clear_files>
+ <clear_rows>N</clear_rows>
+ <create_parent_folder>N</create_parent_folder>
+ <exec_per_row>N</exec_per_row>
+ <filename>${PROJECT_HOME}/0043-javascript.hpl</filename>
+ <loglevel>Basic</loglevel>
+ <parameters>
+ <pass_all_parameters>Y</pass_all_parameters>
+ </parameters>
+ <params_from_previous>N</params_from_previous>
+ <run_configuration>local</run_configuration>
+ <set_append_logfile>N</set_append_logfile>
+ <set_logfile>N</set_logfile>
+ <wait_until_finished>Y</wait_until_finished>
+ <parallel>N</parallel>
+ <xloc>256</xloc>
+ <yloc>64</yloc>
+ <attributes_hac/>
+ </action>
+ <action>
+ <name>0043-javascript-validate UNIT</name>
+ <description/>
+ <type>RunPipelineTests</type>
+ <attributes/>
+ <test_names>
+ <test_name>
+ <name>0043-javascript-validate UNIT</name>
+ </test_name>
+ </test_names>
+ <parallel>N</parallel>
+ <xloc>416</xloc>
+ <yloc>64</yloc>
+ <attributes_hac/>
+ </action>
+ </actions>
+ <hops>
+ <hop>
+ <from>Start</from>
+ <to>0043-javascript</to>
+ <enabled>Y</enabled>
+ <evaluation>Y</evaluation>
+ <unconditional>Y</unconditional>
+ </hop>
+ <hop>
+ <from>0043-javascript</from>
+ <to>0043-javascript-validate UNIT</to>
+ <enabled>Y</enabled>
+ <evaluation>Y</evaluation>
+ <unconditional>N</unconditional>
+ </hop>
+ </hops>
+ <notepads>
+ </notepads>
+ <attributes/>
+</workflow>
diff --git a/integration-tests/mdi/main-0087-javascript.hwf b/integration-tests/mdi/main-0087-javascript.hwf
new file mode 100644
index 0000000000..207028173a
--- /dev/null
+++ b/integration-tests/mdi/main-0087-javascript.hwf
@@ -0,0 +1,58 @@
+<?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-0087-javascript</name>
+ <name_sync_with_filename>Y</name_sync_with_filename>
+ <description/>
+ <extended_description/>
+ <workflow_version/>
+ <created_user>-</created_user>
+ <created_date>2026/03/18 19:32:06.360</created_date>
+ <modified_user>-</modified_user>
+ <modified_date>2026/03/18 19:32:06.360</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>50</xloc>
+ <yloc>50</yloc>
+ <attributes_hac/>
+ </action>
+ </actions>
+ <hops>
+ </hops>
+ <notepads>
+ </notepads>
+ <attributes/>
+</workflow>
diff --git a/integration-tests/mdi/metadata/dataset/golden-javascript-fields.json b/integration-tests/mdi/metadata/dataset/golden-javascript-fields.json
new file mode 100644
index 0000000000..7fbb698719
--- /dev/null
+++ b/integration-tests/mdi/metadata/dataset/golden-javascript-fields.json
@@ -0,0 +1,56 @@
+{
+ "base_filename": "golden-javascript-fields.csv",
+ "name": "golden-javascript-fields",
+ "description": "",
+ "dataset_fields": [
+ {
+ "field_comment": "",
+ "field_length": -1,
+ "field_type": 2,
+ "field_precision": -1,
+ "field_name": "name",
+ "field_format": ""
+ },
+ {
+ "field_comment": "",
+ "field_length": -1,
+ "field_type": 2,
+ "field_precision": -1,
+ "field_name": "rename",
+ "field_format": ""
+ },
+ {
+ "field_comment": "",
+ "field_length": -1,
+ "field_type": 2,
+ "field_precision": -1,
+ "field_name": "type",
+ "field_format": ""
+ },
+ {
+ "field_comment": "",
+ "field_length": -1,
+ "field_type": 5,
+ "field_precision": 0,
+ "field_name": "length",
+ "field_format": "####0;-####0"
+ },
+ {
+ "field_comment": "",
+ "field_length": -1,
+ "field_type": 5,
+ "field_precision": 0,
+ "field_name": "precision",
+ "field_format": "####0;-####0"
+ },
+ {
+ "field_comment": "",
+ "field_length": -1,
+ "field_type": 2,
+ "field_precision": -1,
+ "field_name": "replace",
+ "field_format": ""
+ }
+ ],
+ "folder_name": ""
+}
\ No newline at end of file
diff --git a/integration-tests/mdi/metadata/dataset/golden-javascript-scripts.json b/integration-tests/mdi/metadata/dataset/golden-javascript-scripts.json
new file mode 100644
index 0000000000..e8812dbe4e
--- /dev/null
+++ b/integration-tests/mdi/metadata/dataset/golden-javascript-scripts.json
@@ -0,0 +1,32 @@
+{
+ "base_filename": "golden-javascript-scripts.csv",
+ "name": "golden-javascript-scripts",
+ "description": "",
+ "dataset_fields": [
+ {
+ "field_comment": "",
+ "field_length": -1,
+ "field_type": 5,
+ "field_precision": 0,
+ "field_name": "jsScript_type",
+ "field_format": "####0;-####0"
+ },
+ {
+ "field_comment": "",
+ "field_length": -1,
+ "field_type": 2,
+ "field_precision": -1,
+ "field_name": "jsScript_name",
+ "field_format": ""
+ },
+ {
+ "field_comment": "",
+ "field_length": -1,
+ "field_type": 2,
+ "field_precision": -1,
+ "field_name": "jsScript_script",
+ "field_format": ""
+ }
+ ],
+ "folder_name": ""
+}
\ No newline at end of file
diff --git a/integration-tests/mdi/metadata/dataset/golden-javascript.json b/integration-tests/mdi/metadata/dataset/golden-javascript.json
new file mode 100644
index 0000000000..56bbc6291a
--- /dev/null
+++ b/integration-tests/mdi/metadata/dataset/golden-javascript.json
@@ -0,0 +1,16 @@
+{
+ "base_filename": "golden-javascript.csv",
+ "name": "golden-javascript",
+ "description": "",
+ "dataset_fields": [
+ {
+ "field_comment": "",
+ "field_length": -1,
+ "field_type": 5,
+ "field_precision": 0,
+ "field_name": "optimizationLevel",
+ "field_format": "####0;-####0"
+ }
+ ],
+ "folder_name": ""
+}
\ No newline at end of file
diff --git a/integration-tests/mdi/metadata/unit-test/0043-javascript-validate UNIT.json b/integration-tests/mdi/metadata/unit-test/0043-javascript-validate UNIT.json
new file mode 100644
index 0000000000..be47231459
--- /dev/null
+++ b/integration-tests/mdi/metadata/unit-test/0043-javascript-validate UNIT.json
@@ -0,0 +1,82 @@
+{
+ "database_replacements": [],
+ "autoOpening": true,
+ "description": "",
+ "persist_filename": "",
+ "test_type": "UNIT_TEST",
+ "variableValues": [],
+ "basePath": "${HOP_UNIT_TESTS_FOLDER}",
+ "golden_data_sets": [
+ {
+ "field_mappings": [
+ {
+ "transform_field": "optimizationLevel",
+ "data_set_field": "optimizationLevel"
+ }
+ ],
+ "field_order": [
+ "optimizationLevel"
+ ],
+ "data_set_name": "golden-javascript",
+ "transform_name": "validate"
+ },
+ {
+ "field_mappings": [
+ {
+ "transform_field": "jsScript_type",
+ "data_set_field": "jsScript_type"
+ },
+ {
+ "transform_field": "jsScript_name",
+ "data_set_field": "jsScript_name"
+ },
+ {
+ "transform_field": "jsScript_script",
+ "data_set_field": "jsScript_script"
+ }
+ ],
+ "field_order": [
+ "jsScript_name"
+ ],
+ "data_set_name": "golden-javascript-scripts",
+ "transform_name": "validate scripts"
+ },
+ {
+ "field_mappings": [
+ {
+ "transform_field": "name",
+ "data_set_field": "name"
+ },
+ {
+ "transform_field": "rename",
+ "data_set_field": "rename"
+ },
+ {
+ "transform_field": "type",
+ "data_set_field": "type"
+ },
+ {
+ "transform_field": "length",
+ "data_set_field": "length"
+ },
+ {
+ "transform_field": "precision",
+ "data_set_field": "precision"
+ },
+ {
+ "transform_field": "replace",
+ "data_set_field": "replace"
+ }
+ ],
+ "field_order": [
+ "name"
+ ],
+ "data_set_name": "golden-javascript-fields",
+ "transform_name": "validate fields"
+ }
+ ],
+ "input_data_sets": [],
+ "name": "0043-javascript-validate UNIT",
+ "trans_test_tweaks": [],
+ "pipeline_filename": "./0043-javascript-validate.hpl"
+}
\ No newline at end of file
diff --git a/integration-tests/transforms/0087-javascript-basics.hpl b/integration-tests/transforms/0087-javascript-basics.hpl
new file mode 100644
index 0000000000..af9a8e3746
--- /dev/null
+++ b/integration-tests/transforms/0087-javascript-basics.hpl
@@ -0,0 +1,215 @@
+<?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>0087-javascript-basics</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/18 19:32:21.153</created_date>
+ <modified_user>-</modified_user>
+ <modified_date>2026/03/18 19:32:21.153</modified_date>
+ </info>
+ <notepads>
+ </notepads>
+ <order>
+ <hop>
+ <from>10 rows</from>
+ <to>nr</to>
+ <enabled>Y</enabled>
+ </hop>
+ <hop>
+ <from>nr</from>
+ <to>min,max,avg,sum</to>
+ <enabled>Y</enabled>
+ </hop>
+ <hop>
+ <from>min,max,avg,sum</from>
+ <to>validate</to>
+ <enabled>Y</enabled>
+ </hop>
+ </order>
+ <transform>
+ <name>10 rows</name>
+ <type>RowGenerator</type>
+ <description/>
+ <distribute>Y</distribute>
+ <custom_distribution/>
+ <copies>1</copies>
+ <partitioning>
+ <method>none</method>
+ <schema_name/>
+ </partitioning>
+ <fields>
+</fields>
+ <interval_in_ms>5000</interval_in_ms>
+ <last_time_field>FiveSecondsAgo</last_time_field>
+ <limit>10</limit>
+ <never_ending>N</never_ending>
+ <row_time_field>now</row_time_field>
+ <attributes/>
+ <GUI>
+ <xloc>96</xloc>
+ <yloc>80</yloc>
+ </GUI>
+ </transform>
+ <transform>
+ <name>min,max,avg,sum</name>
+ <type>ScriptValueMod</type>
+ <description/>
+ <distribute>Y</distribute>
+ <custom_distribution/>
+ <copies>1</copies>
+ <partitioning>
+ <method>none</method>
+ <schema_name/>
+ </partitioning>
+ <fields>
+ <field>
+ <length>7</length>
+ <name>avg</name>
+ <precision>2</precision>
+ <rename>avg</rename>
+ <replace>N</replace>
+ <type>Number</type>
+ </field>
+ <field>
+ <length>7</length>
+ <name>min</name>
+ <precision>-1</precision>
+ <rename>min</rename>
+ <replace>N</replace>
+ <type>Integer</type>
+ </field>
+ <field>
+ <length>7</length>
+ <name>max</name>
+ <precision>-1</precision>
+ <rename>max</rename>
+ <replace>N</replace>
+ <type>Integer</type>
+ </field>
+ <field>
+ <length>7</length>
+ <name>cnt</name>
+ <precision>-1</precision>
+ <rename>cnt</rename>
+ <replace>N</replace>
+ <type>Integer</type>
+ </field>
+ </fields>
+ <jsScripts>
+ <jsScript>
+ <jsScript_name>startScript</jsScript_name>
+ <jsScript_script>
+var min = null;
+var max = null;
+var cnt=0;
+var sum=0;
+
+
+
+
+</jsScript_script>
+ <jsScript_type>1</jsScript_type>
+ </jsScript>
+ <jsScript>
+ <jsScript_name>transformScript</jsScript_name>
+ <jsScript_script>
+if (min==null || nr<min) {
+ min = nr;
+}
+if (max==null || nr>max) {
+ max = nr;
+}
+cnt++;
+sum+=nr;
+var avg = sum/cnt;</jsScript_script>
+ <jsScript_type>0</jsScript_type>
+ </jsScript>
+ <jsScript>
+ <jsScript_name>endScript</jsScript_name>
+ <jsScript_script>
+setVariable("TEST_VARIABLE", "testValue", "g");
+</jsScript_script>
+ <jsScript_type>2</jsScript_type>
+ </jsScript>
+ </jsScripts>
+ <optimizationLevel>9</optimizationLevel>
+ <attributes/>
+ <GUI>
+ <xloc>288</xloc>
+ <yloc>80</yloc>
+ </GUI>
+ </transform>
+ <transform>
+ <name>nr</name>
+ <type>Sequence</type>
+ <description/>
+ <distribute>Y</distribute>
+ <custom_distribution/>
+ <copies>1</copies>
+ <partitioning>
+ <method>none</method>
+ <schema_name/>
+ </partitioning>
+ <connection>h2</connection>
+ <increment_by>1</increment_by>
+ <max_value>999999999</max_value>
+ <seqname>SEQ_</seqname>
+ <start_at>1</start_at>
+ <use_counter>Y</use_counter>
+ <use_database>N</use_database>
+ <valuename>nr</valuename>
+ <attributes/>
+ <GUI>
+ <xloc>192</xloc>
+ <yloc>80</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>432</xloc>
+ <yloc>80</yloc>
+ </GUI>
+ </transform>
+ <transform_error_handling>
+ </transform_error_handling>
+ <attributes/>
+</pipeline>
diff --git a/integration-tests/transforms/datasets/golden-javascript-basic.csv b/integration-tests/transforms/datasets/golden-javascript-basic.csv
new file mode 100644
index 0000000000..2240891225
--- /dev/null
+++ b/integration-tests/transforms/datasets/golden-javascript-basic.csv
@@ -0,0 +1,11 @@
+nr,avg,min,max,cnt
+1,1.0,1,1,1
+2,1.5,1,2,2
+3,2.0,1,3,3
+4,2.5,1,4,4
+5,3.0,1,5,5
+6,3.5,1,6,6
+7,4.0,1,7,7
+8,4.5,1,8,8
+9,5.0,1,9,9
+10,5.5,1,10,10
diff --git a/integration-tests/transforms/main-0087-javascript.hwf b/integration-tests/transforms/main-0087-javascript.hwf
new file mode 100644
index 0000000000..17d6daada1
--- /dev/null
+++ b/integration-tests/transforms/main-0087-javascript.hwf
@@ -0,0 +1,162 @@
+<?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-0087-javascript</name>
+ <name_sync_with_filename>Y</name_sync_with_filename>
+ <description/>
+ <extended_description/>
+ <workflow_version/>
+ <created_user>-</created_user>
+ <created_date>2026/03/18 22:27:55.004</created_date>
+ <modified_user>-</modified_user>
+ <modified_date>2026/03/18 22:27:55.004</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>50</xloc>
+ <yloc>50</yloc>
+ <attributes_hac/>
+ </action>
+ <action>
+ <name>0087-javascript-basics UNIT</name>
+ <description/>
+ <type>RunPipelineTests</type>
+ <attributes/>
+ <test_names>
+ <test_name>
+ <name>0087-javascript-basics UNIT</name>
+ </test_name>
+ </test_names>
+ <parallel>N</parallel>
+ <xloc>208</xloc>
+ <yloc>48</yloc>
+ <attributes_hac/>
+ </action>
+ <action>
+ <name>Simple evaluation</name>
+ <description/>
+ <type>SIMPLE_EVAL</type>
+ <attributes/>
+ <comparevalue>testValue</comparevalue>
+ <fieldtype>string</fieldtype>
+ <successbooleancondition>true</successbooleancondition>
+ <successcondition>equal</successcondition>
+ <successnumbercondition>equal</successnumbercondition>
+ <successwhenvarset>N</successwhenvarset>
+ <valuetype>variable</valuetype>
+ <variablename>TEST_VARIABLE</variablename>
+ <parallel>N</parallel>
+ <xloc>416</xloc>
+ <yloc>48</yloc>
+ <attributes_hac/>
+ </action>
+ <action>
+ <name>Success</name>
+ <description/>
+ <type>SUCCESS</type>
+ <attributes/>
+ <parallel>N</parallel>
+ <xloc>544</xloc>
+ <yloc>48</yloc>
+ <attributes_hac/>
+ </action>
+ <action>
+ <name>Fail</name>
+ <description/>
+ <type>ABORT</type>
+ <attributes/>
+ <always_log_rows>N</always_log_rows>
+ <message>End script not called</message>
+ <parallel>N</parallel>
+ <xloc>416</xloc>
+ <yloc>160</yloc>
+ <attributes_hac/>
+ </action>
+ </actions>
+ <hops>
+ <hop>
+ <from>Start</from>
+ <to>0087-javascript-basics UNIT</to>
+ <enabled>Y</enabled>
+ <evaluation>Y</evaluation>
+ <unconditional>Y</unconditional>
+ </hop>
+ <hop>
+ <from>0087-javascript-basics UNIT</from>
+ <to>Simple evaluation</to>
+ <enabled>Y</enabled>
+ <evaluation>Y</evaluation>
+ <unconditional>N</unconditional>
+ </hop>
+ <hop>
+ <from>Simple evaluation</from>
+ <to>Success</to>
+ <enabled>Y</enabled>
+ <evaluation>Y</evaluation>
+ <unconditional>N</unconditional>
+ </hop>
+ <hop>
+ <from>Simple evaluation</from>
+ <to>Fail</to>
+ <enabled>Y</enabled>
+ <evaluation>N</evaluation>
+ <unconditional>N</unconditional>
+ </hop>
+ </hops>
+ <notepads>
+ <notepad>
+ <backgroundcolorblue>210</backgroundcolorblue>
+ <backgroundcolorgreen>136</backgroundcolorgreen>
+ <backgroundcolorred>15</backgroundcolorred>
+ <bordercolorblue>250</bordercolorblue>
+ <bordercolorgreen>231</bordercolorgreen>
+ <bordercolorred>200</bordercolorred>
+ <fontbold>N</fontbold>
+ <fontcolorblue>250</fontcolorblue>
+ <fontcolorgreen>231</fontcolorgreen>
+ <fontcolorred>200</fontcolorred>
+ <fontitalic>N</fontitalic>
+ <fontname>Noto Sans</fontname>
+ <fontsize>10</fontsize>
+ <height>20</height>
+ <xloc>32</xloc>
+ <yloc>112</yloc>
+ <note>The "End" script in the JavaScript transform sets a variable in the grand-parent workflow (this one).
+We check that the end script is called by checking the variable.</note>
+ <width>20</width>
+ </notepad>
+ </notepads>
+ <attributes/>
+</workflow>
diff --git a/integration-tests/transforms/metadata/dataset/golden-javascript-basic.json b/integration-tests/transforms/metadata/dataset/golden-javascript-basic.json
new file mode 100644
index 0000000000..4b8cdd551d
--- /dev/null
+++ b/integration-tests/transforms/metadata/dataset/golden-javascript-basic.json
@@ -0,0 +1,48 @@
+{
+ "base_filename": "golden-javascript-basic.csv",
+ "name": "golden-javascript-basic",
+ "description": "",
+ "dataset_fields": [
+ {
+ "field_comment": "",
+ "field_length": -1,
+ "field_type": 5,
+ "field_precision": 0,
+ "field_name": "nr",
+ "field_format": "####0;-####0"
+ },
+ {
+ "field_comment": "",
+ "field_length": 7,
+ "field_type": 1,
+ "field_precision": 2,
+ "field_name": "avg",
+ "field_format": "####0.0#########;-####0.0#########"
+ },
+ {
+ "field_comment": "",
+ "field_length": 7,
+ "field_type": 5,
+ "field_precision": 0,
+ "field_name": "min",
+ "field_format": "####0;-####0"
+ },
+ {
+ "field_comment": "",
+ "field_length": 7,
+ "field_type": 5,
+ "field_precision": 0,
+ "field_name": "max",
+ "field_format": "####0;-####0"
+ },
+ {
+ "field_comment": "",
+ "field_length": 7,
+ "field_type": 5,
+ "field_precision": 0,
+ "field_name": "cnt",
+ "field_format": "####0;-####0"
+ }
+ ],
+ "folder_name": ""
+}
\ No newline at end of file
diff --git a/integration-tests/transforms/metadata/unit-test/0087-javascript-basics UNIT.json b/integration-tests/transforms/metadata/unit-test/0087-javascript-basics UNIT.json
new file mode 100644
index 0000000000..afdac5d165
--- /dev/null
+++ b/integration-tests/transforms/metadata/unit-test/0087-javascript-basics UNIT.json
@@ -0,0 +1,44 @@
+{
+ "database_replacements": [],
+ "autoOpening": true,
+ "description": "",
+ "persist_filename": "",
+ "test_type": "UNIT_TEST",
+ "variableValues": [],
+ "basePath": "${HOP_UNIT_TESTS_FOLDER}",
+ "golden_data_sets": [
+ {
+ "field_mappings": [
+ {
+ "transform_field": "nr",
+ "data_set_field": "nr"
+ },
+ {
+ "transform_field": "avg",
+ "data_set_field": "avg"
+ },
+ {
+ "transform_field": "min",
+ "data_set_field": "min"
+ },
+ {
+ "transform_field": "max",
+ "data_set_field": "max"
+ },
+ {
+ "transform_field": "cnt",
+ "data_set_field": "cnt"
+ }
+ ],
+ "field_order": [
+ "nr"
+ ],
+ "data_set_name": "golden-javascript-basic",
+ "transform_name": "validate"
+ }
+ ],
+ "input_data_sets": [],
+ "name": "0087-javascript-basics UNIT",
+ "trans_test_tweaks": [],
+ "pipeline_filename": "./0087-javascript-basics.hpl"
+}
\ No newline at end of file
diff --git a/plugins/transforms/javascript/src/main/java/org/apache/hop/pipeline/transforms/javascript/ScriptValues.java b/plugins/transforms/javascript/src/main/java/org/apache/hop/pipeline/transforms/javascript/ScriptValues.java
index f87b9717b9..8588ceba96 100644
--- a/plugins/transforms/javascript/src/main/java/org/apache/hop/pipeline/transforms/javascript/ScriptValues.java
+++ b/plugins/transforms/javascript/src/main/java/org/apache/hop/pipeline/transforms/javascript/ScriptValues.java
@@ -17,6 +17,10 @@
package org.apache.hop.pipeline.transforms.javascript;
+import java.util.ArrayList;
+import java.util.List;
+import lombok.Getter;
+import lombok.Setter;
import org.apache.hop.core.Const;
import org.apache.hop.core.exception.HopException;
import org.apache.hop.core.exception.HopTransformException;
@@ -42,6 +46,8 @@ import org.mozilla.javascript.ScriptableObject;
* Executes a JavaScript on the values in the input stream. Selected calculated values can then be
* put on the output stream.
*/
+@Getter
+@Setter
public class ScriptValues extends BaseTransform<ScriptValuesMeta, ScriptValuesData> {
private static final Class<?> PKG = ScriptValuesMeta.class;
@@ -67,11 +73,9 @@ public class ScriptValues extends BaseTransform<ScriptValuesMeta, ScriptValuesDa
private boolean bRC = false;
- private int iPipelineStat = CONTINUE_PIPELINE;
-
private boolean bFirstRun = false;
- private ScriptValuesScript[] jsScripts;
+ private final List<ScriptValuesScript> jsScripts;
private String strTransformScript = "";
@@ -79,7 +83,7 @@ public class ScriptValues extends BaseTransform<ScriptValuesMeta, ScriptValuesDa
private String strEndScript = "";
- public Script script;
+ private Script script;
public ScriptValues(
TransformMeta transformMeta,
@@ -89,6 +93,7 @@ public class ScriptValues extends BaseTransform<ScriptValuesMeta, ScriptValuesDa
PipelineMeta pipelineMeta,
Pipeline pipeline) {
super(transformMeta, meta, data, copyNr, pipelineMeta, pipeline);
+ jsScripts = new ArrayList<>();
}
private void determineUsedFields(IRowMeta row) {
@@ -97,8 +102,8 @@ public class ScriptValues extends BaseTransform<ScriptValuesMeta, ScriptValuesDa
// Perhaps we find values in comments, but we take no risk!
//
for (int i = 0; i < row.size(); i++) {
- String valname = row.getValueMeta(i).getName().toUpperCase();
- if (strTransformScript.toUpperCase().indexOf(valname) >= 0) {
+ String valueName = row.getValueMeta(i).getName().toUpperCase();
+ if (strTransformScript.toUpperCase().contains(valueName)) {
nr++;
}
}
@@ -114,7 +119,7 @@ public class ScriptValues extends BaseTransform<ScriptValuesMeta, ScriptValuesDa
// Values are case-insensitive in JavaScript.
//
String valname = row.getValueMeta(i).getName();
- if (strTransformScript.indexOf(valname) >= 0) {
+ if (strTransformScript.contains(valname)) {
if (isDetailed()) {
logDetailed(
BaseMessages.getString(
@@ -134,7 +139,9 @@ public class ScriptValues extends BaseTransform<ScriptValuesMeta, ScriptValuesDa
}
}
- private boolean addValues(IRowMeta rowMeta, Object[] row) throws HopException {
+ @SuppressWarnings("deprecation")
+ private void addValuesToContext(IRowMeta rowMeta, Object[] row) throws HopException {
+ int iPipelineStat = CONTINUE_PIPELINE;
if (first) {
first = false;
@@ -149,25 +156,26 @@ public class ScriptValues extends BaseTransform<ScriptValuesMeta, ScriptValuesDa
// Get the indexes of the replaced fields...
//
- data.replaceIndex = new int[meta.getFieldname().length];
- for (int i = 0; i < meta.getFieldname().length; i++) {
- if (meta.getReplace()[i]) {
- data.replaceIndex[i] = rowMeta.indexOfValue(meta.getFieldname()[i]);
+ data.replaceIndex = new int[meta.getScriptFields().size()];
+ for (int i = 0; i < meta.getScriptFields().size(); i++) {
+ ScriptValuesMeta.ScriptField field = meta.getScriptFields().get(i);
+ if (field.isReplace()) {
+ data.replaceIndex[i] = rowMeta.indexOfValue(field.getName());
if (data.replaceIndex[i] < 0) {
- if (Utils.isEmpty(meta.getFieldname()[i])) {
+ if (Utils.isEmpty(field.getName())) {
throw new HopTransformException(
BaseMessages.getString(
PKG,
"ScriptValuesMetaMod.Exception.FieldToReplaceNotFound",
- meta.getFieldname()[i]));
+ field.getName()));
}
- data.replaceIndex[i] = rowMeta.indexOfValue(meta.getRename()[i]);
+ data.replaceIndex[i] = rowMeta.indexOfValue(field.getRename());
if (data.replaceIndex[i] < 0) {
throw new HopTransformException(
BaseMessages.getString(
PKG,
"ScriptValuesMetaMod.Exception.FieldToReplaceNotFound",
- meta.getRename()[i]));
+ field.getRename()));
}
}
} else {
@@ -176,12 +184,12 @@ public class ScriptValues extends BaseTransform<ScriptValuesMeta, ScriptValuesDa
}
// set the optimization level
- data.cx = ContextFactory.getGlobal().enterContext();
+ data.context = ContextFactory.getGlobal().enterContext();
try {
String optimizationLevelAsString = resolve(meta.getOptimizationLevel());
if (!Utils.isEmpty(Const.trim(optimizationLevelAsString))) {
- data.cx.setOptimizationLevel(Integer.parseInt(optimizationLevelAsString.trim()));
+ data.context.setOptimizationLevel(Integer.parseInt(optimizationLevelAsString.trim()));
if (isBasic()) {
logBasic(
BaseMessages.getString(
@@ -190,7 +198,7 @@ public class ScriptValues extends BaseTransform<ScriptValuesMeta, ScriptValuesDa
resolve(meta.getOptimizationLevel())));
}
} else {
- data.cx.setOptimizationLevel(
+ data.context.setOptimizationLevel(
Integer.parseInt(ScriptValuesMeta.OPTIMIZATION_LEVEL_DEFAULT));
if (isBasic()) {
logBasic(
@@ -210,112 +218,43 @@ public class ScriptValues extends BaseTransform<ScriptValuesMeta, ScriptValuesDa
throw new HopException(iae.getMessage());
}
- data.scope = data.cx.initStandardObjects(null, false);
+ data.scope = data.context.initStandardObjects(null, false);
bFirstRun = true;
- Scriptable jsvalue = Context.toObject(this, data.scope);
- data.scope.put("_transform_", data.scope, jsvalue);
+ Scriptable jsTransform = Context.toObject(this, data.scope);
+ data.scope.put("_transform_", data.scope, jsTransform);
// Adding the existing Scripts to the Context
- for (int i = 0; i < meta.getNumberOfJSScripts(); i++) {
- Scriptable jsR = Context.toObject(jsScripts[i].getScript(), data.scope);
- data.scope.put(jsScripts[i].getScriptName(), data.scope, jsR);
+ for (int i = 0; i < meta.getJsScripts().size(); i++) {
+ Scriptable jsR = Context.toObject(jsScripts.get(i).getScript(), data.scope);
+ data.scope.put(jsScripts.get(i).getName(), data.scope, jsR);
}
// Adding the Name of the Pipeline to the Context
data.scope.put("_PipelineName_", data.scope, getPipelineMeta().getName());
try {
- // add these now (they will be re-added later) to make compilation succeed
- //
-
- // Add the old style row object for compatibility reasons...
- //
- Scriptable jsrow = Context.toObject(row, data.scope);
- data.scope.put("row", data.scope, jsrow);
-
// Add the used fields...
//
- for (int i = 0; i < data.fieldsUsed.length; i++) {
- IValueMeta valueMeta = rowMeta.getValueMeta(data.fieldsUsed[i]);
- Object valueData = row[data.fieldsUsed[i]];
-
- Object normalStorageValueData = valueMeta.convertToNormalStorageType(valueData);
- Scriptable jsarg;
- if (normalStorageValueData != null) {
- jsarg = Context.toObject(normalStorageValueData, data.scope);
- } else {
- jsarg = null;
- }
- data.scope.put(valueMeta.getName(), data.scope, jsarg);
- }
-
- // also add the meta information for the whole row
- //
- Scriptable jsrowMeta = Context.toObject(rowMeta, data.scope);
- data.scope.put("rowMeta", data.scope, jsrowMeta);
+ addFieldsToScope(rowMeta, row);
- // Modification for Additional Script parsing
+ // Add the old style row object for compatibility reasons.
+ // also add the meta information for the whole row.
//
- try {
- if (meta.getAddClasses() != null) {
- for (int i = 0; i < meta.getAddClasses().length; i++) {
- Object jsOut = Context.javaToJS(meta.getAddClasses()[i].getAddObject(), data.scope);
- ScriptableObject.putProperty(data.scope, meta.getAddClasses()[i].getJSName(), jsOut);
- }
- }
- } catch (Exception e) {
- throw new HopValueException(
- BaseMessages.getString(PKG, "ScriptValuesMod.Log.CouldNotAttachAdditionalScripts"),
- e);
- }
+ addRowAndRowMetaToScope(rowMeta, row);
// Adding some default JavaScriptFunctions to the System
- try {
- Context.javaToJS(ScriptValuesAddedFunctions.class, data.scope);
- ((ScriptableObject) data.scope)
- .defineFunctionProperties(
- ScriptValuesAddedFunctions.jsFunctionList,
- ScriptValuesAddedFunctions.class,
- ScriptableObject.DONTENUM);
- } catch (Exception ex) {
- throw new HopValueException(
- BaseMessages.getString(PKG, "ScriptValuesMod.Log.CouldNotAddDefaultFunctions"), ex);
- }
+ addFunctionsToScope();
// Adding some Constants to the JavaScript
- try {
+ addConstantsToScope();
- data.scope.put("SKIP_PIPELINE", data.scope, SKIP_PIPELINE);
- data.scope.put("ABORT_PIPELINE", data.scope, ABORT_PIPELINE);
- data.scope.put("ERROR_PIPELINE", data.scope, ERROR_PIPELINE);
- data.scope.put("CONTINUE_PIPELINE", data.scope, CONTINUE_PIPELINE);
+ // Checking for StartScript
+ checkForStartScript();
- } catch (Exception ex) {
- throw new HopValueException(
- BaseMessages.getString(PKG, "ScriptValuesMod.Log.CouldNotAddDefaultConstants"), ex);
- }
-
- try {
- // Checking for StartScript
- if (!Utils.isEmpty(strStartScript)) {
- Script startScript = data.cx.compileString(strStartScript, "pipeline_Start", 1, null);
- startScript.exec(data.cx, data.scope);
- if (isDetailed()) {
- logDetailed(("Start Script found!"));
- }
- } else {
- if (isDetailed()) {
- logDetailed(("No starting Script found!"));
- }
- }
- } catch (Exception es) {
- throw new HopValueException(
- BaseMessages.getString(PKG, "ScriptValuesMod.Log.ErrorProcessingStartScript"), es);
- }
// Now Compile our Script
- data.script = data.cx.compileString(strTransformScript, "script", 1, null);
+ data.script = data.context.compileString(strTransformScript, "script", 1, null);
} catch (Exception e) {
throw new HopValueException(
BaseMessages.getString(PKG, "ScriptValuesMod.Log.CouldNotCompileJavascript"), e);
@@ -330,34 +269,11 @@ public class ScriptValues extends BaseTransform<ScriptValuesMeta, ScriptValuesDa
int outputIndex = rowMeta.size();
try {
- try {
- Scriptable jsrow = Context.toObject(row, data.scope);
- data.scope.put("row", data.scope, jsrow);
-
- for (int i = 0; i < data.fieldsUsed.length; i++) {
- IValueMeta valueMeta = rowMeta.getValueMeta(data.fieldsUsed[i]);
- Object valueData = row[data.fieldsUsed[i]];
-
- Object normalStorageValueData = valueMeta.convertToNormalStorageType(valueData);
- Scriptable jsarg;
- if (normalStorageValueData != null) {
- jsarg = Context.toObject(normalStorageValueData, data.scope);
- } else {
- jsarg = null;
- }
- data.scope.put(valueMeta.getName(), data.scope, jsarg);
- }
-
- // also add the meta information for the hole row
- Scriptable jsrowMeta = Context.toObject(rowMeta, data.scope);
- data.scope.put("rowMeta", data.scope, jsrowMeta);
- } catch (Exception e) {
- throw new HopValueException(
- BaseMessages.getString(PKG, "ScriptValuesMod.Log.UnexpectedeError"), e);
- }
+ addFieldsToScope(rowMeta, row);
+ addRowAndRowMetaToScope(rowMeta, row);
// Executing our Script
- data.script.exec(data.cx, data.scope);
+ data.script.exec(data.context, data.scope, data.scope);
if (bFirstRun) {
bFirstRun = false;
@@ -379,14 +295,13 @@ public class ScriptValues extends BaseTransform<ScriptValuesMeta, ScriptValuesDa
if (bWithPipelineStat) {
iPipelineStat = (int) Context.toNumber(data.scope.get("pipeline_Status", data.scope));
- } else {
- iPipelineStat = CONTINUE_PIPELINE;
}
if (iPipelineStat == CONTINUE_PIPELINE) {
bRC = true;
- for (int i = 0; i < meta.getFieldname().length; i++) {
- Object result = data.scope.get(meta.getFieldname()[i], data.scope);
+ for (int i = 0; i < meta.getScriptFields().size(); i++) {
+ ScriptValuesMeta.ScriptField field = meta.getScriptFields().get(i);
+ Object result = data.scope.get(field.getName(), data.scope);
Object valueData = getValueFromJScript(result, i);
if (data.replaceIndex[i] < 0) {
outputRow[outputIndex++] = valueData;
@@ -407,7 +322,7 @@ public class ScriptValues extends BaseTransform<ScriptValuesMeta, ScriptValuesDa
bRC = true;
break;
case ABORT_PIPELINE:
- if (data.cx != null) {
+ if (data.context != null) {
Context.exit();
}
stopAll();
@@ -415,7 +330,7 @@ public class ScriptValues extends BaseTransform<ScriptValuesMeta, ScriptValuesDa
bRC = false;
break;
case ERROR_PIPELINE:
- if (data.cx != null) {
+ if (data.context != null) {
Context.exit();
}
setErrors(1);
@@ -425,24 +340,88 @@ public class ScriptValues extends BaseTransform<ScriptValuesMeta, ScriptValuesDa
default:
break;
}
-
- // TODO: kick this "ERROR handling" junk out now that we have solid error handling in place.
- //
}
} catch (Exception e) {
throw new HopValueException(
BaseMessages.getString(PKG, "ScriptValuesMod.Log.JavascriptError"), e);
}
- return bRC;
+ }
+
+ private void addRowAndRowMetaToScope(IRowMeta rowMeta, Object[] row) {
+ Scriptable jsRow = Context.toObject(row, data.scope);
+ data.scope.put("row", data.scope, jsRow);
+ Scriptable jsRowMeta = Context.toObject(rowMeta, data.scope);
+ data.scope.put("rowMeta", data.scope, jsRowMeta);
+ }
+
+ private void checkForStartScript() throws HopValueException {
+ try {
+ if (!Utils.isEmpty(strStartScript)) {
+ Script startScript = data.context.compileString(strStartScript, "pipeline_Start", 1, null);
+ startScript.exec(data.context, data.scope, data.scope);
+ if (isDetailed()) {
+ logDetailed(("Start Script found!"));
+ }
+ } else {
+ if (isDetailed()) {
+ logDetailed(("No starting Script found!"));
+ }
+ }
+ } catch (Exception es) {
+ throw new HopValueException(
+ BaseMessages.getString(PKG, "ScriptValuesMod.Log.ErrorProcessingStartScript"), es);
+ }
+ }
+
+ private void addFieldsToScope(IRowMeta rowMeta, Object[] row) throws HopValueException {
+ for (int i = 0; i < data.fieldsUsed.length; i++) {
+ IValueMeta valueMeta = rowMeta.getValueMeta(data.fieldsUsed[i]);
+ Object valueData = row[data.fieldsUsed[i]];
+
+ Object normalStorageValueData = valueMeta.convertToNormalStorageType(valueData);
+ Scriptable jsarg;
+ if (normalStorageValueData != null) {
+ jsarg = Context.toObject(normalStorageValueData, data.scope);
+ } else {
+ jsarg = null;
+ }
+ data.scope.put(valueMeta.getName(), data.scope, jsarg);
+ }
+ }
+
+ private void addFunctionsToScope() throws HopValueException {
+ try {
+ Context.javaToJS(ScriptValuesAddedFunctions.class, data.scope);
+ ((ScriptableObject) data.scope)
+ .defineFunctionProperties(
+ ScriptValuesAddedFunctions.jsFunctionList,
+ ScriptValuesAddedFunctions.class,
+ ScriptableObject.DONTENUM);
+ } catch (Exception ex) {
+ throw new HopValueException(
+ BaseMessages.getString(PKG, "ScriptValuesMod.Log.CouldNotAddDefaultFunctions"), ex);
+ }
+ }
+
+ private void addConstantsToScope() throws HopValueException {
+ try {
+ data.scope.put("SKIP_PIPELINE", data.scope, SKIP_PIPELINE);
+ data.scope.put("ABORT_PIPELINE", data.scope, ABORT_PIPELINE);
+ data.scope.put("ERROR_PIPELINE", data.scope, ERROR_PIPELINE);
+ data.scope.put("CONTINUE_PIPELINE", data.scope, CONTINUE_PIPELINE);
+ } catch (Exception ex) {
+ throw new HopValueException(
+ BaseMessages.getString(PKG, "ScriptValuesMod.Log.CouldNotAddDefaultConstants"), ex);
+ }
}
public Object getValueFromJScript(Object result, int i) throws HopValueException {
- String fieldName = meta.getFieldname()[i];
- if (!Utils.isEmpty(fieldName)) {
+ ScriptValuesMeta.ScriptField field = meta.getScriptFields().get(i);
+ if (!Utils.isEmpty(field.getName())) {
try {
return (result == null)
? null
- : JavaScriptUtils.convertFromJs(result, meta.getType()[i], fieldName);
+ : JavaScriptUtils.convertFromJs(result, field.getType(), field.getName());
} catch (Exception e) {
throw new HopValueException(
BaseMessages.getString(PKG, "ScriptValuesMod.Log.JavascriptError"), e);
@@ -458,47 +437,10 @@ public class ScriptValues extends BaseTransform<ScriptValuesMeta, ScriptValuesDa
@Override
public boolean processRow() throws HopException {
-
Object[] r = getRow(); // Get row from input rowset & set row busy!
if (r == null) {
// Modification for Additional End Function
- try {
- if (data.cx != null) {
- // Checking for EndScript
- if (!Utils.isEmpty(strEndScript)) {
- Script endScript = data.cx.compileString(strEndScript, "pipeline_End", 1, null);
- endScript.exec(data.cx, data.scope);
- if (isDetailed()) {
- logDetailed(("End Script found!"));
- }
- } else {
- if (isDetailed()) {
- logDetailed(("No end Script found!"));
- }
- }
- }
- } catch (Exception e) {
- logError(
- BaseMessages.getString(PKG, "ScriptValuesMod.Log.UnexpectedeError")
- + " : "
- + e.toString());
- logError(
- BaseMessages.getString(PKG, "ScriptValuesMod.Log.ErrorStackTrace")
- + Const.CR
- + Const.getSimpleStackTrace(e)
- + Const.CR
- + Const.getStackTracker(e));
- setErrors(1);
- stopAll();
- }
-
- try {
- if (data.cx != null) {
- Context.exit();
- }
- } catch (Exception er) {
- // Eat this error, it's typically : "Calling Context.exit without previous Context.enter"
- }
+ processEndOfStream();
setOutputDone();
return false;
@@ -506,7 +448,7 @@ public class ScriptValues extends BaseTransform<ScriptValuesMeta, ScriptValuesDa
// Getting the Row, with the Pipeline Status
try {
- addValues(getInputRowMeta(), r);
+ addValuesToContext(getInputRowMeta(), r);
} catch (HopValueException e) {
String location = null;
if (e.getCause() instanceof EvaluatorException evaluatorException) {
@@ -528,39 +470,78 @@ public class ScriptValues extends BaseTransform<ScriptValuesMeta, ScriptValuesDa
return bRC;
}
- @Override
- public boolean init() {
-
- if (super.init()) {
-
- // Add init code here.
- // Get the actual Scripts from our MetaData
- jsScripts = meta.getJSScripts();
- for (ScriptValuesScript jsScript : jsScripts) {
- switch (jsScript.getScriptType()) {
- case ScriptValuesScript.TRANSFORM_SCRIPT:
- strTransformScript = jsScript.getScript();
- break;
- case ScriptValuesScript.START_SCRIPT:
- strStartScript = jsScript.getScript();
- break;
- case ScriptValuesScript.END_SCRIPT:
- strEndScript = jsScript.getScript();
- break;
- default:
- break;
+ private void processEndOfStream() {
+ try {
+ if (data.context != null) {
+ // Checking for EndScript
+ if (!Utils.isEmpty(strEndScript)) {
+ Script endScript = data.context.compileString(strEndScript, "pipeline_End", 1, null);
+ endScript.exec(data.context, data.scope, data.scope);
+ if (isDetailed()) {
+ logDetailed(("End Script found!"));
+ }
+ } else {
+ if (isDetailed()) {
+ logDetailed(("No end Script found!"));
+ }
}
}
+ } catch (Exception e) {
+ logError(
+ BaseMessages.getString(PKG, "ScriptValuesMod.Log.UnexpectedeError")
+ + " : "
+ + e.toString());
+ logError(
+ BaseMessages.getString(PKG, "ScriptValuesMod.Log.ErrorStackTrace")
+ + Const.CR
+ + Const.getSimpleStackTrace(e)
+ + Const.CR
+ + Const.getStackTracker(e));
+ setErrors(1);
+ stopAll();
+ }
- return true;
+ try {
+ if (data.context != null) {
+ Context.exit();
+ }
+ } catch (Exception er) {
+ // Eat this error, it's typically : "Calling Context.exit without previous Context.enter"
+ }
+ }
+
+ @Override
+ public boolean init() {
+ if (!super.init()) {
+ return false;
+ }
+ // Add init code here.
+ // Get the actual Scripts from our MetaData
+ //
+ jsScripts.clear();
+ meta.getJsScripts().forEach(jsScript -> jsScripts.add(new ScriptValuesScript(jsScript)));
+ for (ScriptValuesScript jsScript : jsScripts) {
+ switch (jsScript.getType()) {
+ case ScriptValuesScript.TRANSFORM_SCRIPT:
+ strTransformScript = jsScript.getScript();
+ break;
+ case ScriptValuesScript.START_SCRIPT:
+ strStartScript = jsScript.getScript();
+ break;
+ case ScriptValuesScript.END_SCRIPT:
+ strEndScript = jsScript.getScript();
+ break;
+ default:
+ break;
+ }
}
- return false;
+ return true;
}
@Override
public void dispose() {
try {
- if (data.cx != null) {
+ if (data.context != null) {
Context.exit();
}
} catch (Exception er) {
diff --git a/plugins/transforms/javascript/src/main/java/org/apache/hop/pipeline/transforms/javascript/ScriptValuesAddedFunctions.java b/plugins/transforms/javascript/src/main/java/org/apache/hop/pipeline/transforms/javascript/ScriptValuesAddedFunctions.java
index 75d3c6e65f..30db19fe6a 100644
--- a/plugins/transforms/javascript/src/main/java/org/apache/hop/pipeline/transforms/javascript/ScriptValuesAddedFunctions.java
+++ b/plugins/transforms/javascript/src/main/java/org/apache/hop/pipeline/transforms/javascript/ScriptValuesAddedFunctions.java
@@ -92,7 +92,7 @@ public class ScriptValuesAddedFunctions extends ScriptableObject {
public static final String CONST_THE_FIRST_ARGUMENT_MUST_BE_A_NUMBER =
"The first Argument must be a Number.";
- public static String[] jsFunctionList = {
+ protected static final String[] jsFunctionList = {
"appendToFile",
"getPipelineName",
"writeToLog",
@@ -188,8 +188,7 @@ public class ScriptValuesAddedFunctions extends ScriptableObject {
}
// This is only used for reading, so no concurrency problems.
- // todo: move in the real variables of the transform.
-
+ //
// Functions to Add
// date2num, num2date,
// fisc_date, isNull
diff --git a/plugins/transforms/javascript/src/main/java/org/apache/hop/pipeline/transforms/javascript/ScriptValuesData.java b/plugins/transforms/javascript/src/main/java/org/apache/hop/pipeline/transforms/javascript/ScriptValuesData.java
index 0207f41c11..bff778fe43 100644
--- a/plugins/transforms/javascript/src/main/java/org/apache/hop/pipeline/transforms/javascript/ScriptValuesData.java
+++ b/plugins/transforms/javascript/src/main/java/org/apache/hop/pipeline/transforms/javascript/ScriptValuesData.java
@@ -26,7 +26,7 @@ import org.mozilla.javascript.Scriptable;
@SuppressWarnings("java:S1104")
public class ScriptValuesData extends BaseTransformData implements ITransformData {
- public Context cx;
+ public Context context;
public Scriptable scope;
public Script script;
@@ -37,7 +37,7 @@ public class ScriptValuesData extends BaseTransformData implements ITransformDat
public ScriptValuesData() {
super();
- cx = null;
+ context = null;
fieldsUsed = null;
}
diff --git a/plugins/transforms/javascript/src/main/java/org/apache/hop/pipeline/transforms/javascript/ScriptValuesDialog.java b/plugins/transforms/javascript/src/main/java/org/apache/hop/pipeline/transforms/javascript/ScriptValuesDialog.java
index 6cab057a0a..7677f2f98d 100644
--- a/plugins/transforms/javascript/src/main/java/org/apache/hop/pipeline/transforms/javascript/ScriptValuesDialog.java
+++ b/plugins/transforms/javascript/src/main/java/org/apache/hop/pipeline/transforms/javascript/ScriptValuesDialog.java
@@ -17,13 +17,13 @@
package org.apache.hop.pipeline.transforms.javascript;
-import java.lang.reflect.Method;
import java.math.BigDecimal;
import java.util.Collections;
import java.util.Date;
import java.util.Hashtable;
import java.util.List;
import java.util.Vector;
+import org.apache.commons.lang.StringUtils;
import org.apache.hop.core.Const;
import org.apache.hop.core.Props;
import org.apache.hop.core.exception.HopException;
@@ -71,7 +71,6 @@ import org.eclipse.swt.dnd.DragSourceAdapter;
import org.eclipse.swt.dnd.DragSourceEvent;
import org.eclipse.swt.dnd.TextTransfer;
import org.eclipse.swt.dnd.Transfer;
-import org.eclipse.swt.events.ModifyListener;
import org.eclipse.swt.graphics.Image;
import org.eclipse.swt.graphics.Point;
import org.eclipse.swt.layout.FormAttachment;
@@ -122,8 +121,6 @@ public class ScriptValuesDialog extends BaseTransformDialog {
public static final String CONST_FUNCTION = "Function";
public static final String CONST_JS_FUNCTION = "jsFunction";
- private ModifyListener lsMod;
-
private TableView wFields;
private Label wlPosition;
@@ -348,9 +345,9 @@ public class ScriptValuesDialog extends BaseTransformDialog {
fdlFields.top = new FormAttachment(wSeparator, 0);
wlFields.setLayoutData(fdlFields);
- final int FieldsRows = input.getFieldname().length;
+ final int nrFields = input.getScriptFields().size();
- ColumnInfo[] colinf =
+ ColumnInfo[] colInfos =
new ColumnInfo[] {
new ColumnInfo(
BaseMessages.getString(PKG, "ScriptValuesDialogMod.ColumnInfo.Filename"),
@@ -383,8 +380,8 @@ public class ScriptValuesDialog extends BaseTransformDialog {
variables,
wBottom,
SWT.BORDER | SWT.FULL_SELECTION | SWT.MULTI,
- colinf,
- FieldsRows,
+ colInfos,
+ nrFields,
lsMod,
props);
@@ -766,35 +763,36 @@ public class ScriptValuesDialog extends BaseTransformDialog {
wOptimizationLevel.setText(ScriptValuesMeta.OPTIMIZATION_LEVEL_DEFAULT);
}
- for (int i = 0; i < input.getFieldname().length; i++) {
- if (!Utils.isEmpty(input.getFieldname()[i])) {
+ for (int i = 0; i < input.getScriptFields().size(); i++) {
+ ScriptValuesMeta.ScriptField field = input.getScriptFields().get(i);
+ if (!Utils.isEmpty(field.getName())) {
TableItem item = wFields.table.getItem(i);
- item.setText(1, input.getFieldname()[i]);
- if (input.getRename()[i] != null && !input.getFieldname()[i].equals(input.getRename()[i])) {
- item.setText(2, input.getRename()[i]);
+ item.setText(1, field.getName());
+ if (field.getRename() != null && !field.getName().equals(field.getRename())) {
+ item.setText(2, field.getRename());
}
- item.setText(3, ValueMetaFactory.getValueMetaName(input.getType()[i]));
- if (input.getLength()[i] >= 0) {
- item.setText(4, "" + input.getLength()[i]);
+ item.setText(3, ValueMetaFactory.getValueMetaName(field.getType()));
+ if (field.getLength() >= 0) {
+ item.setText(4, "" + field.getLength());
}
- if (input.getPrecision()[i] >= 0) {
- item.setText(5, "" + input.getPrecision()[i]);
+ if (field.getPrecision() >= 0) {
+ item.setText(5, "" + field.getPrecision());
}
- item.setText(6, input.getReplace()[i] ? YES_NO_COMBO[1] : YES_NO_COMBO[0]);
+ item.setText(6, field.isReplace() ? YES_NO_COMBO[1] : YES_NO_COMBO[0]);
}
}
- ScriptValuesScript[] jsScripts = input.getJSScripts();
- if (jsScripts.length > 0) {
+ List<ScriptValuesScript> jsScripts = input.getJsScripts();
+ if (!jsScripts.isEmpty()) {
for (ScriptValuesScript jsScript : jsScripts) {
if (jsScript.isTransformScript()) {
- strActiveScript = jsScript.getScriptName();
+ strActiveScript = jsScript.getName();
} else if (jsScript.isStartScript()) {
- strActiveStartScript = jsScript.getScriptName();
+ strActiveStartScript = jsScript.getName();
} else if (jsScript.isEndScript()) {
- strActiveEndScript = jsScript.getScriptName();
+ strActiveEndScript = jsScript.getName();
}
- addCtab(jsScript.getScriptName(), jsScript.getScript(), ADD_DEFAULT);
+ addCtab(jsScript.getName(), jsScript.getScript(), ADD_DEFAULT);
}
} else {
addCtab("", "", ADD_DEFAULT);
@@ -867,44 +865,43 @@ public class ScriptValuesDialog extends BaseTransformDialog {
private void getInfo(ScriptValuesMeta meta) {
meta.setOptimizationLevel(wOptimizationLevel.getText());
- int nrFields = wFields.nrNonEmpty();
- meta.allocate(nrFields);
- for (int i = 0; i < nrFields; i++) {
- TableItem item = wFields.getNonEmpty(i);
- meta.getFieldname()[i] = item.getText(1);
- meta.getRename()[i] = item.getText(2);
- if (meta.getRename()[i] == null
- || meta.getRename()[i].isEmpty()
- || meta.getRename()[i].equalsIgnoreCase(meta.getFieldname()[i])) {
- meta.getRename()[i] = meta.getFieldname()[i];
+
+ meta.getScriptFields().clear();
+ for (TableItem item : wFields.getNonEmptyItems()) {
+ ScriptValuesMeta.ScriptField field = new ScriptValuesMeta.ScriptField();
+ field.setName(item.getText(1));
+ field.setRename(item.getText(2));
+ if (StringUtils.isEmpty(field.getRename())
+ || field.getRename().equalsIgnoreCase(field.getName())) {
+ field.setRename(field.getName());
}
- meta.getType()[i] = ValueMetaFactory.getIdForValueMeta(item.getText(3));
- String slen = item.getText(4);
- String sprc = item.getText(5);
- meta.getLength()[i] = Const.toInt(slen, -1);
- meta.getPrecision()[i] = Const.toInt(sprc, -1);
- meta.getReplace()[i] = YES_NO_COMBO[1].equalsIgnoreCase(item.getText(6));
+ field.setType(ValueMetaFactory.getIdForValueMeta(item.getText(3)));
+ String sLength = item.getText(4);
+ String sPrecision = item.getText(5);
+ field.setLength(Const.toInt(sLength, -1));
+ field.setPrecision(Const.toInt(sPrecision, -1));
+ field.setReplace(YES_NO_COMBO[1].equalsIgnoreCase(item.getText(6)));
+ meta.getScriptFields().add(field);
}
CTabItem[] cTabs = folder.getItems();
+ meta.getJsScripts().clear();
if (cTabs.length > 0) {
- ScriptValuesScript[] jsScripts = new ScriptValuesScript[cTabs.length];
for (int i = 0; i < cTabs.length; i++) {
- ScriptValuesScript jsScript =
- new ScriptValuesScript(
- ScriptValuesScript.NORMAL_SCRIPT,
- cTabs[i].getText(),
- getStyledTextComp(cTabs[i]).getText());
+ ScriptValuesScript jsScript = new ScriptValuesScript();
+ jsScript.setType(ScriptValuesScript.NORMAL_SCRIPT);
+ jsScript.setName(cTabs[i].getText());
+ jsScript.setScript(getStyledTextComp(cTabs[i]).getText());
+
if (cTabs[i].getImage().equals(imageActiveScript)) {
- jsScript.setScriptType(ScriptValuesScript.TRANSFORM_SCRIPT);
+ jsScript.setType(ScriptValuesScript.TRANSFORM_SCRIPT);
} else if (cTabs[i].getImage().equals(imageActiveStartScript)) {
- jsScript.setScriptType(ScriptValuesScript.START_SCRIPT);
+ jsScript.setType(ScriptValuesScript.START_SCRIPT);
} else if (cTabs[i].getImage().equals(imageActiveEndScript)) {
- jsScript.setScriptType(ScriptValuesScript.END_SCRIPT);
+ jsScript.setType(ScriptValuesScript.END_SCRIPT);
}
- jsScripts[i] = jsScript;
+ meta.getJsScripts().add(jsScript);
}
- meta.setJSScripts(jsScripts);
}
}
@@ -1133,6 +1130,7 @@ public class ScriptValuesDialog extends BaseTransformDialog {
}
}
+ @SuppressWarnings("deprecation")
private boolean test(boolean getvars, boolean popup) {
boolean retval = true;
TextComposite wScript = getStyledTextComp();
@@ -1169,22 +1167,6 @@ public class ScriptValuesDialog extends BaseTransformDialog {
Scriptable jsvalue = Context.toObject(dummyTransform, jsscope);
jsscope.put("_transform_", jsscope, jsvalue);
- // Modification for Additional Script parsing
- try {
- if (input.getAddClasses() != null) {
- for (int i = 0; i < input.getAddClasses().length; i++) {
- Object jsOut = Context.javaToJS(input.getAddClasses()[i].getAddObject(), jsscope);
- ScriptableObject.putProperty(jsscope, input.getAddClasses()[i].getJSName(), jsOut);
- }
- }
- } catch (Exception e) {
- testException =
- new HopException(
- BaseMessages.getString(
- PKG, "ScriptValuesDialogMod.CouldNotAddToContext", e.toString()));
- retval = false;
- }
-
// Adding some default JavaScriptFunctions to the System
try {
Context.javaToJS(ScriptValuesAddedFunctions.class, jsscope);
@@ -1591,63 +1573,6 @@ public class ScriptValuesDialog extends BaseTransformDialog {
if (wTreeClassesitem != null) {
wTreeClassesitem.dispose();
}
- if (input.getAddClasses() != null) {
- for (int i = 0; i < input.getAddClasses().length; i++) {
- try {
- Method[] methods = input.getAddClasses()[i].getAddClass().getMethods();
- String strClassType = input.getAddClasses()[i].getAddClass().toString();
- String strParams;
- wTreeClassesitem = new TreeItem(wTree, SWT.NULL);
- wTreeClassesitem.setText(input.getAddClasses()[i].getJSName());
- for (Method method : methods) {
- String strDeclaringClass = method.getDeclaringClass().toString();
- if (strClassType.equals(strDeclaringClass)) {
- TreeItem item2 = new TreeItem(wTreeClassesitem, SWT.NULL);
- strParams = buildAddClassFunctionName(method);
- item2.setText(method.getName() + "(" + strParams + ")");
- String strData =
- input.getAddClasses()[i].getJSName()
- + "."
- + method.getName()
- + "("
- + strParams
- + ")";
- item2.setData(strData);
- }
- }
- } catch (Exception e) {
- // Ignore errors
- }
- }
- }
- }
-
- private String buildAddClassFunctionName(Method metForParams) {
- StringBuilder sbRC = new StringBuilder();
- String strRC = "";
- Class<?>[] clsParamType = metForParams.getParameterTypes();
- String strParam;
-
- for (Class<?> aClass : clsParamType) {
- strParam = aClass.getName();
- if (!strParam.toLowerCase().contains("javascript")) {
- if (strParam.toLowerCase().contains("object")) {
- sbRC.append("var");
- sbRC.append(", ");
- } else if (strParam.equals("java.lang.String")) {
- sbRC.append("String");
- sbRC.append(", ");
- } else {
- sbRC.append(strParam);
- sbRC.append(", ");
- }
- }
- }
- strRC = sbRC.toString();
- if (!strRC.isEmpty()) {
- strRC = strRC.substring(0, sbRC.length() - 2);
- }
- return strRC;
}
private void buildingFolderMenu() {
@@ -1916,6 +1841,7 @@ public class ScriptValuesDialog extends BaseTransformDialog {
}
// This could be useful for further improvements
+ @SuppressWarnings("deprecation")
public static ScriptNode parseVariables(
Context cx,
Scriptable scope,
diff --git a/plugins/transforms/javascript/src/main/java/org/apache/hop/pipeline/transforms/javascript/ScriptValuesMeta.java b/plugins/transforms/javascript/src/main/java/org/apache/hop/pipeline/transforms/javascript/ScriptValuesMeta.java
index c4c13c2c6e..40ea0fd016 100644
--- a/plugins/transforms/javascript/src/main/java/org/apache/hop/pipeline/transforms/javascript/ScriptValuesMeta.java
+++ b/plugins/transforms/javascript/src/main/java/org/apache/hop/pipeline/transforms/javascript/ScriptValuesMeta.java
@@ -17,34 +17,26 @@
package org.apache.hop.pipeline.transforms.javascript;
-import com.google.common.annotations.VisibleForTesting;
import java.math.BigDecimal;
-import java.net.URL;
-import java.util.Arrays;
+import java.util.ArrayList;
import java.util.Date;
import java.util.List;
-import java.util.Properties;
+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.HopException;
import org.apache.hop.core.exception.HopTransformException;
-import org.apache.hop.core.exception.HopXmlException;
-import org.apache.hop.core.injection.AfterInjection;
-import org.apache.hop.core.injection.DataTypeConverter;
-import org.apache.hop.core.injection.Injection;
-import org.apache.hop.core.injection.InjectionDeep;
-import org.apache.hop.core.injection.InjectionSupported;
-import org.apache.hop.core.injection.NullNumberConverter;
-import org.apache.hop.core.plugins.HopURLClassLoader;
import org.apache.hop.core.row.IRowMeta;
import org.apache.hop.core.row.IValueMeta;
+import org.apache.hop.core.row.value.ValueMetaBase;
import org.apache.hop.core.row.value.ValueMetaFactory;
import org.apache.hop.core.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.IHopMetadataProvider;
import org.apache.hop.pipeline.PipelineMeta;
import org.apache.hop.pipeline.transform.BaseTransformMeta;
@@ -55,8 +47,6 @@ import org.mozilla.javascript.JavaScriptException;
import org.mozilla.javascript.Script;
import org.mozilla.javascript.Scriptable;
import org.mozilla.javascript.ScriptableObject;
-import org.w3c.dom.Document;
-import org.w3c.dom.Node;
@Transform(
id = "ScriptValueMod",
@@ -66,326 +56,109 @@ import org.w3c.dom.Node;
categoryDescription = "i18n:org.apache.hop.pipeline.transform:BaseTransform.Category.Scripting",
keywords = "i18n::ScriptValuesMeta.keyword",
documentationUrl = "/pipeline/transforms/javascript.html")
-@InjectionSupported(
- localizationPrefix = "ScriptValuesMod.Injection.",
- groups = {"FIELDS", "SCRIPTS"})
+@Getter
+@Setter
public class ScriptValuesMeta extends BaseTransformMeta<ScriptValues, ScriptValuesData> {
private static final Class<?> PKG = ScriptValuesMeta.class;
- private static final String JSSCRIPT_TAG_TYPE = "jsScript_type";
- private static final String JSSCRIPT_TAG_NAME = "jsScript_name";
- private static final String JSSCRIPT_TAG_SCRIPT = "jsScript_script";
-
public static final String OPTIMIZATION_LEVEL_DEFAULT = "9";
- public static final String CONST_SPACES = " ";
-
- private ScriptValuesAddClasses[] additionalClasses;
-
- @InjectionDeep private ScriptValuesScript[] jsScripts;
-
- @Injection(name = "FIELD_NAME", group = "FIELDS")
- private String[] fieldname;
-
- @Injection(name = "FIELD_RENAME_TO", group = "FIELDS")
- private String[] rename;
-
- @Injection(
- name = "FIELD_TYPE",
- group = "FIELDS",
- convertEmpty = true,
- converter = DataTypeConverter.class)
- private int[] type;
-
- @Injection(
- name = "FIELD_LENGTH",
- group = "FIELDS",
- convertEmpty = true,
- converter = NullNumberConverter.class)
- private int[] length;
-
- @Injection(
- name = "FIELD_PRECISION",
- group = "FIELDS",
- convertEmpty = true,
- converter = NullNumberConverter.class)
- private int[] precision;
-
- @Injection(name = "FIELD_REPLACE", group = "FIELDS")
- private boolean[] replace; // Replace the specified field.
-
- @Injection(name = "OPTIMIZATION_LEVEL")
- private String optimizationLevel;
-
- public ScriptValuesMeta() {
- super(); // allocate BaseTransformMeta
- try {
- parseXmlForAdditionalClasses();
- } catch (Exception e) {
- /* Ignore */
- }
- }
-
- /**
- * @return Returns the length.
- */
- public int[] getLength() {
- return length;
- }
-
- /**
- * @param length The length to set.
- */
- public void setLength(int[] length) {
- this.length = length;
- }
-
- /**
- * @return Returns the name.
- */
- public String[] getFieldname() {
- return fieldname;
- }
-
- /**
- * @param fieldname The name to set.
- */
- public void setFieldname(String[] fieldname) {
- this.fieldname = fieldname;
- }
-
- /**
- * @return Returns the precision.
- */
- public int[] getPrecision() {
- return precision;
- }
-
- /**
- * @param precision The precision to set.
- */
- public void setPrecision(int[] precision) {
- this.precision = precision;
- }
-
- /**
- * @return Returns the rename.
- */
- public String[] getRename() {
- return rename;
- }
-
- /**
- * @param rename The rename to set.
- */
- public void setRename(String[] rename) {
- this.rename = rename;
- }
-
- /**
- * @return Returns the type.
- */
- public int[] getType() {
- return this.type;
- }
-
- @AfterInjection
- public void afterInjection() {
- // extend all fields related arrays to match the length of the fieldname array, as they may all
- // be different
- // sizes, after meta injection
- extend(fieldname.length);
- }
-
- /**
- * @param type The type to set.
- */
- public void setType(int[] type) {
- this.type = type;
- }
- public int getNumberOfJSScripts() {
- return jsScripts.length;
- }
-
- public String[] getJSScriptNames() {
- String[] strJSNames = new String[jsScripts.length];
- for (int i = 0; i < jsScripts.length; i++) {
- strJSNames[i] = jsScripts[i].getScriptName();
+ @Getter
+ @Setter
+ public static class ScriptField {
+ @HopMetadataProperty(
+ key = "name",
+ injectionKey = "FIELD_NAME",
+ injectionKeyDescription = "ScriptValuesMod.Injection.FIELD_NAME")
+ private String name;
+
+ @HopMetadataProperty(
+ key = "rename",
+ injectionKey = "FIELD_RENAME_TO",
+ injectionKeyDescription = "ScriptValuesMod.Injection.FIELD_RENAME_TO")
+ private String rename;
+
+ @HopMetadataProperty(
+ key = "type",
+ intCodeConverter = ValueMetaBase.ValueTypeCodeConverter.class,
+ injectionKey = "FIELD_TYPE",
+ injectionKeyDescription = "ScriptValuesMod.Injection.FIELD_TYPE")
+ private int type;
+
+ @HopMetadataProperty(
+ key = "length",
+ injectionKey = "FIELD_LENGTH",
+ injectionKeyDescription = "ScriptValuesMod.Injection.FIELD_LENGTH")
+ private int length;
+
+ @HopMetadataProperty(
+ key = "precision",
+ injectionKey = "FIELD_PRECISION",
+ injectionKeyDescription = "ScriptValuesMod.Injection.FIELD_PRECISION")
+ private int precision;
+
+ @HopMetadataProperty(
+ key = "replace",
+ injectionKey = "FIELD_REPLACE",
+ injectionKeyDescription = "ScriptValuesMod.Injection.FIELD_REPLACE")
+ private boolean replace;
+
+ public ScriptField() {}
+
+ public ScriptField(ScriptField f) {
+ this.name = f.name;
+ this.rename = f.rename;
+ this.type = f.type;
+ this.length = f.length;
+ this.precision = f.precision;
+ this.replace = f.replace;
}
- return strJSNames;
}
- public ScriptValuesScript[] getJSScripts() {
- return jsScripts;
- }
-
- public void setJSScripts(ScriptValuesScript[] jsScripts) {
- this.jsScripts = jsScripts;
- }
-
- @Override
- public void loadXml(Node transformNode, IHopMetadataProvider metadataProvider)
- throws HopXmlException {
- readData(transformNode);
- }
-
- public void allocate(int nrFields) {
- fieldname = new String[nrFields];
- rename = new String[nrFields];
- type = new int[nrFields];
- for (int i = 0; i < nrFields; i++) {
- type[i] = -1;
- }
- length = new int[nrFields];
- for (int i = 0; i < nrFields; i++) {
- length[i] = -1;
- }
- precision = new int[nrFields];
- for (int i = 0; i < nrFields; i++) {
- precision[i] = -1;
- }
- replace = new boolean[nrFields];
- }
-
- /**
- * Extends all field related arrays so that they are the same size.
- *
- * @param nrFields
- */
- @VisibleForTesting
- void extend(int nrFields) {
- fieldname = extend(fieldname, nrFields);
- rename = extend(rename, nrFields);
- type = extend(type, nrFields);
- length = extend(length, nrFields);
- precision = extend(precision, nrFields);
- replace = extend(replace, nrFields);
- }
+ @HopMetadataProperty(
+ key = "jsScript",
+ groupKey = "jsScripts",
+ injectionGroupKey = "SCRIPTS",
+ injectionGroupDescription = "ScriptValuesMod.Injection.SCRIPTS")
+ private List<ScriptValuesScript> jsScripts;
+
+ @HopMetadataProperty(
+ key = "field",
+ groupKey = "fields",
+ injectionGroupKey = "FIELDS",
+ injectionGroupDescription = "ScriptValuesMod.Injection.FIELDS")
+ private List<ScriptField> scriptFields;
+
+ @HopMetadataProperty(
+ key = "optimizationLevel",
+ injectionKey = "OPTIMIZATION_LEVEL",
+ injectionKeyDescription = "ScriptValuesMod.Injection.OPTIMIZATION_LEVEL")
+ private String optimizationLevel;
- private String[] extend(final String[] array, final int nrFields) {
- if (array == null) {
- return new String[nrFields];
- } else if (array.length < nrFields) {
- return Arrays.copyOf(array, nrFields);
- } else {
- return array;
- }
- }
+ public ScriptValuesMeta() {
+ super();
+ jsScripts = new ArrayList<>();
+ scriptFields = new ArrayList<>();
+ optimizationLevel = OPTIMIZATION_LEVEL_DEFAULT;
- private int[] extend(final int[] array, final int nrFields) {
- if (array == null || array.length < nrFields) {
- int originalLength = array == null ? 0 : array.length;
- final int[] newArray = array == null ? new int[nrFields] : Arrays.copyOf(array, nrFields);
- for (int i = originalLength; i < nrFields; i++) {
- newArray[i] = -1;
- }
- return newArray;
- } else {
- return array;
- }
+ ScriptValuesScript script = new ScriptValuesScript();
+ script.setType(ScriptValuesScript.TRANSFORM_SCRIPT);
+ script.setName(BaseMessages.getString(PKG, "ScriptValuesMod.Script1"));
+ script.setScript(
+ "//" + BaseMessages.getString(PKG, "ScriptValuesMod.ScriptHere") + Const.CR + Const.CR);
+ jsScripts.add(script);
}
- private boolean[] extend(final boolean[] array, final int nrFields) {
- if (array == null) {
- return new boolean[nrFields];
- } else if (array.length < nrFields) {
- return Arrays.copyOf(array, nrFields);
- } else {
- return array;
- }
+ public ScriptValuesMeta(ScriptValuesMeta m) {
+ this();
+ this.optimizationLevel = m.optimizationLevel;
+ m.jsScripts.forEach(s -> this.jsScripts.add(new ScriptValuesScript(s)));
+ m.scriptFields.forEach(f -> scriptFields.add(new ScriptField(f)));
}
@Override
public Object clone() {
- ScriptValuesMeta retval = (ScriptValuesMeta) super.clone();
-
- int nrFields = fieldname.length;
-
- retval.allocate(nrFields);
- System.arraycopy(fieldname, 0, retval.fieldname, 0, nrFields);
- System.arraycopy(rename, 0, retval.rename, 0, nrFields);
- System.arraycopy(type, 0, retval.type, 0, nrFields);
- System.arraycopy(length, 0, retval.length, 0, nrFields);
- System.arraycopy(precision, 0, retval.precision, 0, nrFields);
- System.arraycopy(replace, 0, retval.replace, 0, nrFields);
-
- return retval;
- }
-
- private void readData(Node transformNode) throws HopXmlException {
- try {
- String script = XmlHandler.getTagValue(transformNode, "script");
- optimizationLevel = XmlHandler.getTagValue(transformNode, "optimizationLevel");
-
- // When in compatibility mode, we load the script, not the other tabs...
- //
- if (!Utils.isEmpty(script)) {
- jsScripts = new ScriptValuesScript[1];
- jsScripts[0] =
- new ScriptValuesScript(ScriptValuesScript.TRANSFORM_SCRIPT, "ScriptValue", script);
- } else {
- Node scripts = XmlHandler.getSubNode(transformNode, "jsScripts");
- int nrscripts = XmlHandler.countNodes(scripts, "jsScript");
- jsScripts = new ScriptValuesScript[nrscripts];
- for (int i = 0; i < nrscripts; i++) {
- Node fnode = XmlHandler.getSubNodeByNr(scripts, "jsScript", i);
-
- jsScripts[i] =
- new ScriptValuesScript(
- Integer.parseInt(XmlHandler.getTagValue(fnode, JSSCRIPT_TAG_TYPE)),
- XmlHandler.getTagValue(fnode, JSSCRIPT_TAG_NAME),
- XmlHandler.getTagValue(fnode, JSSCRIPT_TAG_SCRIPT));
- }
- }
-
- Node fields = XmlHandler.getSubNode(transformNode, "fields");
- int nrFields = XmlHandler.countNodes(fields, "field");
-
- allocate(nrFields);
-
- for (int i = 0; i < nrFields; i++) {
- Node fnode = XmlHandler.getSubNodeByNr(fields, "field", i);
-
- fieldname[i] = XmlHandler.getTagValue(fnode, "name");
- rename[i] = XmlHandler.getTagValue(fnode, "rename");
- type[i] = ValueMetaFactory.getIdForValueMeta(XmlHandler.getTagValue(fnode, "type"));
-
- String slen = XmlHandler.getTagValue(fnode, "length");
- String sprc = XmlHandler.getTagValue(fnode, "precision");
- length[i] = Const.toInt(slen, -1);
- precision[i] = Const.toInt(sprc, -1);
- replace[i] = "Y".equalsIgnoreCase(XmlHandler.getTagValue(fnode, "replace"));
- }
- } catch (Exception e) {
- throw new HopXmlException(
- BaseMessages.getString(
- PKG, "ScriptValuesMetaMod.Exception.UnableToLoadTransformMetaFromXML"),
- e);
- }
- }
-
- @Override
- public void setDefault() {
- jsScripts = new ScriptValuesScript[1];
- jsScripts[0] =
- new ScriptValuesScript(
- ScriptValuesScript.TRANSFORM_SCRIPT,
- BaseMessages.getString(PKG, "ScriptValuesMod.Script1"),
- "//" + BaseMessages.getString(PKG, "ScriptValuesMod.ScriptHere") + Const.CR + Const.CR);
-
- int nrFields = 0;
- allocate(nrFields);
-
- for (int i = 0; i < nrFields; i++) {
- fieldname[i] = "newvalue";
- rename[i] = "newvalue";
- type[i] = IValueMeta.TYPE_NUMBER;
- length[i] = -1;
- precision[i] = -1;
- replace[i] = false;
- }
-
- optimizationLevel = OPTIMIZATION_LEVEL_DEFAULT;
+ return new ScriptValuesMeta(this);
}
@Override
@@ -398,30 +171,34 @@ public class ScriptValuesMeta extends BaseTransformMeta<ScriptValues, ScriptValu
IHopMetadataProvider metadataProvider)
throws HopTransformException {
try {
- for (int i = 0; i < fieldname.length; i++) {
- if (!Utils.isEmpty(fieldname[i])) {
- int valueIndex = -1;
+ for (ScriptField field : scriptFields) {
+ if (!Utils.isEmpty(field.getName())) {
+ int valueIndex;
IValueMeta v;
- if (replace[i]) {
- valueIndex = row.indexOfValue(fieldname[i]);
+ if (field.isReplace()) {
+ valueIndex = row.indexOfValue(field.getName());
if (valueIndex < 0) {
// The field was not found using the "name" field
- if (Utils.isEmpty(rename[i])) {
+ if (Utils.isEmpty(field.getRename())) {
// There is no "rename" field to try; Therefore we cannot find the
// field to replace
throw new HopTransformException(
BaseMessages.getString(
- PKG, "ScriptValuesMetaMod.Exception.FieldToReplaceNotFound", fieldname[i]));
+ PKG,
+ "ScriptValuesMetaMod.Exception.FieldToReplaceNotFound",
+ field.getName()));
} else {
// Lookup the field to replace using the "rename" field
- valueIndex = row.indexOfValue(rename[i]);
+ valueIndex = row.indexOfValue(field.getRename());
if (valueIndex < 0) {
// The field was not found using the "rename" field"; Therefore
// we cannot find the field to replace
//
throw new HopTransformException(
BaseMessages.getString(
- PKG, "ScriptValuesMetaMod.Exception.FieldToReplaceNotFound", rename[i]));
+ PKG,
+ "ScriptValuesMetaMod.Exception.FieldToReplaceNotFound",
+ field.getRename()));
}
}
}
@@ -429,19 +206,19 @@ public class ScriptValuesMeta extends BaseTransformMeta<ScriptValues, ScriptValu
// Change the data type to match what's specified...
//
IValueMeta source = row.getValueMeta(valueIndex);
- v = ValueMetaFactory.cloneValueMeta(source, type[i]);
+ v = ValueMetaFactory.cloneValueMeta(source, field.getType());
row.setValueMeta(valueIndex, v);
} else {
- if (!Utils.isEmpty(rename[i])) {
- v = ValueMetaFactory.createValueMeta(rename[i], type[i]);
+ if (!Utils.isEmpty(field.getRename())) {
+ v = ValueMetaFactory.createValueMeta(field.getRename(), field.getType());
} else {
- v = ValueMetaFactory.createValueMeta(fieldname[i], type[i]);
+ v = ValueMetaFactory.createValueMeta(field.getName(), field.getType());
}
}
- v.setLength(length[i]);
- v.setPrecision(precision[i]);
+ v.setLength(field.getLength());
+ v.setPrecision(field.getPrecision());
v.setOrigin(originTransformName);
- if (!replace[i]) {
+ if (!field.isReplace()) {
row.addValueMeta(v);
}
}
@@ -451,46 +228,7 @@ public class ScriptValuesMeta extends BaseTransformMeta<ScriptValues, ScriptValu
}
}
- @Override
- public String getXml() {
- StringBuilder retval = new StringBuilder(300);
-
- retval.append(" ").append(XmlHandler.addTagValue("optimizationLevel", optimizationLevel));
-
- retval.append(" <jsScripts>");
- for (ScriptValuesScript jsScript : jsScripts) {
- retval.append(" <jsScript>");
- retval
- .append(CONST_SPACES)
- .append(XmlHandler.addTagValue(JSSCRIPT_TAG_TYPE, jsScript.getScriptType()));
- retval
- .append(CONST_SPACES)
- .append(XmlHandler.addTagValue(JSSCRIPT_TAG_NAME, jsScript.getScriptName()));
- retval
- .append(CONST_SPACES)
- .append(XmlHandler.addTagValue(JSSCRIPT_TAG_SCRIPT, jsScript.getScript()));
- retval.append(" </jsScript>");
- }
- retval.append(" </jsScripts>");
-
- retval.append(" <fields>");
- for (int i = 0; i < fieldname.length; i++) {
- retval.append(" <field>");
- retval.append(CONST_SPACES).append(XmlHandler.addTagValue("name", fieldname[i]));
- retval.append(CONST_SPACES).append(XmlHandler.addTagValue("rename", rename[i]));
- retval
- .append(CONST_SPACES)
- .append(XmlHandler.addTagValue("type", ValueMetaFactory.getValueMetaName(type[i])));
- retval.append(CONST_SPACES).append(XmlHandler.addTagValue("length", length[i]));
- retval.append(CONST_SPACES).append(XmlHandler.addTagValue("precision", precision[i]));
- retval.append(CONST_SPACES).append(XmlHandler.addTagValue("replace", replace[i]));
- retval.append(" </field>");
- }
- retval.append(" </fields>");
-
- return retval.toString();
- }
-
+ @SuppressWarnings("deprecation")
@Override
public void check(
List<ICheckResult> remarks,
@@ -502,18 +240,16 @@ public class ScriptValuesMeta extends BaseTransformMeta<ScriptValues, ScriptValu
IRowMeta info,
IVariables variables,
IHopMetadataProvider metadataProvider) {
- boolean errorFound = false;
String errorMessage = "";
CheckResult cr;
- Context jscx;
- Scriptable jsscope;
- Script jsscript;
+ Context jsContext;
+ ScriptableObject jsScope;
- jscx = ContextFactory.getGlobal().enterContext();
- jsscope = jscx.initStandardObjects(null, false);
+ jsContext = ContextFactory.getGlobal().enterContext();
+ jsScope = jsContext.initStandardObjects(null, false);
try {
- jscx.setOptimizationLevel(Integer.parseInt(variables.resolve(optimizationLevel)));
+ jsContext.setOptimizationLevel(Integer.parseInt(variables.resolve(optimizationLevel)));
} catch (NumberFormatException nfe) {
errorMessage =
"Error with optimization level. Could not convert the value of "
@@ -534,15 +270,15 @@ public class ScriptValuesMeta extends BaseTransformMeta<ScriptValues, ScriptValu
String strActiveEndScript = "";
// Building the Scripts
- if (jsScripts.length > 0) {
+ if (!jsScripts.isEmpty()) {
for (ScriptValuesScript jsScript : jsScripts) {
if (jsScript.isTransformScript()) {
strActiveScript = jsScript.getScript();
} else if (jsScript.isStartScript()) {
- strActiveStartScriptName = jsScript.getScriptName();
+ strActiveStartScriptName = jsScript.getName();
strActiveStartScript = jsScript.getScript();
} else if (jsScript.isEndScript()) {
- strActiveEndScriptName = jsScript.getScriptName();
+ strActiveEndScriptName = jsScript.getName();
strActiveEndScript = jsScript.getScript();
}
}
@@ -560,47 +296,32 @@ public class ScriptValuesMeta extends BaseTransformMeta<ScriptValues, ScriptValu
remarks.add(cr);
// Adding the existing Scripts to the Context
- for (int i = 0; i < getNumberOfJSScripts(); i++) {
- Scriptable jsR = Context.toObject(jsScripts[i].getScript(), jsscope);
- jsscope.put(jsScripts[i].getScriptName(), jsscope, jsR);
- }
-
- // Modification for Additional Script parsing
- try {
- if (getAddClasses() != null) {
- for (int i = 0; i < getAddClasses().length; i++) {
- Object jsOut = Context.javaToJS(getAddClasses()[i].getAddObject(), jsscope);
- ScriptableObject.putProperty(jsscope, getAddClasses()[i].getJSName(), jsOut);
- }
- }
- } catch (Exception e) {
- errorMessage = ("Couldn't add JavaClasses to Context! Error:");
- cr = new CheckResult(ICheckResult.TYPE_RESULT_ERROR, errorMessage, transformMeta);
- remarks.add(cr);
+ for (ScriptValuesScript jsScript : jsScripts) {
+ Scriptable jsR = Context.toObject(jsScript.getScript(), jsScope);
+ jsScope.put(jsScript.getName(), jsScope, jsR);
}
// Adding some default JavaScriptFunctions to the System
try {
- Context.javaToJS(ScriptValuesAddedFunctions.class, jsscope);
- ((ScriptableObject) jsscope)
- .defineFunctionProperties(
- ScriptValuesAddedFunctions.jsFunctionList,
- ScriptValuesAddedFunctions.class,
- ScriptableObject.DONTENUM);
+ Context.javaToJS(ScriptValuesAddedFunctions.class, jsScope);
+ jsScope.defineFunctionProperties(
+ ScriptValuesAddedFunctions.jsFunctionList,
+ ScriptValuesAddedFunctions.class,
+ ScriptableObject.DONTENUM);
} catch (Exception ex) {
- errorMessage = "Couldn't add Default Functions! Error:" + Const.CR + ex.toString();
+ errorMessage = "Couldn't add Default Functions! Error:" + Const.CR + ex;
cr = new CheckResult(ICheckResult.TYPE_RESULT_ERROR, errorMessage, transformMeta);
remarks.add(cr);
}
// Adding some Constants to the JavaScript
try {
- jsscope.put("SKIP_PIPELINE", jsscope, ScriptValues.SKIP_PIPELINE);
- jsscope.put("ABORT_PIPELINE", jsscope, ScriptValues.ABORT_PIPELINE);
- jsscope.put("ERROR_PIPELINE", jsscope, ScriptValues.ERROR_PIPELINE);
- jsscope.put("CONTINUE_PIPELINE", jsscope, ScriptValues.CONTINUE_PIPELINE);
+ jsScope.put("SKIP_PIPELINE", jsScope, ScriptValues.SKIP_PIPELINE);
+ jsScope.put("ABORT_PIPELINE", jsScope, ScriptValues.ABORT_PIPELINE);
+ jsScope.put("ERROR_PIPELINE", jsScope, ScriptValues.ERROR_PIPELINE);
+ jsScope.put("CONTINUE_PIPELINE", jsScope, ScriptValues.CONTINUE_PIPELINE);
} catch (Exception ex) {
- errorMessage = "Couldn't add Pipeline Constants! Error:" + Const.CR + ex.toString();
+ errorMessage = "Couldn't add Pipeline Constants! Error:" + Const.CR + ex;
cr = new CheckResult(ICheckResult.TYPE_RESULT_ERROR, errorMessage, transformMeta);
remarks.add(cr);
}
@@ -608,12 +329,12 @@ public class ScriptValuesMeta extends BaseTransformMeta<ScriptValues, ScriptValu
try {
ScriptValuesDummy dummyTransform =
new ScriptValuesDummy(prev, pipelineMeta.getTransformFields(variables, transformMeta));
- Scriptable jsvalue = Context.toObject(dummyTransform, jsscope);
- jsscope.put("_transform_", jsscope, jsvalue);
+ Scriptable jsvalue = Context.toObject(dummyTransform, jsScope);
+ jsScope.put("_transform_", jsScope, jsvalue);
Object[] row = new Object[prev.size()];
- Scriptable jsRowMeta = Context.toObject(prev, jsscope);
- jsscope.put("rowMeta", jsscope, jsRowMeta);
+ Scriptable jsRowMeta = Context.toObject(prev, jsScope);
+ jsScope.put("rowMeta", jsScope, jsRowMeta);
for (int i = 0; i < prev.size(); i++) {
IValueMeta valueMeta = prev.getValueMeta(i);
Object valueData = null;
@@ -648,114 +369,29 @@ public class ScriptValuesMeta extends BaseTransformMeta<ScriptValues, ScriptValu
}
row[i] = valueData;
-
- Scriptable jsarg = Context.toObject(valueData, jsscope);
- jsscope.put(valueMeta.getName(), jsscope, jsarg);
+ if (valueData != null) {
+ Scriptable jsArgument = Context.toObject(valueData, jsScope);
+ jsScope.put(valueMeta.getName(), jsScope, jsArgument);
+ }
}
- Scriptable jsRow = Context.toObject(row, jsscope);
- jsscope.put("row", jsscope, jsRow);
+ Scriptable jsRow = Context.toObject(row, jsScope);
+ jsScope.put("row", jsScope, jsRow);
} catch (Exception ev) {
- errorMessage = "Couldn't add Input fields to Script! Error:" + Const.CR + ev.toString();
+ errorMessage = "Couldn't add Input fields to Script! Error:" + Const.CR + ev;
cr = new CheckResult(ICheckResult.TYPE_RESULT_ERROR, errorMessage, transformMeta);
remarks.add(cr);
}
- try {
- // Checking for StartScript
- if (!Utils.isEmpty(strActiveStartScript)) {
- /* Object startScript = */ jscx.evaluateString(
- jsscope, strActiveStartScript, "pipeline_Start", 1, null);
- errorMessage = "Found Start Script. " + strActiveStartScriptName + " Processing OK";
- cr = new CheckResult(ICheckResult.TYPE_RESULT_OK, errorMessage, transformMeta);
- remarks.add(cr);
- }
- } catch (Exception e) {
- errorMessage = "Couldn't process Start Script! Error:" + Const.CR + e.toString();
- cr = new CheckResult(ICheckResult.TYPE_RESULT_ERROR, errorMessage, transformMeta);
- remarks.add(cr);
- }
-
- try {
- jsscript = jscx.compileString(strActiveScript, "script", 1, null);
-
- cr =
- new CheckResult(
- ICheckResult.TYPE_RESULT_OK,
- BaseMessages.getString(PKG, "ScriptValuesMetaMod.CheckResult.ScriptCompiledOK"),
- transformMeta);
- remarks.add(cr);
-
- try {
-
- jsscript.exec(jscx, jsscope);
-
- cr =
- new CheckResult(
- ICheckResult.TYPE_RESULT_OK,
- BaseMessages.getString(PKG, "ScriptValuesMetaMod.CheckResult.ScriptCompiledOK2"),
- transformMeta);
- remarks.add(cr);
-
- if (fieldname.length > 0) {
- StringBuilder message =
- new StringBuilder(
- BaseMessages.getString(
- PKG,
- "ScriptValuesMetaMod.CheckResult.FailedToGetValues",
- String.valueOf(fieldname.length))
- + Const.CR
- + Const.CR);
-
- if (errorFound) {
- cr =
- new CheckResult(
- ICheckResult.TYPE_RESULT_ERROR, message.toString(), transformMeta);
- } else {
- cr = new CheckResult(ICheckResult.TYPE_RESULT_OK, message.toString(), transformMeta);
- }
- remarks.add(cr);
- }
- } catch (JavaScriptException jse) {
- Context.exit();
- errorMessage =
- BaseMessages.getString(PKG, "ScriptValuesMetaMod.CheckResult.CouldNotExecuteScript")
- + Const.CR
- + jse.toString();
- cr = new CheckResult(ICheckResult.TYPE_RESULT_ERROR, errorMessage, transformMeta);
- remarks.add(cr);
- } catch (Exception e) {
- Context.exit();
- errorMessage =
- BaseMessages.getString(PKG, "ScriptValuesMetaMod.CheckResult.CouldNotExecuteScript2")
- + Const.CR
- + e.toString();
- cr = new CheckResult(ICheckResult.TYPE_RESULT_ERROR, errorMessage, transformMeta);
- remarks.add(cr);
- }
-
- // Checking End Script
- try {
- if (!Utils.isEmpty(strActiveEndScript)) {
- /* Object endScript = */ jscx.evaluateString(
- jsscope, strActiveEndScript, "pipeline_End", 1, null);
- errorMessage = "Found End Script. " + strActiveEndScriptName + " Processing OK";
- cr = new CheckResult(ICheckResult.TYPE_RESULT_OK, errorMessage, transformMeta);
- remarks.add(cr);
- }
- } catch (Exception e) {
- errorMessage = "Couldn't process End Script! Error:" + Const.CR + e.toString();
- cr = new CheckResult(ICheckResult.TYPE_RESULT_ERROR, errorMessage, transformMeta);
- remarks.add(cr);
- }
- } catch (Exception e) {
- Context.exit();
- errorMessage =
- BaseMessages.getString(PKG, "ScriptValuesMetaMod.CheckResult.CouldNotCompileScript")
- + Const.CR
- + e.toString();
- cr = new CheckResult(ICheckResult.TYPE_RESULT_ERROR, errorMessage, transformMeta);
- remarks.add(cr);
- }
+ checkStartScript(
+ transformMeta,
+ jsContext,
+ jsScope,
+ strActiveStartScript,
+ strActiveStartScriptName,
+ remarks);
+ checkTransformScript(transformMeta, jsContext, jsScope, strActiveStartScript, remarks);
+ checkEndScript(
+ transformMeta, jsContext, jsScope, strActiveEndScript, strActiveEndScriptName, remarks);
} else {
Context.exit();
errorMessage =
@@ -783,100 +419,147 @@ public class ScriptValuesMeta extends BaseTransformMeta<ScriptValues, ScriptValu
}
}
- public String getFunctionFromScript(String strFunction, String strScript) {
- String sRC = "";
- int iStartPos = strScript.indexOf(strFunction);
- if (iStartPos > 0) {
- iStartPos = strScript.indexOf('{', iStartPos);
- int iCounter = 1;
- while (iCounter != 0) {
- if (strScript.charAt(iStartPos++) == '{') {
- iCounter++;
- } else if (strScript.charAt(iStartPos++) == '}') {
- iCounter--;
- }
- sRC = sRC + strScript.charAt(iStartPos);
- }
+ private void checkTransformScript(
+ TransformMeta transformMeta,
+ Context jsContext,
+ ScriptableObject jsScope,
+ String strActiveScript,
+ List<ICheckResult> remarks) {
+ try {
+ Script jsscript = jsContext.compileString(strActiveScript, "script", 1, null);
+ CheckResult cr =
+ new CheckResult(
+ ICheckResult.TYPE_RESULT_OK,
+ BaseMessages.getString(PKG, "ScriptValuesMetaMod.CheckResult.ScriptCompiledOK"),
+ transformMeta);
+ remarks.add(cr);
+
+ checkTransformScriptExecution(transformMeta, jsContext, jsScope, remarks, jsscript);
+ } catch (Exception e) {
+ Context.exit();
+ String errorMessage =
+ BaseMessages.getString(PKG, "ScriptValuesMetaMod.CheckResult.CouldNotCompileScript")
+ + Const.CR
+ + e;
+ CheckResult cr = new CheckResult(ICheckResult.TYPE_RESULT_ERROR, errorMessage, transformMeta);
+ remarks.add(cr);
}
- return sRC;
}
- // This is for Additional Classloading
- public void parseXmlForAdditionalClasses() throws HopException {
+ private void checkTransformScriptExecution(
+ TransformMeta transformMeta,
+ Context jsContext,
+ ScriptableObject jsScope,
+ List<ICheckResult> remarks,
+ Script jsscript) {
+ CheckResult cr;
try {
- Properties sysprops = System.getProperties();
- String strActPath = sysprops.getProperty("user.dir");
- Document dom =
- XmlHandler.loadXmlFile(strActPath + "/plugins/transforms/ScriptValues_mod/plugin.xml");
- Node transformNode = dom.getDocumentElement();
- Node libraries = XmlHandler.getSubNode(transformNode, "js_libraries");
- int nbOfLibs = XmlHandler.countNodes(libraries, "js_lib");
- additionalClasses = new ScriptValuesAddClasses[nbOfLibs];
- for (int i = 0; i < nbOfLibs; i++) {
- Node fnode = XmlHandler.getSubNodeByNr(libraries, "js_lib", i);
- String strJarName = XmlHandler.getTagAttribute(fnode, "name");
- String strClassName = XmlHandler.getTagAttribute(fnode, "classname");
- String strJSName = XmlHandler.getTagAttribute(fnode, "js_name");
-
- Class<?> addClass =
- LoadAdditionalClass(
- strActPath + "/plugins/transforms/ScriptValues_mod/" + strJarName, strClassName);
- Object addObject = addClass.newInstance();
- additionalClasses[i] = new ScriptValuesAddClasses(addClass, addObject, strJSName);
+ jsscript.exec(jsContext, jsScope, jsScope);
+ cr =
+ new CheckResult(
+ ICheckResult.TYPE_RESULT_OK,
+ BaseMessages.getString(PKG, "ScriptValuesMetaMod.CheckResult.ScriptCompiledOK2"),
+ transformMeta);
+ remarks.add(cr);
+
+ if (!scriptFields.isEmpty()) {
+ String message =
+ BaseMessages.getString(
+ PKG,
+ "ScriptValuesMetaMod.CheckResult.FailedToGetValues",
+ String.valueOf(scriptFields.size()))
+ + Const.CR
+ + Const.CR;
+
+ cr = new CheckResult(ICheckResult.TYPE_RESULT_OK, message, transformMeta);
+ remarks.add(cr);
}
+ } catch (JavaScriptException jse) {
+ Context.exit();
+ String errorMessage =
+ BaseMessages.getString(PKG, "ScriptValuesMetaMod.CheckResult.CouldNotExecuteScript")
+ + Const.CR
+ + jse;
+ cr = new CheckResult(ICheckResult.TYPE_RESULT_ERROR, errorMessage, transformMeta);
+ remarks.add(cr);
} catch (Exception e) {
- throw new HopException(
- BaseMessages.getString(
- PKG, "ScriptValuesMetaMod.Exception.UnableToParseXMLforAdditionalClasses"),
- e);
+ Context.exit();
+ String errorMessage =
+ BaseMessages.getString(PKG, "ScriptValuesMetaMod.CheckResult.CouldNotExecuteScript2")
+ + Const.CR
+ + e;
+ cr = new CheckResult(ICheckResult.TYPE_RESULT_ERROR, errorMessage, transformMeta);
+ remarks.add(cr);
}
}
- private static Class<?> LoadAdditionalClass(String strJar, String strClassName)
- throws HopException {
+ private void checkStartScript(
+ TransformMeta transformMeta,
+ Context jsContext,
+ ScriptableObject jsScope,
+ String strActiveStartScript,
+ String strActiveStartScriptName,
+ List<ICheckResult> remarks) {
try {
- Thread t = Thread.currentThread();
- ClassLoader cl = t.getContextClassLoader();
- URL u = new URL("jar:file:" + strJar + "!/");
- // We never know what else the script wants to load with the class loader, so lets not close
- // it just like that.
- HopURLClassLoader kl = new HopURLClassLoader(new URL[] {u}, cl);
- return kl.loadClass(strClassName);
+ // Checking for StartScript
+ if (!Utils.isEmpty(strActiveStartScript)) {
+ jsContext.evaluateString(jsScope, strActiveStartScript, "pipeline_Start", 1, null);
+ String errorMessage = "Found Start Script. " + strActiveStartScriptName + " Processing OK";
+ CheckResult cr = new CheckResult(ICheckResult.TYPE_RESULT_OK, errorMessage, transformMeta);
+ remarks.add(cr);
+ }
} catch (Exception e) {
- throw new HopException(
- BaseMessages.getString(PKG, "ScriptValuesMetaMod.Exception.UnableToLoadAdditionalClass"),
- e);
+ String errorMessage = "Couldn't process Start Script! Error:" + Const.CR + e;
+ CheckResult cr = new CheckResult(ICheckResult.TYPE_RESULT_ERROR, errorMessage, transformMeta);
+ remarks.add(cr);
}
}
- public ScriptValuesAddClasses[] getAddClasses() {
- return additionalClasses;
- }
-
- @Override
- public boolean supportsErrorHandling() {
- return true;
- }
-
- /**
- * @return the replace
- */
- public boolean[] getReplace() {
- return replace;
- }
-
- /**
- * @param replace the replace to set
- */
- public void setReplace(boolean[] replace) {
- this.replace = replace;
+ /** Checking End Script */
+ private void checkEndScript(
+ TransformMeta transformMeta,
+ Context jsContext,
+ ScriptableObject jsScope,
+ String strActiveEndScript,
+ String strActiveEndScriptName,
+ List<ICheckResult> remarks) {
+ try {
+ if (!Utils.isEmpty(strActiveEndScript)) {
+ jsContext.evaluateString(jsScope, strActiveEndScript, "pipeline_End", 1, null);
+ String errorMessage = "Found End Script. " + strActiveEndScriptName + " Processing OK";
+ CheckResult cr = new CheckResult(ICheckResult.TYPE_RESULT_OK, errorMessage, transformMeta);
+ remarks.add(cr);
+ }
+ } catch (Exception e) {
+ String errorMessage = "Couldn't process End Script! Error:" + Const.CR + e;
+ CheckResult cr = new CheckResult(ICheckResult.TYPE_RESULT_ERROR, errorMessage, transformMeta);
+ remarks.add(cr);
+ }
}
- public void setOptimizationLevel(String optimizationLevel) {
- this.optimizationLevel = optimizationLevel;
+ public String getFunctionFromScript(String strFunction, String strScript) {
+ StringBuilder sRC = new StringBuilder();
+ int iStartPos = strScript.indexOf(strFunction);
+ if (iStartPos > 0) {
+ iStartPos = strScript.indexOf('{', iStartPos);
+ int iCounter = 1;
+ while (iCounter != 0) {
+ if (strScript.charAt(iStartPos++) == '{') {
+ iCounter++;
+ } else if (strScript.charAt(iStartPos++) == '}') {
+ iCounter--;
+ }
+ sRC.append(strScript.charAt(iStartPos));
+ }
+ }
+ return sRC.toString();
}
- public String getOptimizationLevel() {
- return this.optimizationLevel;
+ public String[] getJSScriptNames() {
+ String[] strJSNames = new String[jsScripts.size()];
+ for (int i = 0; i < jsScripts.size(); i++) {
+ strJSNames[i] = jsScripts.get(i).getName();
+ }
+ return strJSNames;
}
}
diff --git a/plugins/transforms/javascript/src/main/java/org/apache/hop/pipeline/transforms/javascript/ScriptValuesScript.java b/plugins/transforms/javascript/src/main/java/org/apache/hop/pipeline/transforms/javascript/ScriptValuesScript.java
index d90c7cf69b..00ccad1171 100644
--- a/plugins/transforms/javascript/src/main/java/org/apache/hop/pipeline/transforms/javascript/ScriptValuesScript.java
+++ b/plugins/transforms/javascript/src/main/java/org/apache/hop/pipeline/transforms/javascript/ScriptValuesScript.java
@@ -17,87 +17,65 @@
package org.apache.hop.pipeline.transforms.javascript;
-import org.apache.hop.core.injection.Injection;
+import lombok.Getter;
+import lombok.Setter;
+import org.apache.hop.metadata.api.HopMetadataProperty;
+@Getter
+@Setter
public class ScriptValuesScript {
-
public static final int NORMAL_SCRIPT = -1;
public static final int TRANSFORM_SCRIPT = 0;
public static final int START_SCRIPT = 1;
public static final int END_SCRIPT = 2;
- private int iScriptType;
- private boolean bScriptActive;
+ @HopMetadataProperty(
+ key = "jsScript_type",
+ injectionKey = "SCRIPT_TYPE",
+ injectionKeyDescription = "ScriptValuesMod.Injection.SCRIPT_TYPE")
+ private int type;
- @Injection(name = "SCRIPT_NAME", group = "SCRIPTS")
- private String sScriptName;
+ @HopMetadataProperty(
+ key = "jsScript_name",
+ injectionKey = "SCRIPT_NAME",
+ injectionKeyDescription = "ScriptValuesMod.Injection.SCRIPT_NAME")
+ private String name;
- @Injection(name = "SCRIPT", group = "SCRIPTS")
- private String sScript;
+ @HopMetadataProperty(
+ key = "jsScript_script",
+ injectionKey = "SCRIPT",
+ injectionKeyDescription = "ScriptValuesMod.Injection.SCRIPT")
+ private String script;
public ScriptValuesScript() {}
- public ScriptValuesScript(int iScriptType, String sScriptName, String sScript) {
+ public ScriptValuesScript(ScriptValuesScript s) {
super();
- this.iScriptType = iScriptType;
- this.sScriptName = sScriptName;
- this.sScript = sScript;
- bScriptActive = true;
- }
-
- public int getScriptType() {
- return iScriptType;
- }
-
- public void setScriptType(int iScriptType) {
- this.iScriptType = iScriptType;
- }
-
- public String getScript() {
- return this.sScript;
+ this.type = s.type;
+ this.name = s.name;
+ this.script = s.script;
}
- public void setScript(String sScript) {
- this.sScript = sScript;
- }
-
- public String getScriptName() {
- return sScriptName;
- }
-
- public void setScriptName(String sScriptName) {
- this.sScriptName = sScriptName;
+ public ScriptValuesScript(int type, String name, String script) {
+ this();
+ this.type = type;
+ this.name = name;
+ this.script = script;
}
public boolean isTransformScript() {
- if (this.bScriptActive && this.iScriptType == TRANSFORM_SCRIPT) {
- return true;
- } else {
- return false;
- }
+ return this.type == TRANSFORM_SCRIPT;
}
public boolean isStartScript() {
- if (this.bScriptActive && this.iScriptType == START_SCRIPT) {
- return true;
- } else {
- return false;
- }
+ return this.type == START_SCRIPT;
}
public boolean isEndScript() {
- if (this.bScriptActive && this.iScriptType == END_SCRIPT) {
- return true;
- } else {
- return false;
- }
- }
-
- public boolean isActive() {
- return bScriptActive;
+ return this.type == END_SCRIPT;
}
public String toString() {
- return String.format("ScriptValuesScript: (%d, %s, %s)", iScriptType, sScriptName, sScript);
+ return String.format("ScriptValuesScript: (%d, %s, %s)", type, name, script);
}
}
diff --git a/plugins/transforms/javascript/src/main/resources/org/apache/hop/pipeline/transforms/javascript/messages/messages_en_US.properties b/plugins/transforms/javascript/src/main/resources/org/apache/hop/pipeline/transforms/javascript/messages/messages_en_US.properties
index 366eb43e36..34c0d78773 100644
--- a/plugins/transforms/javascript/src/main/resources/org/apache/hop/pipeline/transforms/javascript/messages/messages_en_US.properties
+++ b/plugins/transforms/javascript/src/main/resources/org/apache/hop/pipeline/transforms/javascript/messages/messages_en_US.properties
@@ -96,6 +96,7 @@ ScriptValuesMod.Injection.FIELD_TYPE=The field type.
ScriptValuesMod.Injection.FIELDS=The output fields to write to.
ScriptValuesMod.Injection.OPTIMIZATION_LEVEL=Specify the level of optimization.
ScriptValuesMod.Injection.SCRIPT=The java script statement.
+ScriptValuesMod.Injection.SCRIPT_TYPE=The type of script: -1=normal, 0=transform, 1=start, 2=end
ScriptValuesMod.Injection.SCRIPT_NAME=The name of the script.
ScriptValuesMod.Injection.SCRIPTS=The java scripts.
ScriptValuesMod.Log.CouldNotAddDefaultConstants=Could not add default constants to the project.
diff --git a/plugins/transforms/javascript/src/test/java/org/apache/hop/pipeline/transforms/javascript/ScriptValuesMetaInjectionTest.java b/plugins/transforms/javascript/src/test/java/org/apache/hop/pipeline/transforms/javascript/ScriptValuesMetaInjectionTest.java
deleted file mode 100644
index 180acd651c..0000000000
--- a/plugins/transforms/javascript/src/test/java/org/apache/hop/pipeline/transforms/javascript/ScriptValuesMetaInjectionTest.java
+++ /dev/null
@@ -1,106 +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.javascript;
-
-import static org.junit.jupiter.api.Assertions.assertEquals;
-
-import org.apache.hop.core.injection.BaseMetadataInjectionTestJunit5;
-import org.apache.hop.core.row.IValueMeta;
-import org.apache.hop.core.row.value.ValueMetaInteger;
-import org.apache.hop.core.row.value.ValueMetaNumber;
-import org.apache.hop.core.row.value.ValueMetaString;
-import org.apache.hop.junit.rules.RestoreHopEngineEnvironmentExtension;
-import org.junit.jupiter.api.BeforeEach;
-import org.junit.jupiter.api.Test;
-import org.junit.jupiter.api.extension.RegisterExtension;
-
-class ScriptValuesMetaInjectionTest extends BaseMetadataInjectionTestJunit5<ScriptValuesMeta> {
-
- @RegisterExtension
- static RestoreHopEngineEnvironmentExtension env = new RestoreHopEngineEnvironmentExtension();
-
- @BeforeEach
- void setup() throws Exception {
- setup(new ScriptValuesMeta());
- }
-
- @Test
- void test() throws Exception {
- check("OPTIMIZATION_LEVEL", () -> meta.getOptimizationLevel());
- check("FIELD_NAME", () -> meta.getFieldname()[0]);
- check("FIELD_RENAME_TO", () -> meta.getRename()[0]);
- check("FIELD_REPLACE", () -> meta.getReplace()[0]);
- check("SCRIPT_NAME", () -> meta.getJSScripts()[0].getScriptName());
- check("SCRIPT", () -> meta.getJSScripts()[0].getScript());
-
- // field type requires special handling, since it's stored as an array of ints, but injected as
- // strings
- skipPropertyTest("FIELD_TYPE");
- IValueMeta mftt = new ValueMetaString("f");
- injector.setProperty(meta, "FIELD_TYPE", setValue(mftt, "String"), "f");
- assertEquals(IValueMeta.TYPE_STRING, meta.getType()[0]);
- // reset the types array, so we can set it again
- meta.setType(new int[] {});
- injector.setProperty(meta, "FIELD_TYPE", setValue(mftt, "Integer"), "f");
- assertEquals(IValueMeta.TYPE_INTEGER, meta.getType()[0]);
-
- // length and precision fields also need special handing, to ensure that we get -1 when the
- // injected string value
- // is empty or null
- skipPropertyTest("FIELD_LENGTH");
- injector.setProperty(meta, "FIELD_LENGTH", setValue(new ValueMetaString(""), ""), "");
- assertEquals(-1, meta.getLength()[0]);
- injector.setProperty(meta, "FIELD_LENGTH", setValue(new ValueMetaString(" "), " "), " ");
- assertEquals(-1, meta.getLength()[0]);
- injector.setProperty(meta, "FIELD_LENGTH", setValue(new ValueMetaString(null), null), null);
- assertEquals(-1, meta.getLength()[0]);
- injector.setProperty(meta, "FIELD_LENGTH", setValue(new ValueMetaString("5"), "5"), "5");
- assertEquals(5, meta.getLength()[0]);
- injector.setProperty(meta, "FIELD_LENGTH", setValue(new ValueMetaInteger("5"), 5L), "5");
- assertEquals(5, meta.getLength()[0]);
- injector.setProperty(
- meta, "FIELD_LENGTH", setValue(new ValueMetaInteger("5"), (Long) null), "5");
- assertEquals(-1, meta.getLength()[0]);
- injector.setProperty(meta, "FIELD_LENGTH", setValue(new ValueMetaNumber("5"), 5.0), "5");
- assertEquals(5, meta.getLength()[0]);
- injector.setProperty(
- meta, "FIELD_LENGTH", setValue(new ValueMetaInteger("5"), (Double) null), "5");
- assertEquals(-1, meta.getLength()[0]);
-
- skipPropertyTest("FIELD_PRECISION");
- injector.setProperty(meta, "FIELD_PRECISION", setValue(new ValueMetaString(""), ""), "");
- assertEquals(-1, meta.getPrecision()[0]);
- injector.setProperty(meta, "FIELD_PRECISION", setValue(new ValueMetaString(" "), " "), " ");
- assertEquals(-1, meta.getPrecision()[0]);
- injector.setProperty(meta, "FIELD_PRECISION", setValue(new ValueMetaString(null), null), null);
- assertEquals(-1, meta.getPrecision()[0]);
- injector.setProperty(meta, "FIELD_PRECISION", setValue(new ValueMetaString("5"), "5"), "5");
- assertEquals(5, meta.getPrecision()[0]);
- injector.setProperty(meta, "FIELD_PRECISION", setValue(new ValueMetaInteger("5"), 5L), "5");
- assertEquals(5, meta.getPrecision()[0]);
- injector.setProperty(
- meta, "FIELD_PRECISION", setValue(new ValueMetaInteger("5"), (Long) null), "5");
- assertEquals(-1, meta.getPrecision()[0]);
- injector.setProperty(meta, "FIELD_PRECISION", setValue(new ValueMetaNumber("5"), 5.0), "5");
- assertEquals(5, meta.getPrecision()[0]);
- injector.setProperty(
- meta, "FIELD_PRECISION", setValue(new ValueMetaInteger("5"), (Double) null), "5");
- assertEquals(-1, meta.getPrecision()[0]);
- }
-}
diff --git a/plugins/transforms/javascript/src/test/java/org/apache/hop/pipeline/transforms/javascript/ScriptValuesMetaTest.java b/plugins/transforms/javascript/src/test/java/org/apache/hop/pipeline/transforms/javascript/ScriptValuesMetaTest.java
index dec109a92d..018d10a9ec 100644
--- a/plugins/transforms/javascript/src/test/java/org/apache/hop/pipeline/transforms/javascript/ScriptValuesMetaTest.java
+++ b/plugins/transforms/javascript/src/test/java/org/apache/hop/pipeline/transforms/javascript/ScriptValuesMetaTest.java
@@ -17,195 +17,80 @@
package org.apache.hop.pipeline.transforms.javascript;
import static org.junit.jupiter.api.Assertions.assertEquals;
-import static org.junit.jupiter.api.Assertions.assertFalse;
-import static org.junit.jupiter.api.Assertions.assertNull;
+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 java.util.Random;
-import java.util.UUID;
-import org.apache.hop.core.HopEnvironment;
+import org.apache.hop.core.exception.HopException;
import org.apache.hop.core.plugins.PluginRegistry;
-import org.apache.hop.junit.rules.RestoreHopEngineEnvironmentExtension;
-import org.apache.hop.pipeline.transform.ITransformMeta;
-import org.apache.hop.pipeline.transforms.loadsave.LoadSaveTester;
-import org.apache.hop.pipeline.transforms.loadsave.initializer.IInitializer;
-import org.apache.hop.pipeline.transforms.loadsave.validator.ArrayLoadSaveValidator;
-import org.apache.hop.pipeline.transforms.loadsave.validator.BooleanLoadSaveValidator;
-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.PrimitiveBooleanArrayLoadSaveValidator;
-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 org.apache.hop.core.row.value.ValueMetaDate;
+import org.apache.hop.core.row.value.ValueMetaInteger;
+import org.apache.hop.core.row.value.ValueMetaNumber;
+import org.apache.hop.core.row.value.ValueMetaPlugin;
+import org.apache.hop.core.row.value.ValueMetaPluginType;
+import org.apache.hop.core.row.value.ValueMetaString;
+import org.apache.hop.pipeline.transform.TransformSerializationTestUtil;
+import org.junit.jupiter.api.BeforeAll;
import org.junit.jupiter.api.Test;
-import org.junit.jupiter.api.extension.RegisterExtension;
-class ScriptValuesMetaTest implements IInitializer<ITransformMeta> {
- @RegisterExtension
- static RestoreHopEngineEnvironmentExtension env = new RestoreHopEngineEnvironmentExtension();
-
- LoadSaveTester loadSaveTester;
- Class<ScriptValuesMeta> testMetaClass = ScriptValuesMeta.class;
-
- @BeforeEach
- void setUpLoadSave() throws Exception {
- HopEnvironment.init();
- PluginRegistry.init();
- List<String> attributes =
- Arrays.asList(
- "fieldname",
- "rename",
- "type",
- "length",
- "precision",
- "replace",
- "jsScripts",
- "optimizationLevel");
-
- Map<String, String> getterMap =
- new HashMap<>() {
- {
- put("fieldname", "getFieldname");
- put("rename", "getRename");
- put("type", "getType");
- put("length", "getLength");
- put("precision", "getPrecision");
- put("replace", "getReplace");
- // put( "compatible", "isCompatible" );
- put("optimizationLevel", "getOptimizationLevel");
- put("jsScripts", "getJSScripts");
- }
- };
- Map<String, String> setterMap =
- new HashMap<>() {
- {
- put("fieldname", "setFieldname");
- put("rename", "setRename");
- put("type", "setType");
- put("length", "setLength");
- put("precision", "setPrecision");
- put("replace", "setReplace");
- // put( "compatible", "setCompatible" );
- put("optimizationLevel", "setOptimizationLevel");
- put("jsScripts", "setJSScripts");
- }
- };
- IFieldLoadSaveValidator<String[]> stringArrayLoadSaveValidator =
- new ArrayLoadSaveValidator<>(new StringLoadSaveValidator(), 5);
-
- IFieldLoadSaveValidator<ScriptValuesScript[]> svsArrayLoadSaveValidator =
- new ArrayLoadSaveValidator<>(new ScriptValuesScriptLoadSaveValidator(), 5);
-
- Map<String, IFieldLoadSaveValidator<?>> attrValidatorMap = new HashMap<>();
- attrValidatorMap.put("fieldname", stringArrayLoadSaveValidator);
- attrValidatorMap.put("rename", stringArrayLoadSaveValidator);
- attrValidatorMap.put(
- "type", new PrimitiveIntArrayLoadSaveValidator(new IntLoadSaveValidator(9), 5));
- attrValidatorMap.put(
- "length", new PrimitiveIntArrayLoadSaveValidator(new IntLoadSaveValidator(100), 5));
- attrValidatorMap.put(
- "precision", new PrimitiveIntArrayLoadSaveValidator(new IntLoadSaveValidator(6), 5));
- attrValidatorMap.put(
- "replace", new PrimitiveBooleanArrayLoadSaveValidator(new BooleanLoadSaveValidator(), 5));
- attrValidatorMap.put("jsScripts", svsArrayLoadSaveValidator);
-
- Map<String, IFieldLoadSaveValidator<?>> typeValidatorMap = new HashMap<>();
-
- loadSaveTester =
- new LoadSaveTester(
- testMetaClass,
- attributes,
- getterMap,
- setterMap,
- attrValidatorMap,
- typeValidatorMap,
- this);
- }
-
- // Call the allocate method on the LoadSaveTester meta class
- @Override
- public void modify(ITransformMeta someMeta) {
- if (someMeta instanceof ScriptValuesMeta) {
- ((ScriptValuesMeta) someMeta).allocate(5);
- }
- }
-
- public class ScriptValuesScriptLoadSaveValidator
- implements IFieldLoadSaveValidator<ScriptValuesScript> {
- final Random rand = new Random();
-
- @Override
- public ScriptValuesScript getTestObject() {
- int scriptType = rand.nextInt(4);
- if (scriptType == 3) {
- scriptType = -1;
- }
- return new ScriptValuesScript(
- scriptType, UUID.randomUUID().toString(), UUID.randomUUID().toString());
- }
-
- @Override
- public boolean validateTestObject(ScriptValuesScript testObject, Object actual) {
- if (!(actual instanceof ScriptValuesScript)) {
- return false;
- }
- return (actual.toString().equals(testObject.toString()));
- }
+class ScriptValuesMetaTest {
+ @BeforeAll
+ static void beforeAll() throws HopException {
+ PluginRegistry registry = PluginRegistry.getInstance();
+ registry.registerPluginClass(
+ ValueMetaString.class.getName(), ValueMetaPluginType.class, ValueMetaPlugin.class);
+ registry.registerPluginClass(
+ ValueMetaInteger.class.getName(), ValueMetaPluginType.class, ValueMetaPlugin.class);
+ registry.registerPluginClass(
+ ValueMetaNumber.class.getName(), ValueMetaPluginType.class, ValueMetaPlugin.class);
+ registry.registerPluginClass(
+ ValueMetaDate.class.getName(), ValueMetaPluginType.class, ValueMetaPlugin.class);
}
@Test
- void testExtend() {
- ScriptValuesMeta meta = new ScriptValuesMeta();
- int size = 1;
- meta.extend(size);
-
- assertEquals(size, meta.getFieldname().length);
- assertNull(meta.getFieldname()[0]);
- assertEquals(size, meta.getRename().length);
- assertNull(meta.getRename()[0]);
- assertEquals(size, meta.getType().length);
- assertEquals(-1, meta.getType()[0]);
- assertEquals(size, meta.getLength().length);
- assertEquals(-1, meta.getLength()[0]);
- assertEquals(size, meta.getPrecision().length);
- assertEquals(-1, meta.getPrecision()[0]);
- assertEquals(size, meta.getReplace().length);
- assertFalse(meta.getReplace()[0]);
-
- meta = new ScriptValuesMeta();
-
- meta.extend(3);
- validateExtended(meta);
- }
-
- private void validateExtended(final ScriptValuesMeta meta) {
-
- assertEquals(3, meta.getFieldname().length);
- // assertEquals("Field 1", meta.getFieldname()[0]);
- // assertEquals("Field 2", meta.getFieldname()[1]);
- // assertEquals("Field 3", meta.getFieldname()[2]);
- // assertEquals(3, meta.getRename().length);
- // assertEquals("Field 1 - new", meta.getRename()[0]);
- // assertNull(meta.getRename()[1]);
- // assertNull(meta.getRename()[2]);
- // assertEquals(3, meta.getType().length);
- // assertEquals(IValueMeta.TYPE_STRING, meta.getType()[0]);
- // assertEquals(IValueMeta.TYPE_INTEGER, meta.getType()[1]);
- // assertEquals(IValueMeta.TYPE_NUMBER, meta.getType()[2]);
- // assertEquals(3, meta.getLength().length);
- // assertEquals(-1, meta.getLength()[0]);
- // assertEquals(-1, meta.getLength()[1]);
- // assertEquals(-1, meta.getLength()[2]);
- // assertEquals(3, meta.getPrecision().length);
- // assertEquals(-1, meta.getPrecision()[0]);
- // assertEquals(-1, meta.getPrecision()[1]);
- // assertEquals(-1, meta.getPrecision()[2]);
- // assertEquals(3, meta.getReplace().length);
- // assertFalse(meta.getReplace()[0]);
- // assertFalse(meta.getReplace()[1]);
- // assertFalse(meta.getReplace()[2]);
+ void testXmlRoundTrip() throws Exception {
+ // Test XML->Meta->XML->Meta
+ ScriptValuesMeta meta =
+ TransformSerializationTestUtil.testSerialization("/javascript.xml", ScriptValuesMeta.class);
+
+ // See if after all that we still have the correct data
+ //
+ assertEquals("2", meta.getOptimizationLevel());
+
+ // The scripts
+ assertEquals(3, meta.getJsScripts().size());
+ ScriptValuesScript s = meta.getJsScripts().getFirst();
+ assertEquals("startScript", s.getName());
+ assertEquals("startScript", s.getScript());
+ assertEquals(1, s.getType());
+ s = meta.getJsScripts().get(1);
+ assertEquals("transformScript", s.getName());
+ assertEquals("transformScript", s.getScript());
+ assertEquals(0, s.getType());
+ s = meta.getJsScripts().getLast();
+ assertEquals("endScript", s.getName());
+ assertEquals("endScript", s.getScript());
+ assertEquals(2, s.getType());
+
+ // The fields
+ assertEquals(3, meta.getScriptFields().size());
+ ScriptValuesMeta.ScriptField f = meta.getScriptFields().getFirst();
+ assertEquals("f1", f.getName());
+ assertEquals("renamedF1", f.getRename());
+ assertEquals(100, f.getLength());
+ assertEquals(-1, f.getPrecision());
+ assertTrue(f.isReplace());
+
+ f = meta.getScriptFields().get(1);
+ assertEquals("f2", f.getName());
+ assertEquals("renamedF2", f.getRename());
+ assertEquals(7, f.getLength());
+ assertEquals(-1, f.getPrecision());
+ assertTrue(f.isReplace());
+
+ f = meta.getScriptFields().getLast();
+ assertEquals("f3", f.getName());
+ assertEquals("renamedF3", f.getRename());
+ assertEquals(9, f.getLength());
+ assertEquals(2, f.getPrecision());
+ assertTrue(f.isReplace());
}
}
diff --git a/plugins/transforms/javascript/src/test/java/org/apache/hop/pipeline/transforms/javascript/ScriptValuesTest.java b/plugins/transforms/javascript/src/test/java/org/apache/hop/pipeline/transforms/javascript/ScriptValuesTest.java
index 1f0b0228b2..f19186eed1 100644
--- a/plugins/transforms/javascript/src/test/java/org/apache/hop/pipeline/transforms/javascript/ScriptValuesTest.java
+++ b/plugins/transforms/javascript/src/test/java/org/apache/hop/pipeline/transforms/javascript/ScriptValuesTest.java
@@ -58,20 +58,24 @@ class ScriptValuesTest {
doReturn(new Object[] {BigDecimal.ONE, BigDecimal.ONE}).when(transform).getRow();
ScriptValuesMeta meta = new ScriptValuesMeta();
- meta.allocate(2);
- meta.setFieldname(new String[] {"value_int", "value_double"});
- meta.setType(new int[] {IValueMeta.TYPE_BIGNUMBER, IValueMeta.TYPE_BIGNUMBER});
- meta.setReplace(new boolean[] {true, true});
-
- meta.setJSScripts(
- new ScriptValuesScript[] {
- new ScriptValuesScript(
- ScriptValuesScript.TRANSFORM_SCRIPT,
- "script",
- "value_int = 10.00;\nvalue_double = 10.50")
- });
-
- ScriptValuesData data = new ScriptValuesData();
+ ScriptValuesMeta.ScriptField f1 = new ScriptValuesMeta.ScriptField();
+ f1.setName("value_int");
+ f1.setType(IValueMeta.TYPE_BIGNUMBER);
+ f1.setReplace(true);
+ meta.getScriptFields().add(f1);
+ ScriptValuesMeta.ScriptField f2 = new ScriptValuesMeta.ScriptField();
+ f2.setName("value_double");
+ f2.setType(IValueMeta.TYPE_BIGNUMBER);
+ f2.setReplace(true);
+ meta.getScriptFields().add(f2);
+
+ meta.getJsScripts()
+ .add(
+ new ScriptValuesScript(
+ ScriptValuesScript.TRANSFORM_SCRIPT,
+ "script",
+ "value_int = 10.00;\nvalue_double = 10.50"));
+
transform.init();
Object[] expectedRow = {BigDecimal.TEN, new BigDecimal("10.5")};
@@ -94,20 +98,19 @@ class ScriptValuesTest {
doReturn(new Object[] {""}).when(transform).getRow();
ScriptValuesMeta meta = new ScriptValuesMeta();
- meta.allocate(1);
- meta.setFieldname(new String[] {"str"});
- meta.setType(new int[] {IValueMeta.TYPE_STRING});
- meta.setReplace(new boolean[] {true});
-
- meta.setJSScripts(
- new ScriptValuesScript[] {
- new ScriptValuesScript(
- ScriptValuesScript.TRANSFORM_SCRIPT,
- "script",
- "setVariable('temp', 'pass', 'r');\nstr = getVariable('temp', 'fail');")
- });
-
- ScriptValuesData data = new ScriptValuesData();
+ ScriptValuesMeta.ScriptField f1 = new ScriptValuesMeta.ScriptField();
+ f1.setName("str");
+ f1.setType(IValueMeta.TYPE_STRING);
+ f1.setReplace(true);
+ meta.getScriptFields().add(f1);
+
+ meta.getJsScripts()
+ .add(
+ new ScriptValuesScript(
+ ScriptValuesScript.TRANSFORM_SCRIPT,
+ "script",
+ "setVariable('temp', 'pass', 'r');\nstr = getVariable('temp', 'fail');"));
+
transform.init();
Object[] expectedRow = {"pass"};
diff --git a/plugins/transforms/javascript/src/test/resources/javascript.xml b/plugins/transforms/javascript/src/test/resources/javascript.xml
new file mode 100644
index 0000000000..964c6d5e31
--- /dev/null
+++ b/plugins/transforms/javascript/src/test/resources/javascript.xml
@@ -0,0 +1,65 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+ ~ Licensed to the Apache Software Foundation (ASF) under one or more
+ ~ contributor license agreements. See the NOTICE file distributed with
+ ~ this work for additional information regarding copyright ownership.
+ ~ The ASF licenses this file to You under the Apache License, Version 2.0
+ ~ (the "License"); you may not use this file except in compliance with
+ ~ the License. You may obtain a copy of the License at
+ ~
+ ~ http://www.apache.org/licenses/LICENSE-2.0
+ ~
+ ~ Unless required by applicable law or agreed to in writing, software
+ ~ distributed under the License is distributed on an "AS IS" BASIS,
+ ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ ~ See the License for the specific language governing permissions and
+ ~ limitations under the License.
+ ~
+ -->
+
+<transform>
+ <optimizationLevel>2</optimizationLevel>
+ <jsScripts>
+ <jsScript>
+ <jsScript_type>1</jsScript_type>
+ <jsScript_name>startScript</jsScript_name>
+ <jsScript_script>startScript</jsScript_script>
+ </jsScript>
+ <jsScript>
+ <jsScript_type>0</jsScript_type>
+ <jsScript_name>transformScript</jsScript_name>
+ <jsScript_script>transformScript</jsScript_script>
+ </jsScript>
+ <jsScript>
+ <jsScript_type>2</jsScript_type>
+ <jsScript_name>endScript</jsScript_name>
+ <jsScript_script>endScript</jsScript_script>
+ </jsScript>
+ </jsScripts>
+ <fields>
+ <field>
+ <name>f1</name>
+ <rename>renamedF1</rename>
+ <type>String</type>
+ <length>100</length>
+ <precision>-1</precision>
+ <replace>Y</replace>
+ </field>
+ <field>
+ <name>f2</name>
+ <rename>renamedF2</rename>
+ <type>Integer</type>
+ <length>7</length>
+ <precision>-1</precision>
+ <replace>Y</replace>
+ </field>
+ <field>
+ <name>f3</name>
+ <rename>renamedF3</rename>
+ <type>Number</type>
+ <length>9</length>
+ <precision>2</precision>
+ <replace>Y</replace>
+ </field>
+ </fields>
+</transform>