This is an automated email from the ASF dual-hosted git repository.

hansva pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/hop.git


The following commit(s) were added to refs/heads/master by this push:
     new d19d4244a0 HOP-4312 Cleanup XML of transform If Null
     new d7c1eb54c4 Merge pull request #1854 from nadment/HOP-4312
d19d4244a0 is described below

commit d19d4244a0123c33bc61023b65543821ef4acf12
Author: Nicolas Adment <[email protected]>
AuthorDate: Wed Nov 30 22:14:36 2022 +0100

    HOP-4312 Cleanup XML of transform If Null
---
 .../hop/pipeline/transforms/ifnull/Field.java      |  97 +++++++
 .../hop/pipeline/transforms/ifnull/IfNull.java     |  38 +--
 .../pipeline/transforms/ifnull/IfNullDialog.java   |  85 +++---
 .../hop/pipeline/transforms/ifnull/IfNullMeta.java | 322 ++++-----------------
 .../hop/pipeline/transforms/ifnull/ValueType.java  |  80 +++++
 .../transforms/ifnull/IfNullMetaInjectionTest.java |  18 +-
 .../pipeline/transforms/ifnull/IfNullMetaTest.java | 200 ++++---------
 .../hop/pipeline/transforms/ifnull/IfNullTest.java |  16 +-
 .../pipeline/transforms/ifnull/PDI_11319Test.java  |  96 ------
 .../src/test/resources/if-null-transform-field.xml |  55 ++++
 .../resources/if-null-transform-value-type.xml     |  59 ++++
 .../apache/hop/pipeline/transforms/ifnull/v4.hpl   | 166 -----------
 .../apache/hop/pipeline/transforms/ifnull/v5.hpl   | 194 -------------
 13 files changed, 485 insertions(+), 941 deletions(-)

diff --git 
a/plugins/transforms/ifnull/src/main/java/org/apache/hop/pipeline/transforms/ifnull/Field.java
 
b/plugins/transforms/ifnull/src/main/java/org/apache/hop/pipeline/transforms/ifnull/Field.java
new file mode 100644
index 0000000000..b02582ac33
--- /dev/null
+++ 
b/plugins/transforms/ifnull/src/main/java/org/apache/hop/pipeline/transforms/ifnull/Field.java
@@ -0,0 +1,97 @@
+/*
+ * 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.ifnull;
+
+import org.apache.hop.metadata.api.HopMetadataProperty;
+import java.util.Objects;
+
+public class Field {
+
+    @HopMetadataProperty(key = "name", injectionKey = "FIELD_NAME", 
injectionKeyDescription = "IfNull.Injection.FIELD_NAME")
+    private String name;
+
+    @HopMetadataProperty(key = "value", injectionKey = "REPLACE_VALUE", 
injectionKeyDescription = "IfNull.Injection.REPLACE_VALUE")
+    private String value;
+    
+    @HopMetadataProperty(key = "mask", injectionKey = "REPLACE_MASK", 
injectionKeyDescription = "IfNull.Injection.REPLACE_MASK")
+    private String mask;
+        
+    @HopMetadataProperty(key = "set_empty_string", injectionKey = 
"SET_EMPTY_STRING", injectionKeyDescription = 
"IfNull.Injection.SET_EMPTY_STRING")
+    private boolean setEmptyString;
+    
+    public Field() {
+    }
+
+    public Field(Field field) {
+        this.name = field.name;
+        this.value = field.value;
+        this.mask = field.mask;
+        this.setEmptyString = field.setEmptyString;
+    }
+
+    public String getName() {
+      return name;
+    }
+
+    public void setName(String fieldName) {
+      this.name = fieldName;
+    }
+
+    public String getValue() {
+      return value;
+    }
+
+    public void setValue(String replaceValue) {
+      this.value = replaceValue;
+    }
+
+    public String getMask() {
+      return mask;
+    }
+
+    public void setMask(String replaceMask) {
+      this.mask = replaceMask;
+    }
+
+    public boolean isSetEmptyString() {
+      return setEmptyString;
+    }
+
+    public void setSetEmptyString(boolean setEmptyString) {
+      this.setEmptyString = setEmptyString;
+    }
+
+    @Override
+    public boolean equals(Object o) {
+        if (this == o) return true;
+        if (o == null || getClass() != o.getClass()) return false;
+        Field field = (Field) o;
+        return Objects.equals(name, field.name) && Objects.equals(value, 
field.value) && Objects.equals(mask, field.mask) && 
this.setEmptyString==field.setEmptyString;
+    }
+
+    @Override
+    public int hashCode() {
+        return Objects.hash(name, value, mask, setEmptyString);
+    }
+
+    @Override
+    public Field clone() {
+        return new Field(this);
+    }
+}
+
diff --git 
a/plugins/transforms/ifnull/src/main/java/org/apache/hop/pipeline/transforms/ifnull/IfNull.java
 
b/plugins/transforms/ifnull/src/main/java/org/apache/hop/pipeline/transforms/ifnull/IfNull.java
index b9da6b9ecd..91e0e696f3 100644
--- 
a/plugins/transforms/ifnull/src/main/java/org/apache/hop/pipeline/transforms/ifnull/IfNull.java
+++ 
b/plugins/transforms/ifnull/src/main/java/org/apache/hop/pipeline/transforms/ifnull/IfNull.java
@@ -71,35 +71,36 @@ public class IfNull extends BaseTransform<IfNullMeta, 
IfNullData> {
 
       if (meta.isSelectFields()) {
         // Consider only selected fields
-        if (meta.getFields() != null && meta.getFields().length > 0) {
-          int fieldsLength = meta.getFields().length;
+        if (meta.getFields() != null && meta.getFields().size() > 0) {
+          int fieldsLength = meta.getFields().size();
           data.fieldnrs = new int[fieldsLength];
           data.defaultValues = new String[fieldsLength];
           data.defaultMasks = new String[fieldsLength];
           data.setEmptyString = new boolean[fieldsLength];
 
-          for (int i = 0; i < meta.getFields().length; i++) {
-            data.fieldnrs[i] = 
data.outputRowMeta.indexOfValue(meta.getFields()[i].getFieldName());
+          for (int i = 0; i < meta.getFields().size(); i++) {
+            Field field = meta.getFields().get(i);
+            data.fieldnrs[i] = 
data.outputRowMeta.indexOfValue(field.getName());
             if (data.fieldnrs[i] < 0) {
               logError(
                   BaseMessages.getString(
-                      PKG, "IfNull.Log.CanNotFindField", 
meta.getFields()[i].getFieldName()));
+                      PKG, "IfNull.Log.CanNotFindField", field.getName()));
               throw new HopException(
                   BaseMessages.getString(
-                      PKG, "IfNull.Log.CanNotFindField", 
meta.getFields()[i].getFieldName()));
+                      PKG, "IfNull.Log.CanNotFindField", field.getName()));
             }
-            data.defaultValues[i] = 
resolve(meta.getFields()[i].getReplaceValue());
-            data.defaultMasks[i] = 
resolve(meta.getFields()[i].getReplaceMask());
-            data.setEmptyString[i] = meta.getFields()[i].isSetEmptyString();
+            data.defaultValues[i] = resolve(field.getValue());
+            data.defaultMasks[i] = resolve(field.getMask());
+            data.setEmptyString[i] = field.isSetEmptyString();
           }
         } else {
           throw new HopException(BaseMessages.getString(PKG, 
"IfNull.Log.SelectFieldsEmpty"));
         }
       } else if (meta.isSelectValuesType()) {
         // Consider only select value types
-        if (meta.getValueTypes() != null && meta.getValueTypes().length > 0) {
+        if (meta.getValueTypes() != null && meta.getValueTypes().size() > 0) {
           // return the real default values
-          int typeLength = meta.getValueTypes().length;
+          int typeLength = meta.getValueTypes().size();
           data.defaultValues = new String[typeLength];
           data.defaultMasks = new String[typeLength];
           data.setEmptyString = new boolean[typeLength];
@@ -110,19 +111,20 @@ public class IfNull extends BaseTransform<IfNullMeta, 
IfNullData> {
             alllistTypes.add(IValueMeta.typeCodes[i]);
           }
 
-          for (int i = 0; i < meta.getValueTypes().length; i++) {
-            if (!alllistTypes.contains(meta.getValueTypes()[i].getTypeName())) 
{
+          for (int i = 0; i < meta.getValueTypes().size(); i++) {
+            ValueType valueType = meta.getValueTypes().get(i);
+            if (!alllistTypes.contains(valueType.getName())) {
               throw new HopException(
                   BaseMessages.getString(
                       PKG,
                       "IfNull.Log.CanNotFindValueType",
-                      meta.getValueTypes()[i].getTypeName()));
+                      valueType.getName()));
             }
 
-            data.ListTypes.put(meta.getValueTypes()[i].getTypeName(), i);
-            data.defaultValues[i] = 
resolve(meta.getValueTypes()[i].getTypereplaceValue());
-            data.defaultMasks[i] = 
resolve(meta.getValueTypes()[i].getTypereplaceMask());
-            data.setEmptyString[i] = 
meta.getValueTypes()[i].isSetTypeEmptyString();
+            data.ListTypes.put(valueType.getName(), i);
+            data.defaultValues[i] = resolve(valueType.getValue());
+            data.defaultMasks[i] = resolve(valueType.getMask());
+            data.setEmptyString[i] = valueType.isSetEmptyString();
           }
 
           HashSet<Integer> fieldsSelectedIndex = new HashSet<>();
diff --git 
a/plugins/transforms/ifnull/src/main/java/org/apache/hop/pipeline/transforms/ifnull/IfNullDialog.java
 
b/plugins/transforms/ifnull/src/main/java/org/apache/hop/pipeline/transforms/ifnull/IfNullDialog.java
index d3b9304b7d..4fad9b7c71 100644
--- 
a/plugins/transforms/ifnull/src/main/java/org/apache/hop/pipeline/transforms/ifnull/IfNullDialog.java
+++ 
b/plugins/transforms/ifnull/src/main/java/org/apache/hop/pipeline/transforms/ifnull/IfNullDialog.java
@@ -110,9 +110,9 @@ public class IfNullDialog extends BaseTransformDialog 
implements ITransformDialo
     formLayout.marginHeight = PropsUi.getFormMargin();
 
     int middle = props.getMiddlePct();
-    margin = props.getMargin();
+    margin = PropsUi.getMargin();
 
-    fieldsRows = input.getFields().length;
+    fieldsRows = input.getFields().size();
 
     shell.setLayout(formLayout);
     shell.setText(BaseMessages.getString(PKG, "IfNullDialog.Shell.Title"));
@@ -284,7 +284,7 @@ public class IfNullDialog extends BaseTransformDialog 
implements ITransformDialo
     fdlValueTypes.top = new FormAttachment(wSelectValuesType, margin);
     wlValueTypes.setLayoutData(fdlValueTypes);
 
-    int valueTypesRows = input.getValueTypes().length;
+    int valueTypesRows = input.getValueTypes().size();
 
     ColumnInfo[] colval =
         new ColumnInfo[] {
@@ -514,24 +514,25 @@ public class IfNullDialog extends BaseTransformDialog 
implements ITransformDialo
     wSelectValuesType.setSelection(input.isSelectValuesType());
 
     Table table = wValueTypes.table;
-    if (input.getValueTypes().length > 0) {
+    if ( !input.getValueTypes().isEmpty() ) {
       table.removeAll();
     }
-    for (int i = 0; i < input.getValueTypes().length; i++) {
+    for (int i = 0; i < input.getValueTypes().size(); i++) {
+      ValueType valueType = input.getValueTypes().get(i);      
       TableItem ti = new TableItem(table, SWT.NONE);
       ti.setText(0, "" + (i + 1));
-      if (input.getValueTypes()[i].getTypeName() != null) {
-        ti.setText(1, input.getValueTypes()[i].getTypeName());
+      if (valueType.getName() != null) {
+        ti.setText(1, valueType.getName());
       }
-      if (input.getValueTypes()[i].getTypereplaceValue() != null) {
-        ti.setText(2, input.getValueTypes()[i].getTypereplaceValue());
+      if (valueType.getValue() != null) {
+        ti.setText(2, valueType.getValue());
       }
-      if (input.getValueTypes()[i].getTypereplaceMask() != null) {
-        ti.setText(3, input.getValueTypes()[i].getTypereplaceMask());
+      if (valueType.getMask() != null) {
+        ti.setText(3, valueType.getMask());
       }
       ti.setText(
           4,
-          input.getValueTypes()[i].isSetTypeEmptyString()
+          valueType.isSetEmptyString()
               ? BaseMessages.getString(PKG, "System.Combo.Yes")
               : BaseMessages.getString(PKG, "System.Combo.No"));
     }
@@ -541,24 +542,25 @@ public class IfNullDialog extends BaseTransformDialog 
implements ITransformDialo
     wValueTypes.optWidth(true);
 
     table = wFields.table;
-    if (input.getFields().length > 0) {
+    if (!input.getFields().isEmpty()) {
       table.removeAll();
     }
-    for (int i = 0; i < input.getFields().length; i++) {
+    for (int i = 0; i < input.getFields().size(); i++) {
+      Field field = input.getFields().get(i);
       TableItem ti = new TableItem(table, SWT.NONE);
       ti.setText(0, "" + (i + 1));
-      if (input.getFields()[i].getFieldName() != null) {
-        ti.setText(1, input.getFields()[i].getFieldName());
+      if (field.getName() != null) {
+        ti.setText(1, field.getName());
       }
-      if (input.getFields()[i].getReplaceValue() != null) {
-        ti.setText(2, input.getFields()[i].getReplaceValue());
+      if (field.getValue() != null) {
+        ti.setText(2, field.getValue());
       }
-      if (input.getFields()[i].getReplaceMask() != null) {
-        ti.setText(3, input.getFields()[i].getReplaceMask());
+      if (field.getMask() != null) {
+        ti.setText(3, field.getMask());
       }
       ti.setText(
           4,
-          input.getFields()[i].isSetEmptyString()
+          field.isSetEmptyString()
               ? BaseMessages.getString(PKG, "System.Combo.Yes")
               : BaseMessages.getString(PKG, "System.Combo.No"));
     }
@@ -587,7 +589,7 @@ public class IfNullDialog extends BaseTransformDialog 
implements ITransformDialo
     }
     transformName = wTransformName.getText(); // return value
 
-    input.setEmptyStringAll(wSetEmptyStringAll.getSelection());
+    input.setSetEmptyStringAll(wSetEmptyStringAll.getSelection());
 
     if (wSetEmptyStringAll.getSelection()) {
       input.setReplaceAllByValue("");
@@ -603,36 +605,39 @@ public class IfNullDialog extends BaseTransformDialog 
implements ITransformDialo
 
     int nrtypes = wValueTypes.nrNonEmpty();
     int nrFields = wFields.nrNonEmpty();
-    input.allocate(nrtypes, nrFields);
-
-    // CHECKSTYLE:Indentation:OFF
+    
+    input.getValueTypes().clear();
     for (int i = 0; i < nrtypes; i++) {
       TableItem ti = wValueTypes.getNonEmpty(i);
-      input.getValueTypes()[i].setTypeName(ti.getText(1));
-      input.getValueTypes()[i].setTypeEmptyString(
+      ValueType valueType = new ValueType();
+      valueType.setName(ti.getText(1));
+      valueType.setSetEmptyString(
           BaseMessages.getString(PKG, 
"System.Combo.Yes").equalsIgnoreCase(ti.getText(4)));
-      if (input.getValueTypes()[i].isSetTypeEmptyString()) {
-        input.getValueTypes()[i].setTypereplaceValue("");
-        input.getValueTypes()[i].setTypereplaceMask("");
+      if (valueType.isSetEmptyString()) {
+        valueType.setValue("");
+        valueType.setMask("");
       } else {
-        input.getValueTypes()[i].setTypereplaceValue(ti.getText(2));
-        input.getValueTypes()[i].setTypereplaceMask(ti.getText(3));
+        valueType.setValue(ti.getText(2));
+        valueType.setMask(ti.getText(3));
       }
+      input.getValueTypes().add(valueType);
     }
 
-    // CHECKSTYLE:Indentation:OFF
+    input.getFields().clear();
     for (int i = 0; i < nrFields; i++) {
       TableItem ti = wFields.getNonEmpty(i);
-      input.getFields()[i].setFieldName(ti.getText(1));
-      input.getFields()[i].setEmptyString(
+      Field field = new Field();
+      field.setName(ti.getText(1));
+      field.setSetEmptyString(
           BaseMessages.getString(PKG, 
"System.Combo.Yes").equalsIgnoreCase(ti.getText(4)));
-      if (input.getFields()[i].isSetEmptyString()) {
-        input.getFields()[i].setReplaceValue("");
-        input.getFields()[i].setReplaceMask("");
+      if (field.isSetEmptyString()) {
+        field.setValue("");
+        field.setMask("");
       } else {
-        input.getFields()[i].setReplaceValue(ti.getText(2));
-        input.getFields()[i].setReplaceMask(ti.getText(3));
+        field.setValue(ti.getText(2));
+        field.setMask(ti.getText(3));
       }
+      input.getFields().add(field);
     }
     dispose();
   }
diff --git 
a/plugins/transforms/ifnull/src/main/java/org/apache/hop/pipeline/transforms/ifnull/IfNullMeta.java
 
b/plugins/transforms/ifnull/src/main/java/org/apache/hop/pipeline/transforms/ifnull/IfNullMeta.java
index 4f93e03d7f..fa868e94bf 100644
--- 
a/plugins/transforms/ifnull/src/main/java/org/apache/hop/pipeline/transforms/ifnull/IfNullMeta.java
+++ 
b/plugins/transforms/ifnull/src/main/java/org/apache/hop/pipeline/transforms/ifnull/IfNullMeta.java
@@ -21,21 +21,15 @@ import org.apache.hop.core.CheckResult;
 import org.apache.hop.core.Const;
 import org.apache.hop.core.ICheckResult;
 import org.apache.hop.core.annotations.Transform;
-import org.apache.hop.core.exception.HopXmlException;
-import org.apache.hop.core.injection.Injection;
-import org.apache.hop.core.injection.InjectionDeep;
-import org.apache.hop.core.injection.InjectionSupported;
 import org.apache.hop.core.row.IRowMeta;
-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;
 import org.apache.hop.pipeline.transform.TransformMeta;
-import org.w3c.dom.Node;
-
+import java.util.ArrayList;
 import java.util.List;
 
 @Transform(
@@ -46,153 +40,54 @@ import java.util.List;
     categoryDescription = 
"i18n:org.apache.hop.pipeline.transform:BaseTransform.Category.Flow",
     keywords = "i18n::IfNullMeta.keyword",
     documentationUrl = "/pipeline/transforms/ifnull.html")
-@InjectionSupported(
-    localizationPrefix = "IfNull.Injection.",
-    groups = {"FIELDS", "VALUE_TYPES"})
 public class IfNullMeta extends BaseTransformMeta<IfNull, IfNullData> {
 
   private static final Class<?> PKG = IfNullMeta.class; // For Translator
 
-  public static class Fields implements Cloneable {
-
-    /** which fields to display? */
-    @Injection(name = "FIELD_NAME", group = "FIELDS")
-    private String fieldName;
-
-    /** by which value we replace */
-    @Injection(name = "REPLACE_VALUE", group = "FIELDS")
-    private String replaceValue;
-
-    @Injection(name = "REPLACE_MASK", group = "FIELDS")
-    private String replaceMask;
-
-    /** Flag : set empty string */
-    @Injection(name = "SET_EMPTY_STRING", group = "FIELDS")
-    private boolean setEmptyString;
-
-    public String getFieldName() {
-      return fieldName;
-    }
-
-    public void setFieldName(String fieldName) {
-      this.fieldName = fieldName;
-    }
-
-    public String getReplaceValue() {
-      return replaceValue;
-    }
-
-    public void setReplaceValue(String replaceValue) {
-      this.replaceValue = replaceValue;
-    }
-
-    public String getReplaceMask() {
-      return replaceMask;
-    }
-
-    public void setReplaceMask(String replaceMask) {
-      this.replaceMask = replaceMask;
-    }
-
-    public boolean isSetEmptyString() {
-      return setEmptyString;
-    }
-
-    public void setEmptyString(boolean setEmptyString) {
-      this.setEmptyString = setEmptyString;
-    }
-
-    @Override
-    public Fields clone() {
-      try {
-        return (Fields) super.clone();
-      } catch (CloneNotSupportedException e) {
-        throw new RuntimeException(e);
-      }
-    }
-  }
-
-  public static class ValueTypes implements Cloneable {
-
-    /** which types to display? */
-    @Injection(name = "TYPE_NAME", group = "VALUE_TYPES")
-    private String typeName;
-
-    /** by which value we replace */
-    @Injection(name = "TYPE_REPLACE_VALUE", group = "VALUE_TYPES")
-    private String typereplaceValue;
-
-    @Injection(name = "TYPE_REPLACE_MASK", group = "VALUE_TYPES")
-    private String typereplaceMask;
-
-    /** Flag : set empty string for type */
-    @Injection(name = "SET_TYPE_EMPTY_STRING", group = "VALUE_TYPES")
-    private boolean setTypeEmptyString;
-
-    public String getTypeName() {
-      return typeName;
-    }
-
-    public void setTypeName(String typeName) {
-      this.typeName = typeName;
-    }
-
-    public String getTypereplaceValue() {
-      return typereplaceValue;
-    }
-
-    public void setTypereplaceValue(String typereplaceValue) {
-      this.typereplaceValue = typereplaceValue;
-    }
-
-    public String getTypereplaceMask() {
-      return typereplaceMask;
-    }
-
-    public void setTypereplaceMask(String typereplaceMask) {
-      this.typereplaceMask = typereplaceMask;
-    }
-
-    public boolean isSetTypeEmptyString() {
-      return setTypeEmptyString;
-    }
+  @HopMetadataProperty(groupKey = "fields", key = "field", injectionGroupKey = 
"FIELDS",
+      injectionGroupDescription = "IfNull.Injection.FIELDS")
+  private List<Field> fields;
 
-    public void setTypeEmptyString(boolean setTypeEmptyString) {
-      this.setTypeEmptyString = setTypeEmptyString;
-    }
+  @HopMetadataProperty(groupKey = "valuetypes", key = "valuetype", 
injectionGroupKey = "VALUE_TYPES",
+      injectionGroupDescription = "IfNull.Injection.VALUE_TYPES")
+  private List<ValueType> valueTypes;
 
-    @Override
-    public ValueTypes clone() {
-      try {
-        return (ValueTypes) super.clone();
-      } catch (CloneNotSupportedException e) {
-        throw new RuntimeException(e);
-      }
-    }
-  }
-
-  @InjectionDeep private Fields[] fields;
-
-  @InjectionDeep private ValueTypes[] valueTypes;
-
-  @Injection(name = "SELECT_FIELDS")
+  @HopMetadataProperty(key = "selectFields", injectionKey = "SELECT_FIELDS", 
injectionKeyDescription = "IfNull.Injection.SELECT_FIELDS")
   private boolean selectFields;
 
-  @Injection(name = "SELECT_VALUES_TYPE")
+  @HopMetadataProperty(key = "selectValuesType", injectionKey = 
"SELECT_VALUES_TYPE", injectionKeyDescription = 
"IfNull.Injection.SELECT_VALUES_TYPE")
   private boolean selectValuesType;
-
-  @Injection(name = "REPLACE_ALL_BY_VALUE")
+  
+  @HopMetadataProperty(key = "replaceAllByValue", injectionKey = 
"REPLACE_ALL_BY_VALUE", injectionKeyDescription = 
"IfNull.Injection.REPLACE_ALL_BY_VALUE")
   private String replaceAllByValue;
 
-  @Injection(name = "REPLACE_ALL_MASK")
+  @HopMetadataProperty(key = "replaceAllMask", injectionKey = 
"REPLACE_ALL_MASK", injectionKeyDescription = 
"IfNull.Injection.REPLACE_ALL_MASK")
   private String replaceAllMask;
 
   /** The flag to set auto commit on or off on the connection */
-  @Injection(name = "SET_EMPTY_STRING_ALL")
+  @HopMetadataProperty(key = "setEmptyStringAll", injectionKey = 
"SET_EMPTY_STRING_ALL", injectionKeyDescription = 
"IfNull.Injection.SET_EMPTY_STRING_ALL")
   private boolean setEmptyStringAll;
 
   public IfNullMeta() {
     super(); // allocate BaseTransformMeta
+    this.valueTypes = new ArrayList<>();
+    this.fields = new ArrayList<>();
+  }
+  
+  public IfNullMeta(final IfNullMeta meta) {
+    this(); 
+    this.selectFields = meta.selectFields;
+    this.selectValuesType = meta.selectValuesType;
+    this.replaceAllByValue = meta.replaceAllByValue;
+    this.replaceAllMask = meta.replaceAllMask;
+    this.setEmptyStringAll = meta.setEmptyStringAll;
+    
+    for (Field field:meta.fields) {
+      this.fields.add(new Field(field));
+    }
+    for (ValueType vt:meta.valueTypes) {
+      this.valueTypes.add(new ValueType(vt));
+    } 
   }
 
   /** @return Returns the setEmptyStringAll. */
@@ -201,44 +96,13 @@ public class IfNullMeta extends BaseTransformMeta<IfNull, 
IfNullData> {
   }
 
   /** @param setEmptyStringAll The setEmptyStringAll to set. */
-  public void setEmptyStringAll(boolean setEmptyStringAll) {
+  public void setSetEmptyStringAll(boolean setEmptyStringAll) {
     this.setEmptyStringAll = setEmptyStringAll;
   }
 
-  @Override
-  public void loadXml(Node transformNode, IHopMetadataProvider 
metadataProvider)
-      throws HopXmlException {
-    readData(transformNode, metadataProvider);
-  }
-
   @Override
   public Object clone() {
-    IfNullMeta retval = (IfNullMeta) super.clone();
-
-    int nrTypes = valueTypes.length;
-    int nrFields = fields.length;
-    retval.allocate(nrTypes, nrFields);
-
-    for (int i = 0; i < nrTypes; i++) {
-      retval.getValueTypes()[i] = valueTypes[i].clone();
-    }
-
-    for (int i = 0; i < nrFields; i++) {
-      retval.getFields()[i] = fields[i].clone();
-    }
-
-    return retval;
-  }
-
-  public void allocate(int nrtypes, int nrFields) {
-    valueTypes = new ValueTypes[nrtypes];
-    for (int i = 0; i < nrtypes; i++) {
-      valueTypes[i] = new ValueTypes();
-    }
-    fields = new Fields[nrFields];
-    for (int i = 0; i < nrFields; i++) {
-      fields[i] = new Fields();
-    }
+    return new IfNullMeta(this);
   }
 
   public boolean isSelectFields() {
@@ -273,115 +137,31 @@ public class IfNullMeta extends 
BaseTransformMeta<IfNull, IfNullData> {
     return replaceAllMask;
   }
 
-  public Fields[] getFields() {
+  public List<Field> getFields() {
     return fields;
   }
 
-  public void setFields(Fields[] fields) {
+  public void setFields(List<Field> fields) {
     this.fields = fields;
   }
 
-  public ValueTypes[] getValueTypes() {
+  public List<ValueType> getValueTypes() {
     return valueTypes;
   }
 
-  public void setValueTypes(ValueTypes[] valueTypes) {
+  public void setValueTypes(List<ValueType> valueTypes) {
     this.valueTypes = valueTypes;
   }
 
-  private void readData(Node transformNode, IHopMetadataProvider 
metadataProvider)
-      throws HopXmlException {
-    try {
-      selectFields = 
"Y".equalsIgnoreCase(XmlHandler.getTagValue(transformNode, "selectFields"));
-      selectValuesType =
-          "Y".equalsIgnoreCase(XmlHandler.getTagValue(transformNode, 
"selectValuesType"));
-      replaceAllByValue = XmlHandler.getTagValue(transformNode, 
"replaceAllByValue");
-      replaceAllMask = XmlHandler.getTagValue(transformNode, "replaceAllMask");
-      String setEmptyStringAllString = XmlHandler.getTagValue(transformNode, 
"setEmptyStringAll");
-      setEmptyStringAll =
-          !Utils.isEmpty(setEmptyStringAllString) && 
"Y".equalsIgnoreCase(setEmptyStringAllString);
-
-      Node types = XmlHandler.getSubNode(transformNode, "valuetypes");
-      int nrtypes = XmlHandler.countNodes(types, "valuetype");
-      Node fieldNodes = XmlHandler.getSubNode(transformNode, "fields");
-      int nrFields = XmlHandler.countNodes(fieldNodes, "field");
-
-      allocate(nrtypes, nrFields);
-
-      for (int i = 0; i < nrtypes; i++) {
-        Node tnode = XmlHandler.getSubNodeByNr(types, "valuetype", i);
-        valueTypes[i].setTypeName(XmlHandler.getTagValue(tnode, "name"));
-        valueTypes[i].setTypereplaceValue(XmlHandler.getTagValue(tnode, 
"value"));
-        valueTypes[i].setTypereplaceMask(XmlHandler.getTagValue(tnode, 
"mask"));
-        String typeemptyString = XmlHandler.getTagValue(tnode, 
"set_type_empty_string");
-        valueTypes[i].setTypeEmptyString(
-            !Utils.isEmpty(typeemptyString) && 
"Y".equalsIgnoreCase(typeemptyString));
-      }
-      for (int i = 0; i < nrFields; i++) {
-        Node fnode = XmlHandler.getSubNodeByNr(fieldNodes, "field", i);
-        fields[i].setFieldName(XmlHandler.getTagValue(fnode, "name"));
-        fields[i].setReplaceValue(XmlHandler.getTagValue(fnode, "value"));
-        fields[i].setReplaceMask(XmlHandler.getTagValue(fnode, "mask"));
-        String emptyString = XmlHandler.getTagValue(fnode, "set_empty_string");
-        fields[i].setEmptyString(!Utils.isEmpty(emptyString) && 
"Y".equalsIgnoreCase(emptyString));
-      }
-    } catch (Exception e) {
-      throw new HopXmlException("It was not possibke to load the IfNull 
metadata from XML", e);
-    }
-  }
-
-  @Override
-  public String getXml() {
-    StringBuilder retval = new StringBuilder();
-
-    retval.append("      " + XmlHandler.addTagValue("replaceAllByValue", 
replaceAllByValue));
-    retval.append("      " + XmlHandler.addTagValue("replaceAllMask", 
replaceAllMask));
-    retval.append("      " + XmlHandler.addTagValue("selectFields", 
selectFields));
-    retval.append("      " + XmlHandler.addTagValue("selectValuesType", 
selectValuesType));
-    retval.append("      " + XmlHandler.addTagValue("setEmptyStringAll", 
setEmptyStringAll));
-
-    retval.append("    <valuetypes>" + Const.CR);
-    for (int i = 0; i < valueTypes.length; i++) {
-      retval.append("      <valuetype>" + Const.CR);
-      retval.append("        " + XmlHandler.addTagValue("name", 
valueTypes[i].getTypeName()));
-      retval.append(
-          "        " + XmlHandler.addTagValue("value", 
valueTypes[i].getTypereplaceValue()));
-      retval.append(
-          "        " + XmlHandler.addTagValue("mask", 
valueTypes[i].getTypereplaceMask()));
-      retval.append(
-          "        "
-              + XmlHandler.addTagValue(
-                  "set_type_empty_string", 
valueTypes[i].isSetTypeEmptyString()));
-      retval.append("        </valuetype>" + Const.CR);
-    }
-    retval.append("      </valuetypes>" + Const.CR);
-
-    retval.append("    <fields>" + Const.CR);
-    for (int i = 0; i < fields.length; i++) {
-      retval.append("      <field>" + Const.CR);
-      retval.append("        " + XmlHandler.addTagValue("name", 
fields[i].getFieldName()));
-      retval.append("        " + XmlHandler.addTagValue("value", 
fields[i].getReplaceValue()));
-      retval.append("        " + XmlHandler.addTagValue("mask", 
fields[i].getReplaceMask()));
-      retval.append(
-          "        " + XmlHandler.addTagValue("set_empty_string", 
fields[i].isSetEmptyString()));
-      retval.append("        </field>" + Const.CR);
-    }
-    retval.append("      </fields>" + Const.CR);
-
-    return retval.toString();
-  }
-
   @Override
   public void setDefault() {
-    replaceAllByValue = null;
-    replaceAllMask = null;
-    selectFields = false;
-    selectValuesType = false;
-    setEmptyStringAll = false;
-
-    int nrFields = 0;
-    int nrtypes = 0;
-    allocate(nrtypes, nrFields);
+    this.replaceAllByValue = null;
+    this.replaceAllMask = null;
+    this.selectFields = false;
+    this.selectValuesType = false;
+    this.setEmptyStringAll = false;
+    this.valueTypes = new ArrayList<>();
+    this.fields = new ArrayList<>();
   }
 
   @Override
@@ -399,7 +179,7 @@ public class IfNullMeta extends BaseTransformMeta<IfNull, 
IfNullData> {
     if (prev == null || prev.size() == 0) {
       cr =
           new CheckResult(
-              CheckResult.TYPE_RESULT_WARNING,
+              ICheckResult.TYPE_RESULT_WARNING,
               BaseMessages.getString(PKG, 
"IfNullMeta.CheckResult.NotReceivingFields"),
               transformMeta);
       remarks.add(cr);
@@ -416,10 +196,10 @@ public class IfNullMeta extends BaseTransformMeta<IfNull, 
IfNullData> {
       boolean errorFound = false;
 
       // Starting from selected fields in ...
-      for (int i = 0; i < fields.length; i++) {
-        int idx = prev.indexOfValue(fields[i].getFieldName());
+      for (Field field : this.fields) {
+        int idx = prev.indexOfValue(field.getName());
         if (idx < 0) {
-          errorMessage += "\t\t" + fields[i].getFieldName() + Const.CR;
+          errorMessage += "\t\t" + field.getName() + Const.CR;
           errorFound = true;
         }
       }
@@ -430,7 +210,7 @@ public class IfNullMeta extends BaseTransformMeta<IfNull, 
IfNullData> {
         cr = new CheckResult(ICheckResult.TYPE_RESULT_ERROR, errorMessage, 
transformMeta);
         remarks.add(cr);
       } else {
-        if (fields.length > 0) {
+        if (fields.size() > 0) {
           cr =
               new CheckResult(
                   ICheckResult.TYPE_RESULT_OK,
@@ -440,7 +220,7 @@ public class IfNullMeta extends BaseTransformMeta<IfNull, 
IfNullData> {
         } else {
           cr =
               new CheckResult(
-                  CheckResult.TYPE_RESULT_WARNING,
+                  ICheckResult.TYPE_RESULT_WARNING,
                   BaseMessages.getString(PKG, 
"IfNullMeta.CheckResult.NoFieldsEntered"),
                   transformMeta);
           remarks.add(cr);
diff --git 
a/plugins/transforms/ifnull/src/main/java/org/apache/hop/pipeline/transforms/ifnull/ValueType.java
 
b/plugins/transforms/ifnull/src/main/java/org/apache/hop/pipeline/transforms/ifnull/ValueType.java
new file mode 100644
index 0000000000..54f5b57a70
--- /dev/null
+++ 
b/plugins/transforms/ifnull/src/main/java/org/apache/hop/pipeline/transforms/ifnull/ValueType.java
@@ -0,0 +1,80 @@
+/*
+ * 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.ifnull;
+
+import org.apache.hop.metadata.api.HopMetadataProperty;
+
+public class ValueType {
+
+  /** which types to display? */
+  @HopMetadataProperty(key = "name", injectionKey = "TYPE_NAME", 
injectionKeyDescription = "IfNull.Injection.TYPE_NAME")
+  private String name;
+
+  /** by which value we replace */
+  @HopMetadataProperty(key = "value", injectionKey = "TYPE_REPLACE_VALUE", 
injectionKeyDescription = "IfNull.Injection.TYPE_REPLACE_VALUE")
+  private String value;
+
+  @HopMetadataProperty(key = "mask", injectionKey = "TYPE_REPLACE_MASK", 
injectionKeyDescription = "IfNull.Injection.TYPE_REPLACE_MASK")
+  private String mask;
+
+  /** Flag : set empty string for type */
+  @HopMetadataProperty(key = "set_type_empty_string", injectionKey = 
"SET_TYPE_EMPTY_STRING", injectionKeyDescription = 
"IfNull.Injection.SET_TYPE_EMPTY_STRING")
+  private boolean setEmptyString;
+
+  public ValueType() {   
+  }
+
+  public ValueType(ValueType other) {
+      this.name = other.name;
+      this.value = other.value;
+      this.mask = other.mask;
+      this.setEmptyString = other.setEmptyString;
+  }
+  
+  public String getName() {
+    return name;
+  }
+
+  public void setName(String name) {
+    this.name = name;
+  }
+
+  public String getValue() {
+    return value;
+  }
+
+  public void setValue(String value) {
+    this.value = value;
+  }
+
+  public String getMask() {
+    return mask;
+  }
+
+  public void setMask(String mask) {
+    this.mask = mask;
+  }
+
+  public boolean isSetEmptyString() {
+    return setEmptyString;
+  }
+
+  public void setSetEmptyString(boolean setEmptyString) {
+    this.setEmptyString = setEmptyString;
+  }
+}
\ No newline at end of file
diff --git 
a/plugins/transforms/ifnull/src/test/java/org/apache/hop/pipeline/transforms/ifnull/IfNullMetaInjectionTest.java
 
b/plugins/transforms/ifnull/src/test/java/org/apache/hop/pipeline/transforms/ifnull/IfNullMetaInjectionTest.java
index 79a92fe412..3efce9cf6e 100644
--- 
a/plugins/transforms/ifnull/src/test/java/org/apache/hop/pipeline/transforms/ifnull/IfNullMetaInjectionTest.java
+++ 
b/plugins/transforms/ifnull/src/test/java/org/apache/hop/pipeline/transforms/ifnull/IfNullMetaInjectionTest.java
@@ -33,14 +33,16 @@ public class IfNullMetaInjectionTest extends 
BaseMetadataInjectionTest<IfNullMet
 
   @Test
   public void test() throws Exception {
-    check("FIELD_NAME", () -> meta.getFields()[0].getFieldName());
-    check("REPLACE_VALUE", () -> meta.getFields()[0].getReplaceValue());
-    check("TYPE_NAME", () -> meta.getValueTypes()[0].getTypeName());
-    check("TYPE_REPLACE_VALUE", () -> 
meta.getValueTypes()[0].getTypereplaceValue());
-    check("TYPE_REPLACE_MASK", () -> 
meta.getValueTypes()[0].getTypereplaceMask());
-    check("REPLACE_MASK", () -> meta.getFields()[0].getReplaceMask());
-    check("SET_TYPE_EMPTY_STRING", () -> 
meta.getValueTypes()[0].isSetTypeEmptyString());
-    check("SET_EMPTY_STRING", () -> meta.getFields()[0].isSetEmptyString());
+    check("FIELD_NAME", () -> meta.getFields().get(0).getName());
+    check("REPLACE_VALUE", () -> meta.getFields().get(0).getValue());
+    check("REPLACE_MASK", () -> meta.getFields().get(0).getMask());
+    check("SET_EMPTY_STRING", () -> 
meta.getFields().get(0).isSetEmptyString());
+    
+    check("TYPE_NAME", () -> meta.getValueTypes().get(0).getName());
+    check("TYPE_REPLACE_VALUE", () -> meta.getValueTypes().get(0).getValue());
+    check("TYPE_REPLACE_MASK", () -> meta.getValueTypes().get(0).getMask());   
 
+    check("SET_TYPE_EMPTY_STRING", () -> 
meta.getValueTypes().get(0).isSetEmptyString());
+    
     check("SELECT_FIELDS", () -> meta.isSelectFields());
     check("SELECT_VALUES_TYPE", () -> meta.isSelectValuesType());
     check("REPLACE_ALL_BY_VALUE", () -> meta.getReplaceAllByValue());
diff --git 
a/plugins/transforms/ifnull/src/test/java/org/apache/hop/pipeline/transforms/ifnull/IfNullMetaTest.java
 
b/plugins/transforms/ifnull/src/test/java/org/apache/hop/pipeline/transforms/ifnull/IfNullMetaTest.java
index d42696c0bc..0b5fa53473 100644
--- 
a/plugins/transforms/ifnull/src/test/java/org/apache/hop/pipeline/transforms/ifnull/IfNullMetaTest.java
+++ 
b/plugins/transforms/ifnull/src/test/java/org/apache/hop/pipeline/transforms/ifnull/IfNullMetaTest.java
@@ -16,159 +16,79 @@
  */
 package org.apache.hop.pipeline.transforms.ifnull;
 
-import org.apache.commons.lang.builder.EqualsBuilder;
-import org.apache.hop.core.exception.HopException;
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertNull;
+import static org.junit.Assert.assertTrue;
+import org.apache.hop.core.HopEnvironment;
+import org.apache.hop.core.plugins.PluginRegistry;
 import org.apache.hop.junit.rules.RestoreHopEngineEnvironment;
-import org.apache.hop.pipeline.transforms.ifnull.IfNullMeta.Fields;
-import org.apache.hop.pipeline.transforms.ifnull.IfNullMeta.ValueTypes;
-import org.apache.hop.pipeline.transforms.loadsave.LoadSaveTester;
-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.PrimitiveBooleanArrayLoadSaveValidator;
-import 
org.apache.hop.pipeline.transforms.loadsave.validator.StringLoadSaveValidator;
+import org.apache.hop.pipeline.transform.TransformSerializationTestUtil;
 import org.junit.Before;
 import org.junit.ClassRule;
 import org.junit.Test;
 
-import java.util.Arrays;
-import java.util.HashMap;
-import java.util.List;
-import java.util.Map;
-
-import static org.junit.Assert.assertFalse;
-import static org.junit.Assert.assertTrue;
-
 public class IfNullMetaTest {
   @ClassRule public static RestoreHopEngineEnvironment env = new 
RestoreHopEngineEnvironment();
-
-  LoadSaveTester loadSaveTester;
-
+  
   @Before
-  public void setUp() throws Exception {
-    List<String> attributes =
-        Arrays.asList(
-            "fields",
-            "valueTypes",
-            "selectFields",
-            "selectValuesType",
-            "replaceAllByValue",
-            "replaceAllMask",
-            "setEmptyStringAll");
-
-    Map<String, String> getterMap =
-        new HashMap<String, String>() {
-          {
-            put("fields", "getFields");
-            put("valueTypes", "getValueTypes");
-            put("selectFields", "isSelectFields");
-            put("selectValuesType", "isSelectValuesType");
-            put("replaceAllByValue", "getReplaceAllByValue");
-            put("replaceAllMask", "getReplaceAllMask");
-            put("setEmptyStringAll", "isSetEmptyStringAll");
-          }
-        };
-
-    Map<String, String> setterMap =
-        new HashMap<String, String>() {
-          {
-            put("fields", "setFields");
-            put("valueTypes", "setValueTypes");
-            put("selectFields", "setSelectFields");
-            put("selectValuesType", "setSelectValuesType");
-            put("replaceAllByValue", "setReplaceAllByValue");
-            put("replaceAllMask", "setReplaceAllMask");
-            put("setEmptyStringAll", "setEmptyStringAll");
-          }
-        };
-    IFieldLoadSaveValidator<String[]> stringArrayLoadSaveValidator =
-        new ArrayLoadSaveValidator<>(new StringLoadSaveValidator(), 3);
-    Map<String, IFieldLoadSaveValidator<?>> attrValidatorMap = new HashMap<>();
-    attrValidatorMap.put("fieldName", stringArrayLoadSaveValidator);
-    attrValidatorMap.put("replaceValue", stringArrayLoadSaveValidator);
-    attrValidatorMap.put("typeName", stringArrayLoadSaveValidator);
-    attrValidatorMap.put("typereplaceValue", stringArrayLoadSaveValidator);
-    attrValidatorMap.put("typereplaceMask", stringArrayLoadSaveValidator);
-    attrValidatorMap.put("replaceMask", stringArrayLoadSaveValidator);
-
-    Map<String, IFieldLoadSaveValidator<?>> typeValidatorMap = new HashMap<>();
-    typeValidatorMap.put(
-        boolean[].class.getCanonicalName(),
-        new PrimitiveBooleanArrayLoadSaveValidator(new 
BooleanLoadSaveValidator(), 3));
-
-    Fields field = new Fields();
-    field.setFieldName("fieldName");
-    field.setReplaceValue("replaceValue");
-    field.setReplaceMask("replaceMask");
-    field.setEmptyString(true);
-    typeValidatorMap.put(
-        Fields[].class.getCanonicalName(),
-        new ArrayLoadSaveValidator<>(new FieldsLoadSaveValidator(field), 3));
-
-    ValueTypes type = new ValueTypes();
-    type.setTypeName("typeName");
-    type.setTypereplaceValue("typereplaceValue");
-    type.setTypereplaceMask("typereplaceMask");
-    type.setTypeEmptyString(true);
-    typeValidatorMap.put(
-        ValueTypes[].class.getCanonicalName(),
-        new ArrayLoadSaveValidator<>(new ValueTypesLoadSaveValidator(type), 
3));
-
-    loadSaveTester =
-        new LoadSaveTester(
-            IfNullMeta.class, attributes, getterMap, setterMap, 
attrValidatorMap, typeValidatorMap);
+  public void setUpLoadSave() throws Exception {
+    HopEnvironment.init();
+    PluginRegistry.init();
   }
-
+  
   @Test
-  public void testLoadSave() throws HopException {
-    loadSaveTester.testSerialization();
+  public void testLoadSaveValueType() throws Exception {
+    IfNullMeta meta =
+        TransformSerializationTestUtil.testSerialization(
+            "/if-null-transform-value-type.xml", IfNullMeta.class);
+    
+    assertTrue(meta.isSelectValuesType());
+    assertEquals(3, meta.getValueTypes().size());
+    assertFalse(meta.isSelectFields());
+    assertEquals(0, meta.getFields().size());     
+    
+    assertEquals("String", meta.getValueTypes().get(0).getName());
+    assertNull(meta.getValueTypes().get(0).getValue());    
+    assertTrue(meta.getValueTypes().get(0).isSetEmptyString());
+    assertEquals("Number", meta.getValueTypes().get(1).getName());
+    assertNull(meta.getValueTypes().get(1).getValue());    
+    assertFalse(meta.getValueTypes().get(1).isSetEmptyString());    
+    assertEquals("Date", meta.getValueTypes().get(2).getName());
+    assertNull(meta.getValueTypes().get(2).getValue());    
+    assertFalse(meta.getValueTypes().get(2).isSetEmptyString());   
   }
-
+  
   @Test
-  public void testSetDefault() throws Exception {
-    IfNullMeta inm = new IfNullMeta();
-    inm.setDefault();
-    assertTrue((inm.getValueTypes() != null) && (inm.getValueTypes().length == 
0));
-    assertTrue((inm.getFields() != null) && (inm.getFields().length == 0));
-    assertFalse(inm.isSelectFields());
-    assertFalse(inm.isSelectValuesType());
-  }
-
-  public static class FieldsLoadSaveValidator implements 
IFieldLoadSaveValidator<Fields> {
-
-    private final Fields defaultValue;
-
-    public FieldsLoadSaveValidator(Fields defaultValue) {
-      this.defaultValue = defaultValue;
-    }
-
-    @Override
-    public Fields getTestObject() {
-      return defaultValue;
-    }
-
-    @Override
-    public boolean validateTestObject(Fields testObject, Object actual) {
-      return EqualsBuilder.reflectionEquals(testObject, actual);
-    }
+  public void testLoadSaveField() throws Exception {
+      IfNullMeta meta =
+          TransformSerializationTestUtil.testSerialization(
+            "/if-null-transform-field.xml", IfNullMeta.class);
+  
+    assertFalse(meta.isSelectValuesType());
+    assertEquals(0, meta.getValueTypes().size());
+    assertTrue(meta.isSelectFields());
+    assertEquals(3, meta.getFields().size());    
+    
+    assertEquals("F1", meta.getFields().get(0).getName());
+    assertEquals("EMPTY",meta.getFields().get(0).getValue());    
+    assertFalse(meta.getFields().get(0).isSetEmptyString());
+    assertEquals("F2", meta.getFields().get(1).getName());
+    assertEquals("01019999",meta.getFields().get(1).getValue());    
+    assertEquals("ddMMYYYY",meta.getFields().get(1).getMask());
+    assertFalse(meta.getFields().get(1).isSetEmptyString());    
+    assertEquals("F3", meta.getFields().get(2).getName());
+    assertNull(meta.getFields().get(2).getValue());    
+    assertTrue(meta.getFields().get(2).isSetEmptyString());   
   }
 
-  public static class ValueTypesLoadSaveValidator implements 
IFieldLoadSaveValidator<ValueTypes> {
-
-    private final ValueTypes defaultValue;
-
-    public ValueTypesLoadSaveValidator(ValueTypes defaultValue) {
-      this.defaultValue = defaultValue;
-    }
-
-    @Override
-    public ValueTypes getTestObject() {
-      return defaultValue;
-    }
-
-    @Override
-    public boolean validateTestObject(ValueTypes testObject, Object actual) {
-      return EqualsBuilder.reflectionEquals(testObject, actual);
-    }
+  @Test
+  public void testSetDefault() throws Exception {
+    IfNullMeta meta = new IfNullMeta();
+    meta.setDefault();
+    assertTrue((meta.getValueTypes() != null) && 
(meta.getValueTypes().isEmpty()));
+    assertTrue((meta.getFields() != null) && (meta.getFields().isEmpty()));
+    assertFalse(meta.isSelectFields());
+    assertFalse(meta.isSelectValuesType());
   }
 }
diff --git 
a/plugins/transforms/ifnull/src/test/java/org/apache/hop/pipeline/transforms/ifnull/IfNullTest.java
 
b/plugins/transforms/ifnull/src/test/java/org/apache/hop/pipeline/transforms/ifnull/IfNullTest.java
index 205fa414fc..2a4859c93c 100644
--- 
a/plugins/transforms/ifnull/src/test/java/org/apache/hop/pipeline/transforms/ifnull/IfNullTest.java
+++ 
b/plugins/transforms/ifnull/src/test/java/org/apache/hop/pipeline/transforms/ifnull/IfNullTest.java
@@ -33,13 +33,13 @@ import org.apache.hop.core.variables.IVariables;
 import org.apache.hop.junit.rules.RestoreHopEngineEnvironment;
 import org.apache.hop.metadata.api.IHopMetadataProvider;
 import org.apache.hop.pipeline.transform.TransformMeta;
-import org.apache.hop.pipeline.transforms.ifnull.IfNullMeta.Fields;
 import org.apache.hop.pipeline.transforms.mock.TransformMockHelper;
 import org.junit.After;
 import org.junit.Before;
 import org.junit.BeforeClass;
 import org.junit.Test;
-
+import java.util.ArrayList;
+import java.util.List;
 import static org.mockito.Matchers.any;
 import static org.mockito.Matchers.anyString;
 import static org.mockito.Mockito.doCallRealMethod;
@@ -94,12 +94,12 @@ public class IfNullTest {
     return processRowMeta;
   }
 
-  private static Fields[] createFields(String... fieldNames) {
-    Fields[] fields = new Fields[fieldNames.length];
-    for (int i = 0; i < fields.length; i++) {
-      Fields currentField = new Fields();
-      currentField.setFieldName(fieldNames[i]);
-      fields[i] = currentField;
+  private static List<Field> createFields(String... fieldNames) {
+    List<Field> fields = new ArrayList<>();
+    for (int i = 0; i < fieldNames.length; i++) {
+      Field field = new Field();
+      field.setName(fieldNames[i]);
+      fields.add(field);
     }
     return fields;
   }
diff --git 
a/plugins/transforms/ifnull/src/test/java/org/apache/hop/pipeline/transforms/ifnull/PDI_11319Test.java
 
b/plugins/transforms/ifnull/src/test/java/org/apache/hop/pipeline/transforms/ifnull/PDI_11319Test.java
deleted file mode 100644
index abde6e56a1..0000000000
--- 
a/plugins/transforms/ifnull/src/test/java/org/apache/hop/pipeline/transforms/ifnull/PDI_11319Test.java
+++ /dev/null
@@ -1,96 +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.ifnull;
-
-import org.apache.hop.core.xml.XmlHandler;
-import org.apache.hop.pipeline.transforms.ifnull.IfNullMeta.ValueTypes;
-import org.junit.Assert;
-import org.junit.Before;
-import org.junit.Test;
-import org.w3c.dom.Node;
-
-import java.io.File;
-import java.util.List;
-
-public class PDI_11319Test {
-
-  private Node xmlVersion4;
-  private Node xmlVersion5;
-  private IfNullMeta meta;
-
-  @Before
-  public void init() throws Exception {
-    File v4 = new File(this.getClass().getResource("v4.hpl").getFile());
-    File v5 = new File(this.getClass().getResource("v5.hpl").getFile());
-    xmlVersion4 = XmlHandler.loadXmlFile(v4);
-    xmlVersion5 = XmlHandler.loadXmlFile(v5);
-    meta = new IfNullMeta();
-  }
-
-  /**
-   * Test forward compatibility - pipeline created in version 4 don't contain 
"set emtry" elements
-   */
-  @Test
-  public void testLoadXmlVersion4() throws Exception {
-    Node nullIfTransform = getNullIfTransform(xmlVersion4);
-    meta.loadXml(nullIfTransform, null);
-
-    Assert.assertFalse("Set Empty String is true", meta.isSetEmptyStringAll());
-    boolean[] expected = {false};
-    ValueTypes[] actual = meta.getValueTypes();
-    Assert.assertEquals(expected.length, actual.length);
-    for (int i = 0; i < expected.length; i++) {
-      Assert.assertEquals(
-          "Set empty string value type works incorrectly",
-          expected[i],
-          actual[i].isSetTypeEmptyString());
-    }
-  }
-
-  /** Test pipeline created in Hop 5 - should work w/ and w/o the fix */
-  @Test
-  public void testLoadXmlVersion5() throws Exception {
-    Node nullIfTransform = getNullIfTransform(xmlVersion5);
-    meta.loadXml(nullIfTransform, null);
-
-    Assert.assertFalse("Set Empty String is true", meta.isSetEmptyStringAll());
-    boolean[] expected = {true, false, false};
-    ValueTypes[] actual = meta.getValueTypes();
-    Assert.assertEquals(expected.length, actual.length);
-    for (int i = 0; i < expected.length; i++) {
-      Assert.assertEquals(
-          "Set empty string value type works incorrectly",
-          expected[i],
-          actual[i].isSetTypeEmptyString());
-    }
-  }
-
-  private Node getNullIfTransform(Node doc) {
-    Node pipeline = XmlHandler.getSubNode(doc, "pipeline");
-    List<Node> transforms = XmlHandler.getNodes(pipeline, "transform");
-    Node nullIfTransform = null;
-    for (Node transform : transforms) {
-      if 
("IfNull".equals(XmlHandler.getNodeValue(XmlHandler.getSubNode(transform, 
"type")))) {
-        nullIfTransform = transform;
-        break;
-      }
-    }
-
-    return nullIfTransform;
-  }
-}
diff --git 
a/plugins/transforms/ifnull/src/test/resources/if-null-transform-field.xml 
b/plugins/transforms/ifnull/src/test/resources/if-null-transform-field.xml
new file mode 100644
index 0000000000..0ebdbb153a
--- /dev/null
+++ b/plugins/transforms/ifnull/src/test/resources/if-null-transform-field.xml
@@ -0,0 +1,55 @@
+<?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>
+    <name>If field value is null</name>
+    <type>IfNull</type>
+    <description/>
+    <distribute>Y</distribute>
+    <custom_distribution/>
+    <copies>1</copies>
+    <partitioning>
+      <method>none</method>
+      <schema_name/>
+    </partitioning>
+    <replaceAllByValue>EMPTY</replaceAllByValue>
+    <replaceAllMask/>
+    <selectFields>Y</selectFields>
+    <selectValuesType>N</selectValuesType>
+    <setEmptyStringAll>N</setEmptyStringAll>
+    <valuetypes>
+      </valuetypes>
+    <fields>
+      <field>
+        <name>F1</name>
+        <value>EMPTY</value>
+        <mask/>
+        <set_empty_string>N</set_empty_string>
+      </field>
+      <field>
+        <name>F2</name>
+        <value>01019999</value>
+        <mask>ddMMYYYY</mask>
+        <set_empty_string>N</set_empty_string>
+      </field>
+      <field>
+        <name>F3</name>
+        <value/>
+        <mask/>
+        <set_empty_string>Y</set_empty_string>
+      </field>
+    </fields>
+    <attributes/>
+    <GUI>
+      <xloc>544</xloc>
+      <yloc>96</yloc>
+    </GUI>
+  </transform>
\ No newline at end of file
diff --git 
a/plugins/transforms/ifnull/src/test/resources/if-null-transform-value-type.xml 
b/plugins/transforms/ifnull/src/test/resources/if-null-transform-value-type.xml
new file mode 100644
index 0000000000..080553bebd
--- /dev/null
+++ 
b/plugins/transforms/ifnull/src/test/resources/if-null-transform-value-type.xml
@@ -0,0 +1,59 @@
+<?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>
+       <name>If field value is null</name>
+       <type>IfNull</type>
+       <description />
+       <distribute>Y</distribute>
+       <custom_distribution />
+       <copies>1</copies>
+       <partitioning>
+               <method>none</method>
+               <schema_name />
+       </partitioning>
+       <replaceAllByValue />
+       <replaceAllMask />
+       <selectFields>N</selectFields>
+       <selectValuesType>Y</selectValuesType>
+       <setEmptyStringAll>N</setEmptyStringAll>
+       <valuetypes>
+               <valuetype>
+                       <name>String</name>
+                       <value />
+                       <mask />
+                       <set_type_empty_string>Y</set_type_empty_string>
+               </valuetype>
+               <valuetype>
+                       <name>Number</name>
+                       <value />
+                       <mask />
+                       <set_type_empty_string>N</set_type_empty_string>
+               </valuetype>
+               <valuetype>
+                       <name>Date</name>
+                       <value />
+                       <mask />
+                       <set_type_empty_string>N</set_type_empty_string>
+               </valuetype>
+       </valuetypes>
+       <fields>
+       </fields>
+       <input>
+       </input>
+       <output>
+       </output>
+       <GUI>
+               <xloc>290</xloc>
+               <yloc>143</yloc>
+               <draw>Y</draw>
+       </GUI>
+</transform>
diff --git 
a/plugins/transforms/ifnull/src/test/resources/org/apache/hop/pipeline/transforms/ifnull/v4.hpl
 
b/plugins/transforms/ifnull/src/test/resources/org/apache/hop/pipeline/transforms/ifnull/v4.hpl
deleted file mode 100644
index ad735c3532..0000000000
--- 
a/plugins/transforms/ifnull/src/test/resources/org/apache/hop/pipeline/transforms/ifnull/v4.hpl
+++ /dev/null
@@ -1,166 +0,0 @@
-<?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>v4</name>
-    <description/>
-    <extended_description/>
-    <trans_version/>
-    <trans_type>Normal</trans_type>
-    <directory>&#x2f;</directory>
-    <parameters>
-    </parameters>
-    <log>
-<pipeline-log-table><connection/>
-<schema/>
-<table/>
-<size_limit_lines/>
-<interval/>
-<timeout_days/>
-<field><id>ID_BATCH</id><enabled>Y</enabled><name>ID_BATCH</name></field><field><id>CHANNEL_ID</id><enabled>Y</enabled><name>CHANNEL_ID</name></field><field><id>TRANSNAME</id><enabled>Y</enabled><name>TRANSNAME</name></field><field><id>STATUS</id><enabled>Y</enabled><name>STATUS</name></field><field><id>LINES_READ</id><enabled>Y</enabled><name>LINES_READ</name><subject/></field><field><id>LINES_WRITTEN</id><enabled>Y</enabled><name>LINES_WRITTEN</name><subject/></field><field><id>LINES_U
 [...]
-<perf-log-table><connection/>
-<schema/>
-<table/>
-<interval/>
-<timeout_days/>
-<field><id>ID_BATCH</id><enabled>Y</enabled><name>ID_BATCH</name></field><field><id>SEQ_NR</id><enabled>Y</enabled><name>SEQ_NR</name></field><field><id>LOGDATE</id><enabled>Y</enabled><name>LOGDATE</name></field><field><id>TRANSNAME</id><enabled>Y</enabled><name>TRANSNAME</name></field><field><id>STEPNAME</id><enabled>Y</enabled><name>STEPNAME</name></field><field><id>STEP_COPY</id><enabled>Y</enabled><name>STEP_COPY</name></field><field><id>LINES_READ</id><enabled>Y</enabled><name>LINE
 [...]
-<channel-log-table><connection/>
-<schema/>
-<table/>
-<timeout_days/>
-<field><id>ID_BATCH</id><enabled>Y</enabled><name>ID_BATCH</name></field><field><id>CHANNEL_ID</id><enabled>Y</enabled><name>CHANNEL_ID</name></field><field><id>LOG_DATE</id><enabled>Y</enabled><name>LOG_DATE</name></field><field><id>LOGGING_OBJECT_TYPE</id><enabled>Y</enabled><name>LOGGING_OBJECT_TYPE</name></field><field><id>OBJECT_NAME</id><enabled>Y</enabled><name>OBJECT_NAME</name></field><field><id>OBJECT_COPY</id><enabled>Y</enabled><name>OBJECT_COPY</name></field><field><id>REPOS
 [...]
-<transform-log-table><connection/>
-<schema/>
-<table/>
-<timeout_days/>
-<field><id>ID_BATCH</id><enabled>Y</enabled><name>ID_BATCH</name></field><field><id>CHANNEL_ID</id><enabled>Y</enabled><name>CHANNEL_ID</name></field><field><id>LOG_DATE</id><enabled>Y</enabled><name>LOG_DATE</name></field><field><id>TRANSNAME</id><enabled>Y</enabled><name>TRANSNAME</name></field><field><id>STEPNAME</id><enabled>Y</enabled><name>STEPNAME</name></field><field><id>STEP_COPY</id><enabled>Y</enabled><name>STEP_COPY</name></field><field><id>LINES_READ</id><enabled>Y</enabled>
 [...]
-    </log>
-    <maxdate>
-      <connection/>
-      <table/>
-      <field/>
-      <offset>0.0</offset>
-      <maxdiff>0.0</maxdiff>
-    </maxdate>
-    <size_rowset>10000</size_rowset>
-    <sleep_time_empty>50</sleep_time_empty>
-    <sleep_time_full>50</sleep_time_full>
-    <unique_connections>N</unique_connections>
-    <feedback_shown>Y</feedback_shown>
-    <feedback_size>50000</feedback_size>
-    <using_thread_priorities>Y</using_thread_priorities>
-    <shared_objects_file/>
-    <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>
-    <dependencies>
-    </dependencies>
-    <partitionschemas>
-    </partitionschemas>
-    <hop-servers>
-         
<hop-server><name>8081</name><hostname>localhost</hostname><port>8081</port><webAppName/><username>cluster</username><password>Encrypted
 
2be98afc86aa7f2e4cb1aa265cd86aac8</password><proxy_hostname/><proxy_port/><non_proxy_hosts/><master>Y</master></hop-server>
-    </hop-servers>
-    <clusterschemas>
-    </clusterschemas>
-  <created_user>-</created_user>
-  <created_date>2014&#x2f;02&#x2f;25 12&#x3a;51&#x3a;44.876</created_date>
-  <modified_user>-</modified_user>
-  <modified_date>2014&#x2f;02&#x2f;25 12&#x3a;51&#x3a;44.876</modified_date>
-  </info>
-  <notepads>
-  </notepads>
-  <order>
-  <hop> <from>Generate Rows</from><to>If field value is 
null</to><enabled>Y</enabled> </hop>
-  </order>
-  <transform>
-    <name>If field value is null</name>
-    <type>IfNull</type>
-    <description/>
-    <distribute>Y</distribute>
-    <copies>1</copies>
-         <partitioning>
-           <method>none</method>
-           <schema_name/>
-           </partitioning>
-      <replaceAllByValue/>
-      <replaceAllMask/>
-      <selectFields>N</selectFields>
-      <selectValuesType>Y</selectValuesType>
-    <valuetypes>
-      <valuetype>
-        <name>String</name>
-        <value/>
-        <mask/>
-        </valuetype>
-      </valuetypes>
-    <fields>
-      </fields>
- <input>   </input>   <output>   </output>     <GUI>
-      <xloc>290</xloc>
-      <yloc>143</yloc>
-      <draw>Y</draw>
-      </GUI>
-    </transform>
-
-  <transform>
-    <name>Generate Rows</name>
-    <type>RowGenerator</type>
-    <description/>
-    <distribute>Y</distribute>
-    <copies>1</copies>
-         <partitioning>
-           <method>none</method>
-           <schema_name/>
-           </partitioning>
-    <fields>
-      <field>
-        <name>a</name>
-        <type>String</type>
-        <format/>
-        <currency/>
-        <decimal/>
-        <group/>
-        <nullif/>
-        <length>-1</length>
-        <precision>-1</precision>
-      </field>
-      <field>
-        <name>b</name>
-        <type>Number</type>
-        <format/>
-        <currency/>
-        <decimal/>
-        <group/>
-        <nullif/>
-        <length>-1</length>
-        <precision>-1</precision>
-      </field>
-    </fields>
-    <limit>10</limit>
- <input>   </input>   <output>   </output>     <GUI>
-      <xloc>146</xloc>
-      <yloc>142</yloc>
-      <draw>Y</draw>
-      </GUI>
-    </transform>
-
-  <transform_error_handling>
-  </transform_error_handling>
- </pipeline>
diff --git 
a/plugins/transforms/ifnull/src/test/resources/org/apache/hop/pipeline/transforms/ifnull/v5.hpl
 
b/plugins/transforms/ifnull/src/test/resources/org/apache/hop/pipeline/transforms/ifnull/v5.hpl
deleted file mode 100644
index ed6a1b6f42..0000000000
--- 
a/plugins/transforms/ifnull/src/test/resources/org/apache/hop/pipeline/transforms/ifnull/v5.hpl
+++ /dev/null
@@ -1,194 +0,0 @@
-<?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>v5</name>
-    <description/>
-    <extended_description/>
-    <trans_version/>
-    <trans_type>Normal</trans_type>
-    <trans_status>0</trans_status>
-    <directory>&#x2f;</directory>
-    <parameters>
-    </parameters>
-    <log>
-<pipeline-log-table><connection/>
-<schema/>
-<table/>
-<size_limit_lines/>
-<interval/>
-<timeout_days/>
-<field><id>ID_BATCH</id><enabled>Y</enabled><name>ID_BATCH</name></field><field><id>CHANNEL_ID</id><enabled>Y</enabled><name>CHANNEL_ID</name></field><field><id>TRANSNAME</id><enabled>Y</enabled><name>TRANSNAME</name></field><field><id>STATUS</id><enabled>Y</enabled><name>STATUS</name></field><field><id>LINES_READ</id><enabled>Y</enabled><name>LINES_READ</name><subject/></field><field><id>LINES_WRITTEN</id><enabled>Y</enabled><name>LINES_WRITTEN</name><subject/></field><field><id>LINES_U
 [...]
-<perf-log-table><connection/>
-<schema/>
-<table/>
-<interval/>
-<timeout_days/>
-<field><id>ID_BATCH</id><enabled>Y</enabled><name>ID_BATCH</name></field><field><id>SEQ_NR</id><enabled>Y</enabled><name>SEQ_NR</name></field><field><id>LOGDATE</id><enabled>Y</enabled><name>LOGDATE</name></field><field><id>TRANSNAME</id><enabled>Y</enabled><name>TRANSNAME</name></field><field><id>STEPNAME</id><enabled>Y</enabled><name>STEPNAME</name></field><field><id>STEP_COPY</id><enabled>Y</enabled><name>STEP_COPY</name></field><field><id>LINES_READ</id><enabled>Y</enabled><name>LINE
 [...]
-<channel-log-table><connection/>
-<schema/>
-<table/>
-<timeout_days/>
-<field><id>ID_BATCH</id><enabled>Y</enabled><name>ID_BATCH</name></field><field><id>CHANNEL_ID</id><enabled>Y</enabled><name>CHANNEL_ID</name></field><field><id>LOG_DATE</id><enabled>Y</enabled><name>LOG_DATE</name></field><field><id>LOGGING_OBJECT_TYPE</id><enabled>Y</enabled><name>LOGGING_OBJECT_TYPE</name></field><field><id>OBJECT_NAME</id><enabled>Y</enabled><name>OBJECT_NAME</name></field><field><id>OBJECT_COPY</id><enabled>Y</enabled><name>OBJECT_COPY</name></field><field><id>REPOS
 [...]
-<transform-log-table><connection/>
-<schema/>
-<table/>
-<timeout_days/>
-<field><id>ID_BATCH</id><enabled>Y</enabled><name>ID_BATCH</name></field><field><id>CHANNEL_ID</id><enabled>Y</enabled><name>CHANNEL_ID</name></field><field><id>LOG_DATE</id><enabled>Y</enabled><name>LOG_DATE</name></field><field><id>TRANSNAME</id><enabled>Y</enabled><name>TRANSNAME</name></field><field><id>STEPNAME</id><enabled>Y</enabled><name>STEPNAME</name></field><field><id>STEP_COPY</id><enabled>Y</enabled><name>STEP_COPY</name></field><field><id>LINES_READ</id><enabled>Y</enabled>
 [...]
-<metrics-log-table><connection/>
-<schema/>
-<table/>
-<timeout_days/>
-<field><id>ID_BATCH</id><enabled>Y</enabled><name>ID_BATCH</name></field><field><id>CHANNEL_ID</id><enabled>Y</enabled><name>CHANNEL_ID</name></field><field><id>LOG_DATE</id><enabled>Y</enabled><name>LOG_DATE</name></field><field><id>METRICS_DATE</id><enabled>Y</enabled><name>METRICS_DATE</name></field><field><id>METRICS_CODE</id><enabled>Y</enabled><name>METRICS_CODE</name></field><field><id>METRICS_DESCRIPTION</id><enabled>Y</enabled><name>METRICS_DESCRIPTION</name></field><field><id>M
 [...]
-    </log>
-    <maxdate>
-      <connection/>
-      <table/>
-      <field/>
-      <offset>0.0</offset>
-      <maxdiff>0.0</maxdiff>
-    </maxdate>
-    <size_rowset>10000</size_rowset>
-    <sleep_time_empty>50</sleep_time_empty>
-    <sleep_time_full>50</sleep_time_full>
-    <unique_connections>N</unique_connections>
-    <feedback_shown>Y</feedback_shown>
-    <feedback_size>50000</feedback_size>
-    <using_thread_priorities>Y</using_thread_priorities>
-    <shared_objects_file/>
-    <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>
-    <dependencies>
-    </dependencies>
-    <partitionschemas>
-    </partitionschemas>
-    <hop-servers>
-         
<hop-server><name>8081</name><hostname>localhost</hostname><port>8081</port><webAppName/><username>cluster</username><password>Encrypted
 
2be98afc86aa7f2e4cb1aa265cd86aac8</password><proxy_hostname/><proxy_port/><non_proxy_hosts/><master>Y</master></hop-server>
-    </hop-servers>
-    <clusterschemas>
-    </clusterschemas>
-  <created_user>-</created_user>
-  <created_date>2014&#x2f;02&#x2f;25 12&#x3a;51&#x3a;44.876</created_date>
-  <modified_user>-</modified_user>
-  <modified_date>2014&#x2f;02&#x2f;25 12&#x3a;51&#x3a;44.876</modified_date>
-  </info>
-  <notepads>
-  </notepads>
-  <order>
-  <hop> <from>Generate Rows</from><to>If field value is 
null</to><enabled>Y</enabled> </hop>
-  </order>
-  <transform>
-    <name>Generate Rows</name>
-    <type>RowGenerator</type>
-    <description/>
-    <distribute>Y</distribute>
-    <custom_distribution/>
-    <copies>1</copies>
-         <partitioning>
-           <method>none</method>
-           <schema_name/>
-           </partitioning>
-    <fields>
-      <field>
-        <name>a</name>
-        <type>String</type>
-        <format/>
-        <currency/>
-        <decimal/>
-        <group/>
-        <nullif/>
-        <length>-1</length>
-        <precision>-1</precision>
-        <set_empty_string>N</set_empty_string>
-      </field>
-      <field>
-        <name>b</name>
-        <type>Number</type>
-        <format/>
-        <currency/>
-        <decimal/>
-        <group/>
-        <nullif/>
-        <length>-1</length>
-        <precision>-1</precision>
-        <set_empty_string>N</set_empty_string>
-      </field>
-    </fields>
-    <limit>10</limit>
-    <never_ending>N</never_ending>
-    <interval_in_ms/>
-    <row_time_field/>
-    <last_time_field/>
- <input>   </input>   <output>   </output>     <GUI>
-      <xloc>146</xloc>
-      <yloc>142</yloc>
-      <draw>Y</draw>
-      </GUI>
-    </transform>
-
-  <transform>
-    <name>If field value is null</name>
-    <type>IfNull</type>
-    <description/>
-    <distribute>Y</distribute>
-    <custom_distribution/>
-    <copies>1</copies>
-         <partitioning>
-           <method>none</method>
-           <schema_name/>
-           </partitioning>
-      <replaceAllByValue/>
-      <replaceAllMask/>
-      <selectFields>N</selectFields>
-      <selectValuesType>Y</selectValuesType>
-      <setEmptyStringAll>N</setEmptyStringAll>
-    <valuetypes>
-      <valuetype>
-        <name>String</name>
-        <value/>
-        <mask/>
-        <set_type_empty_string>Y</set_type_empty_string>
-        </valuetype>
-      <valuetype>
-        <name>Number</name>
-        <value/>
-        <mask/>
-        <set_type_empty_string>N</set_type_empty_string>
-        </valuetype>
-      <valuetype>
-        <name>Date</name>
-        <value/>
-        <mask/>
-        <set_type_empty_string>N</set_type_empty_string>
-        </valuetype>
-      </valuetypes>
-    <fields>
-      </fields>
- <input>   </input>   <output>   </output>     <GUI>
-      <xloc>290</xloc>
-      <yloc>143</yloc>
-      <draw>Y</draw>
-      </GUI>
-    </transform>
-
-  <transform_error_handling>
-  </transform_error_handling>
- </pipeline>

Reply via email to