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 2021/09/23 07:42:13 UTC

[incubator-hop] branch master updated: HOP-3053 Add MDI support to Database join - Add MDI support - Add keywords - Connection can use variable - Fix sonar issues

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/incubator-hop.git


The following commit(s) were added to refs/heads/master by this push:
     new 96ad2f9  HOP-3053 Add MDI support to Database join - Add MDI support - Add keywords - Connection can use variable - Fix sonar issues
     new 388d6cd  Merge pull request #1075 from nadment/HOP-3053
96ad2f9 is described below

commit 96ad2f917989db6e8f6596fef56d30d9e47f788f
Author: Nicolas Adment <na...@gmail.com>
AuthorDate: Wed Sep 22 20:47:49 2021 +0200

    HOP-3053 Add MDI support to Database join
    - Add MDI support
    - Add keywords
    - Connection can use variable
    - Fix sonar issues
---
 .../transforms/databasejoin/DatabaseJoin.java      |  28 +--
 .../transforms/databasejoin/DatabaseJoinData.java  |   4 -
 .../databasejoin/DatabaseJoinDialog.java           |  63 +++---
 .../transforms/databasejoin/DatabaseJoinMeta.java  | 246 ++++++++-------------
 .../transforms/databasejoin/ParameterField.java    |  82 +++++++
 .../messages/messages_de_DE.properties             |   4 +-
 .../messages/messages_en_US.properties             |  13 +-
 .../messages/messages_es_AR.properties             |   4 +-
 .../messages/messages_es_ES.properties             |   4 +-
 .../messages/messages_fr_FR.properties             |   6 +-
 .../messages/messages_ja_JP.properties             |   4 +-
 .../messages/messages_zh_CN.properties             |   4 +-
 .../databasejoin/DatabaseJoinMetaTest.java         |  72 +++---
 13 files changed, 288 insertions(+), 246 deletions(-)

diff --git a/plugins/transforms/databasejoin/src/main/java/org/apache/hop/pipeline/transforms/databasejoin/DatabaseJoin.java b/plugins/transforms/databasejoin/src/main/java/org/apache/hop/pipeline/transforms/databasejoin/DatabaseJoin.java
index c5964e3..b6b8ed8 100644
--- a/plugins/transforms/databasejoin/src/main/java/org/apache/hop/pipeline/transforms/databasejoin/DatabaseJoin.java
+++ b/plugins/transforms/databasejoin/src/main/java/org/apache/hop/pipeline/transforms/databasejoin/DatabaseJoin.java
@@ -18,6 +18,7 @@
 package org.apache.hop.pipeline.transforms.databasejoin;
 
 import org.apache.hop.core.database.Database;
+import org.apache.hop.core.database.DatabaseMeta;
 import org.apache.hop.core.exception.HopException;
 import org.apache.hop.core.exception.HopTransformException;
 import org.apache.hop.core.row.IRowMeta;
@@ -33,11 +34,8 @@ import org.apache.hop.pipeline.transform.TransformMeta;
 import java.sql.ResultSet;
 
 /**
- * Use values from input streams to joins with values in a database. Freehand SQL can be used to do
- * this.
- *
- * @author Matt
- * @since 26-apr-2003
+ * Use values from input streams to joins with values in a database.
+ * Freehand SQL can be used to do this.
  */
 public class DatabaseJoin extends BaseTransform<DatabaseJoinMeta, DatabaseJoinData>
     implements ITransform<DatabaseJoinMeta, DatabaseJoinData> {
@@ -77,14 +75,16 @@ public class DatabaseJoin extends BaseTransform<DatabaseJoinMeta, DatabaseJoinDa
                 + rowMeta.getString(rowData));
       }
 
-      data.keynrs = new int[meta.getParameterField().length];
+      data.keynrs = new int[meta.getParameters().size()];
 
-      for (int i = 0; i < meta.getParameterField().length; i++) {
-        data.keynrs[i] = rowMeta.indexOfValue(meta.getParameterField()[i]);
+      
+      for (int i = 0; i < data.keynrs.length; i++) {
+        ParameterField field = meta.getParameters().get(i);
+        data.keynrs[i] = rowMeta.indexOfValue(field.getName());
         if (data.keynrs[i] < 0) {
           throw new HopTransformException(
               BaseMessages.getString(
-                  PKG, "DatabaseJoin.Exception.FieldNotFound", meta.getParameterField()[i]));
+                  PKG, "DatabaseJoin.Exception.FieldNotFound", field.getName()));
         }
 
         data.lookupRowMeta.addValueMeta(rowMeta.getValueMeta(data.keynrs[i]).clone());
@@ -218,11 +218,13 @@ public class DatabaseJoin extends BaseTransform<DatabaseJoinMeta, DatabaseJoinDa
   @Override
   public boolean init() {
     if (super.init()) {
-      if (meta.getDatabaseMeta() == null) {
-        logError(
-            BaseMessages.getString(PKG, "DatabaseJoin.Init.ConnectionMissing", getTransformName()));
+      DatabaseMeta databaseMeta = getPipelineMeta().findDatabase(meta.getConnection(), variables);
+      if (databaseMeta == null) {
+        logError(BaseMessages.getString(PKG, "DatabaseJoin.Init.ConnectionMissing", getTransformName()));
         return false;
       }
+
+      meta.setDatabaseMeta(databaseMeta);
       data.db = new Database(this, this, meta.getDatabaseMeta());
 
       try {
@@ -233,7 +235,7 @@ public class DatabaseJoin extends BaseTransform<DatabaseJoinMeta, DatabaseJoinDa
         }
 
         String sql = meta.getSql();
-        if (meta.isVariableReplace()) {
+        if (meta.isReplaceVariables()) {
           sql = resolve(sql);
         }
         // Prepare the SQL statement
diff --git a/plugins/transforms/databasejoin/src/main/java/org/apache/hop/pipeline/transforms/databasejoin/DatabaseJoinData.java b/plugins/transforms/databasejoin/src/main/java/org/apache/hop/pipeline/transforms/databasejoin/DatabaseJoinData.java
index c33e2c8..ab96239 100644
--- a/plugins/transforms/databasejoin/src/main/java/org/apache/hop/pipeline/transforms/databasejoin/DatabaseJoinData.java
+++ b/plugins/transforms/databasejoin/src/main/java/org/apache/hop/pipeline/transforms/databasejoin/DatabaseJoinData.java
@@ -24,10 +24,6 @@ import org.apache.hop.pipeline.transform.ITransformData;
 
 import java.sql.PreparedStatement;
 
-/**
- * @author Matt
- * @since 24-jan-2005
- */
 public class DatabaseJoinData extends BaseTransformData implements ITransformData {
   public Database db;
   public PreparedStatement pstmt;
diff --git a/plugins/transforms/databasejoin/src/main/java/org/apache/hop/pipeline/transforms/databasejoin/DatabaseJoinDialog.java b/plugins/transforms/databasejoin/src/main/java/org/apache/hop/pipeline/transforms/databasejoin/DatabaseJoinDialog.java
index 62c69ba..a3830ff 100644
--- a/plugins/transforms/databasejoin/src/main/java/org/apache/hop/pipeline/transforms/databasejoin/DatabaseJoinDialog.java
+++ b/plugins/transforms/databasejoin/src/main/java/org/apache/hop/pipeline/transforms/databasejoin/DatabaseJoinDialog.java
@@ -60,7 +60,7 @@ public class DatabaseJoinDialog extends BaseTransformDialog implements ITransfor
 
   private TableView wParam;
 
-  private Button wuseVars;
+  private Button wUseVars;
 
   private final DatabaseJoinMeta input;
 
@@ -246,14 +246,14 @@ public class DatabaseJoinDialog extends BaseTransformDialog implements ITransfor
     fdluseVars.right = new FormAttachment(middle, -margin);
     fdluseVars.top = new FormAttachment(wOuter, margin);
     wluseVars.setLayoutData(fdluseVars);
-    wuseVars = new Button(shell, SWT.CHECK);
-    props.setLook(wuseVars);
-    wuseVars.setToolTipText(wluseVars.getToolTipText());
+    wUseVars = new Button(shell, SWT.CHECK);
+    props.setLook(wUseVars);
+    wUseVars.setToolTipText(wluseVars.getToolTipText());
     FormData fduseVars = new FormData();
     fduseVars.left = new FormAttachment(middle, 0);
     fduseVars.top = new FormAttachment(wluseVars, 0, SWT.CENTER);
-    wuseVars.setLayoutData(fduseVars);
-    wuseVars.addSelectionListener(
+    wUseVars.setLayoutData(fduseVars);
+    wUseVars.addSelectionListener(
         new SelectionAdapter() {
           @Override
           public void widgetSelected(SelectionEvent e) {
@@ -277,11 +277,11 @@ public class DatabaseJoinDialog extends BaseTransformDialog implements ITransfor
     props.setLook(wlParam);
     FormData fdlParam = new FormData();
     fdlParam.left = new FormAttachment(0, 0);
-    fdlParam.top = new FormAttachment(wuseVars, margin);
+    fdlParam.top = new FormAttachment(wUseVars, margin);
     wlParam.setLayoutData(fdlParam);
 
     int nrKeyCols = 2;
-    int nrKeyRows = (input.getParameterField() != null ? input.getParameterField().length : 1);
+    int nrKeyRows = (input.getParameters() != null ? input.getParameters().size() : 1);
 
     ciKey = new ColumnInfo[nrKeyCols];
     ciKey[0] =
@@ -376,26 +376,22 @@ public class DatabaseJoinDialog extends BaseTransformDialog implements ITransfor
   public void getData() {
     logDebug(BaseMessages.getString(PKG, "DatabaseJoinDialog.Log.GettingKeyInfo"));
 
+    wConnection.setText(Const.NVL(input.getConnection(), ""));
     wSql.setText(Const.NVL(input.getSql(), ""));
     wLimit.setText("" + input.getRowLimit());
     wOuter.setSelection(input.isOuterJoin());
-    wuseVars.setSelection(input.isVariableReplace());
-    if (input.getParameterField() != null) {
-      for (int i = 0; i < input.getParameterField().length; i++) {
-        TableItem item = wParam.table.getItem(i);
-        if (input.getParameterField()[i] != null) {
-          item.setText(1, input.getParameterField()[i]);
-        }
-        if (input.getParameterType()[i] != 0) {
-          item.setText(2, ValueMetaFactory.getValueMetaName(input.getParameterType()[i]));
+    wUseVars.setSelection(input.isReplaceVariables());
+    if (input.getParameters() != null) {
+      int i = 0;
+      for (ParameterField field: input.getParameters()) {
+        TableItem item = wParam.table.getItem(i++);
+        if (field != null) {
+          item.setText(1, field.getName());
+          item.setText(2, field.getType());
         }
       }
-    }
-
-    if (input.getDatabaseMeta() != null) {
-      wConnection.setText(input.getDatabaseMeta().getName());
-    }
-
+    }  
+    
     wParam.setRowNums();
     wParam.optWidth(true);
 
@@ -416,29 +412,30 @@ public class DatabaseJoinDialog extends BaseTransformDialog implements ITransfor
 
     int nrparam = wParam.nrNonEmpty();
 
-    input.allocate(nrparam);
-
+    input.setConnection(wConnection.getText());
+    input.setDatabaseMeta(pipelineMeta.findDatabase(wConnection.getText(), variables));
     input.setRowLimit(Const.toInt(wLimit.getText(), 0));
     input.setSql(wSql.getText());
-
     input.setOuterJoin(wOuter.getSelection());
-    input.setVariableReplace(wuseVars.getSelection());
+    input.setReplaceVariables(wUseVars.getSelection());
     logDebug(
         BaseMessages.getString(PKG, "DatabaseJoinDialog.Log.ParametersFound")
             + nrparam
             + " parameters");
-    // CHECKSTYLE:Indentation:OFF
+ 
+    List<ParameterField> parameters = new ArrayList<>();    
     for (int i = 0; i < nrparam; i++) {
       TableItem item = wParam.getNonEmpty(i);
-      input.getParameterField()[i] = item.getText(1);
-      input.getParameterType()[i] = ValueMetaFactory.getIdForValueMeta(item.getText(2));
+      ParameterField field = new ParameterField();
+      field.setName(item.getText(1));
+      field.setType(ValueMetaFactory.getIdForValueMeta(item.getText(2)));
+      parameters.add(field);
     }
-
-    input.setDatabaseMeta(pipelineMeta.findDatabase(wConnection.getText()));
+    input.setParameters(parameters);      
 
     transformName = wTransformName.getText(); // return value
 
-    if (pipelineMeta.findDatabase(wConnection.getText()) == null) {
+    if (pipelineMeta.findDatabase(wConnection.getText(), variables) == null) {
       MessageBox mb = new MessageBox(shell, SWT.OK | SWT.ICON_ERROR);
       mb.setMessage(
           BaseMessages.getString(PKG, "DatabaseJoinDialog.InvalidConnection.DialogMessage"));
diff --git a/plugins/transforms/databasejoin/src/main/java/org/apache/hop/pipeline/transforms/databasejoin/DatabaseJoinMeta.java b/plugins/transforms/databasejoin/src/main/java/org/apache/hop/pipeline/transforms/databasejoin/DatabaseJoinMeta.java
index 6879f83..89307b8 100644
--- a/plugins/transforms/databasejoin/src/main/java/org/apache/hop/pipeline/transforms/databasejoin/DatabaseJoinMeta.java
+++ b/plugins/transforms/databasejoin/src/main/java/org/apache/hop/pipeline/transforms/databasejoin/DatabaseJoinMeta.java
@@ -30,8 +30,8 @@ import org.apache.hop.core.row.RowMeta;
 import org.apache.hop.core.row.value.ValueMetaFactory;
 import org.apache.hop.core.row.value.ValueMetaNone;
 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.DatabaseImpact;
 import org.apache.hop.pipeline.Pipeline;
@@ -39,50 +39,85 @@ import org.apache.hop.pipeline.PipelineMeta;
 import org.apache.hop.pipeline.transform.BaseTransformMeta;
 import org.apache.hop.pipeline.transform.ITransformMeta;
 import org.apache.hop.pipeline.transform.TransformMeta;
-import org.w3c.dom.Node;
 
+import java.util.ArrayList;
 import java.util.List;
 
 @Transform(
     id = "DBJoin",
     image = "dbjoin.svg",
-    name = "i18n::BaseTransform.TypeLongDesc.DatabaseJoin",
-    description = "i18n::BaseTransform.TypeTooltipDesc.DatabaseJoin",
+    name = "i18n::DatabaseJoin.Name",
+    description = "i18n::DatabaseJoin.Description",
     categoryDescription = "i18n:org.apache.hop.pipeline.transform:BaseTransform.Category.Lookup",
-    documentationUrl = "/pipeline/transforms/databasejoin.html")
+    documentationUrl = "/pipeline/transforms/databasejoin.html",
+    keywords = "sql")
 public class DatabaseJoinMeta extends BaseTransformMeta
     implements ITransformMeta<DatabaseJoin, DatabaseJoinData> {
 
   private static final Class<?> PKG = DatabaseJoinMeta.class; // For Translator
 
-  /** database connection */
+  @HopMetadataProperty(key = "connection",
+      injectionKeyDescription = "DatabaseJoinMeta.Injection.Connection")
+  private String connection;
+
+  /** Database connection */
   private DatabaseMeta databaseMeta;
 
   /** SQL Statement */
+  @HopMetadataProperty(key = "sql", injectionKeyDescription = "DatabaseJoinMeta.Injection.SQL")
   private String sql;
 
   /** Number of rows to return (0=ALL) */
+  @HopMetadataProperty(key = "rowlimit",
+      injectionKeyDescription = "DatabaseJoinMeta.Injection.RowLimit")
   private int rowLimit;
 
   /**
-   * false: don't return rows where nothing is found true: at least return one source row, the rest
-   * is NULL
+   * false: don't return rows where nothing is found
+   * true: at least return one source row, the rest is NULL
    */
+  @HopMetadataProperty(key = "outer_join",
+      injectionKeyDescription = "DatabaseJoinMeta.Injection.OuterJoin")
   private boolean outerJoin;
 
   /** Fields to use as parameters (fill in the ? markers) */
-  private String[] parameterField;
-
-  /** Type of the paramenters */
-  private int[] parameterType;
-
-  /** false: don't replave variable in scrip true: replace variable in script */
-  private boolean replacevars;
+  @HopMetadataProperty(key = "field", groupKey = "parameter",
+      injectionGroupDescription = "DatabaseJoinMeta.Injection.Parameters",
+      injectionKeyDescription = "DatabaseJoinMeta.Injection.Field")
+  private List<ParameterField> parameters = new ArrayList<>();
+  
+  /** 
+   * false: don't replace variable in script 
+   * true: replace variable in script 
+   */
+  @HopMetadataProperty(key = "replace_vars", injectionKeyDescription = "DatabaseJoinMeta.Injection.ReplaceVariables")
+  private boolean replaceVariables;
 
   public DatabaseJoinMeta() {
     super(); // allocate BaseTransformMeta
   }
 
+  public DatabaseJoinMeta(final DatabaseJoinMeta clone) {
+    super();
+
+    this.connection = clone.connection;
+    this.sql = clone.sql;
+    this.rowLimit = clone.rowLimit;
+    this.outerJoin = clone.outerJoin;
+    this.replaceVariables = clone.replaceVariables;    
+    for (ParameterField field : clone.parameters) {
+      parameters.add(new ParameterField(field));
+    }
+  }
+  
+  public String getConnection() {
+    return connection;
+  }
+
+  public void setConnection(String connection) {
+    this.connection = connection;
+  }
+  
   /** @return Returns the database. */
   public DatabaseMeta getDatabaseMeta() {
     return databaseMeta;
@@ -104,33 +139,13 @@ public class DatabaseJoinMeta extends BaseTransformMeta
   }
 
   /** @return Returns the replacevars. */
-  public boolean isVariableReplace() {
-    return replacevars;
+  public boolean isReplaceVariables() {
+    return replaceVariables;
   }
 
   /** @param replacevars The replacevars to set. */
-  public void setVariableReplace(boolean replacevars) {
-    this.replacevars = replacevars;
-  }
-
-  /** @return Returns the parameterField. */
-  public String[] getParameterField() {
-    return parameterField;
-  }
-
-  /** @param parameterField The parameterField to set. */
-  public void setParameterField(String[] parameterField) {
-    this.parameterField = parameterField;
-  }
-
-  /** @return Returns the parameterType. */
-  public int[] getParameterType() {
-    return parameterType;
-  }
-
-  /** @param parameterType The parameterType to set. */
-  public void setParameterType(int[] parameterType) {
-    this.parameterType = parameterType;
+  public void setReplaceVariables(boolean enabled) {
+    this.replaceVariables = enabled;
   }
 
   /** @return Returns the rowLimit. */
@@ -154,59 +169,8 @@ public class DatabaseJoinMeta extends BaseTransformMeta
   }
 
   @Override
-  public void loadXml(Node transformNode, IHopMetadataProvider metadataProvider)
-      throws HopXmlException {
-    parameterField = null;
-    parameterType = null;
-    outerJoin = false;
-    replacevars = false;
-    readData(transformNode, metadataProvider);
-  }
-
-  public void allocate(int nrparam) {
-    parameterField = new String[nrparam];
-    parameterType = new int[nrparam];
-  }
-
-  @Override
   public Object clone() {
-    DatabaseJoinMeta retval = (DatabaseJoinMeta) super.clone();
-
-    int nrparam = parameterField.length;
-
-    retval.allocate(nrparam);
-
-    System.arraycopy(parameterField, 0, retval.parameterField, 0, nrparam);
-    System.arraycopy(parameterType, 0, retval.parameterType, 0, nrparam);
-
-    return retval;
-  }
-
-  private void readData(Node transformNode, IHopMetadataProvider metadataProvider)
-      throws HopXmlException {
-    try {
-      String con = XmlHandler.getTagValue(transformNode, "connection");
-      databaseMeta = DatabaseMeta.loadDatabase(metadataProvider, con);
-      sql = XmlHandler.getTagValue(transformNode, "sql");
-      outerJoin = "Y".equalsIgnoreCase(XmlHandler.getTagValue(transformNode, "outer_join"));
-      replacevars = "Y".equalsIgnoreCase(XmlHandler.getTagValue(transformNode, "replace_vars"));
-      rowLimit = Const.toInt(XmlHandler.getTagValue(transformNode, "rowlimit"), 0);
-
-      Node param = XmlHandler.getSubNode(transformNode, "parameter");
-      int nrparam = XmlHandler.countNodes(param, "field");
-
-      allocate(nrparam);
-
-      for (int i = 0; i < nrparam; i++) {
-        Node pnode = XmlHandler.getSubNodeByNr(param, "field", i);
-        parameterField[i] = XmlHandler.getTagValue(pnode, "name");
-        String ptype = XmlHandler.getTagValue(pnode, "type");
-        parameterType[i] = ValueMetaFactory.getIdForValueMeta(ptype);
-      }
-    } catch (Exception e) {
-      throw new HopXmlException(
-          BaseMessages.getString(PKG, "DatabaseJoinMeta.Exception.UnableToLoadTransformMeta"), e);
-    }
+    return new DatabaseJoinMeta(this);
   }
 
   @Override
@@ -215,32 +179,22 @@ public class DatabaseJoinMeta extends BaseTransformMeta
     rowLimit = 0;
     sql = "";
     outerJoin = false;
-    parameterField = null;
-    parameterType = null;
-    outerJoin = false;
-    replacevars = false;
-
-    int nrparam = 0;
-
-    allocate(nrparam);
-
-    for (int i = 0; i < nrparam; i++) {
-      parameterField[i] = "param" + i;
-      parameterType[i] = IValueMeta.TYPE_NUMBER;
-    }
+    replaceVariables = false;
+    parameters = new ArrayList<>();
   }
 
   public IRowMeta getParameterRow(IRowMeta fields) {
     IRowMeta param = new RowMeta();
 
     if (fields != null) {
-      for (int i = 0; i < parameterField.length; i++) {
-        IValueMeta v = fields.searchValueMeta(parameterField[i]);
-        if (v != null) {
-          param.addValueMeta(v);
+      for (ParameterField field: this.parameters) {
+        IValueMeta valueMeta = fields.searchValueMeta(field.getName());
+        if (valueMeta != null) {
+          param.addValueMeta(valueMeta);
         }
       }
     }
+        
     return param;
   }
 
@@ -306,34 +260,6 @@ public class DatabaseJoinMeta extends BaseTransformMeta
   }
 
   @Override
-  public String getXml() {
-    StringBuilder retval = new StringBuilder(300);
-
-    retval
-        .append("    ")
-        .append(
-            XmlHandler.addTagValue(
-                "connection", databaseMeta == null ? "" : databaseMeta.getName()));
-    retval.append("    ").append(XmlHandler.addTagValue("rowlimit", rowLimit));
-    retval.append("    ").append(XmlHandler.addTagValue("sql", sql));
-    retval.append("    ").append(XmlHandler.addTagValue("outer_join", outerJoin));
-    retval.append("    ").append(XmlHandler.addTagValue("replace_vars", replacevars));
-    retval.append("    <parameter>").append(Const.CR);
-    for (int i = 0; i < parameterField.length; i++) {
-      retval.append("      <field>").append(Const.CR);
-      retval.append("        ").append(XmlHandler.addTagValue("name", parameterField[i]));
-      retval
-          .append("        ")
-          .append(
-              XmlHandler.addTagValue("type", ValueMetaFactory.getValueMetaName(parameterType[i])));
-      retval.append("      </field>").append(Const.CR);
-    }
-    retval.append("    </parameter>").append(Const.CR);
-
-    return retval.toString();
-  }
-
-  @Override
   public void check(
       List<ICheckResult> remarks,
       PipelineMeta pipelineMeta,
@@ -364,7 +290,7 @@ public class DatabaseJoinMeta extends BaseTransformMeta
           if (r != null) {
             cr =
                 new CheckResult(
-                    CheckResult.TYPE_RESULT_OK,
+                    ICheckResult.TYPE_RESULT_OK,
                     BaseMessages.getString(PKG, "DatabaseJoinMeta.CheckResult.QueryOK"),
                     transformMeta);
             remarks.add(cr);
@@ -376,7 +302,7 @@ public class DatabaseJoinMeta extends BaseTransformMeta
           }
 
           int q = db.countParameters(variables.resolve(sql));
-          if (q != parameterField.length) {
+          if (q != parameters.size() ) {
             errorMessage =
                 BaseMessages.getString(
                         PKG, "DatabaseJoinMeta.CheckResult.DismatchBetweenParametersAndQuestion")
@@ -389,14 +315,14 @@ public class DatabaseJoinMeta extends BaseTransformMeta
             errorMessage +=
                 BaseMessages.getString(
                         PKG, "DatabaseJoinMeta.CheckResult.DismatchBetweenParametersAndQuestion3")
-                    + parameterField.length;
+                    + parameters.size();
 
-            cr = new CheckResult(CheckResult.TYPE_RESULT_ERROR, errorMessage, transformMeta);
+            cr = new CheckResult(ICheckResult.TYPE_RESULT_ERROR, errorMessage, transformMeta);
             remarks.add(cr);
           } else {
             cr =
                 new CheckResult(
-                    CheckResult.TYPE_RESULT_OK,
+                    ICheckResult.TYPE_RESULT_OK,
                     BaseMessages.getString(PKG, "DatabaseJoinMeta.CheckResult.NumberOfParamCorrect")
                         + q
                         + ")",
@@ -411,8 +337,8 @@ public class DatabaseJoinMeta extends BaseTransformMeta
           errorMessage = "";
           boolean errorFound = false;
 
-          for (int i = 0; i < parameterField.length; i++) {
-            IValueMeta v = prev.searchValueMeta(parameterField[i]);
+          for (ParameterField field: this.parameters) {
+            IValueMeta v = prev.searchValueMeta(field.getName());
             if (v == null) {
               if (first) {
                 first = false;
@@ -421,15 +347,15 @@ public class DatabaseJoinMeta extends BaseTransformMeta
                         + Const.CR;
               }
               errorFound = true;
-              errorMessage += "\t\t" + parameterField[i] + Const.CR;
+              errorMessage += "\t\t" + field.getName() + Const.CR;
             }
           }
           if (errorFound) {
-            cr = new CheckResult(CheckResult.TYPE_RESULT_ERROR, errorMessage, transformMeta);
+            cr = new CheckResult(ICheckResult.TYPE_RESULT_ERROR, errorMessage, transformMeta);
           } else {
             cr =
                 new CheckResult(
-                    CheckResult.TYPE_RESULT_OK,
+                    ICheckResult.TYPE_RESULT_OK,
                     BaseMessages.getString(PKG, "DatabaseJoinMeta.CheckResult.AllFieldsFound"),
                     transformMeta);
           }
@@ -438,21 +364,21 @@ public class DatabaseJoinMeta extends BaseTransformMeta
           errorMessage =
               BaseMessages.getString(PKG, "DatabaseJoinMeta.CheckResult.CounldNotReadFields")
                   + Const.CR;
-          cr = new CheckResult(CheckResult.TYPE_RESULT_ERROR, errorMessage, transformMeta);
+          cr = new CheckResult(ICheckResult.TYPE_RESULT_ERROR, errorMessage, transformMeta);
           remarks.add(cr);
         }
       } catch (HopException e) {
         errorMessage =
             BaseMessages.getString(PKG, "DatabaseJoinMeta.CheckResult.ErrorOccurred")
                 + e.getMessage();
-        cr = new CheckResult(CheckResult.TYPE_RESULT_ERROR, errorMessage, transformMeta);
+        cr = new CheckResult(ICheckResult.TYPE_RESULT_ERROR, errorMessage, transformMeta);
         remarks.add(cr);
       } finally {
         db.disconnect();
       }
     } else {
       errorMessage = BaseMessages.getString(PKG, "DatabaseJoinMeta.CheckResult.InvalidConnection");
-      cr = new CheckResult(CheckResult.TYPE_RESULT_ERROR, errorMessage, transformMeta);
+      cr = new CheckResult(ICheckResult.TYPE_RESULT_ERROR, errorMessage, transformMeta);
       remarks.add(cr);
     }
 
@@ -460,14 +386,14 @@ public class DatabaseJoinMeta extends BaseTransformMeta
     if (input.length > 0) {
       cr =
           new CheckResult(
-              CheckResult.TYPE_RESULT_OK,
+              ICheckResult.TYPE_RESULT_OK,
               BaseMessages.getString(PKG, "DatabaseJoinMeta.CheckResult.ReceivingInfo"),
               transformMeta);
       remarks.add(cr);
     } else {
       cr =
           new CheckResult(
-              CheckResult.TYPE_RESULT_ERROR,
+              ICheckResult.TYPE_RESULT_ERROR,
               BaseMessages.getString(PKG, "DatabaseJoinMeta.CheckResult.NoInputReceived"),
               transformMeta);
       remarks.add(cr);
@@ -479,16 +405,18 @@ public class DatabaseJoinMeta extends BaseTransformMeta
     // Build a dummy parameter row...
     //
     IRowMeta param = new RowMeta();
-    for (int i = 0; i < parameterField.length; i++) {
+    for (ParameterField field: this.parameters) {
       IValueMeta v;
       try {
-        v = ValueMetaFactory.createValueMeta(parameterField[i], parameterType[i]);
+        int id = ValueMetaFactory.getIdForValueMeta(field.getType());            
+        v = ValueMetaFactory.createValueMeta(field.getName(), id);
       } catch (HopPluginException e) {
-        v = new ValueMetaNone(parameterField[i]);
+        v = new ValueMetaNone(field.getName());
       }
       param.addValueMeta(v);
     }
-
+    
+    
     IRowMeta fields = null;
     if (databaseMeta != null) {
       Database db = new Database(loggingObject, variables, databaseMeta);
@@ -582,4 +510,12 @@ public class DatabaseJoinMeta extends BaseTransformMeta
   public boolean supportsErrorHandling() {
     return true;
   }
+  
+  public List<ParameterField> getParameters() {
+    return parameters;
+  }
+
+  public void setParameters(List<ParameterField> parameters) {
+    this.parameters = parameters;
+  }
 }
diff --git a/plugins/transforms/databasejoin/src/main/java/org/apache/hop/pipeline/transforms/databasejoin/ParameterField.java b/plugins/transforms/databasejoin/src/main/java/org/apache/hop/pipeline/transforms/databasejoin/ParameterField.java
new file mode 100644
index 0000000..6110522
--- /dev/null
+++ b/plugins/transforms/databasejoin/src/main/java/org/apache/hop/pipeline/transforms/databasejoin/ParameterField.java
@@ -0,0 +1,82 @@
+/*
+ * 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.databasejoin;
+
+import org.apache.commons.lang.StringUtils;
+import org.apache.hop.core.row.IValueMeta;
+import org.apache.hop.core.row.value.ValueMetaFactory;
+import org.apache.hop.metadata.api.HopMetadataProperty;
+/**
+ * The parameters field.
+ */
+public class ParameterField implements Cloneable {
+
+  /** The target field name */
+  @HopMetadataProperty(
+      key = "name",
+      injectionKey = "NAME",
+      injectionKeyDescription = "DatabaseJoinMeta.Injection.Parameter.Name")
+  private String name;
+
+  @HopMetadataProperty(
+      key = "type",
+      injectionKey = "TYPE",
+      injectionKeyDescription = "DatabaseJoinMeta.Injection.Parameter.Type")
+  private String type = ValueMetaFactory.getValueMetaName(IValueMeta.TYPE_NONE);
+
+
+  public ParameterField() {
+    super();
+  }
+
+  public ParameterField(ParameterField cloned) {
+    super();
+    this.name = cloned.name;
+    this.type = cloned.type;
+  }
+
+  @Override
+  public Object clone() {
+    return new ParameterField(this);
+  }
+
+  public String getName() {
+    return name;
+  }
+
+  public void setName(final String name) {
+    this.name = StringUtils.stripToNull(name);
+  }
+
+  public String getType() {
+    return this.type;
+  }
+
+  public void setType(final String type) {
+    this.type = type;
+  }
+  
+  public void setType(int id) {
+    this.type = ValueMetaFactory.getValueMetaName(id);
+  }
+
+  @Override
+  public String toString() {
+    return name + ":" + type;
+  }
+}
diff --git a/plugins/transforms/databasejoin/src/main/resources/org/apache/hop/pipeline/transforms/databasejoin/messages/messages_de_DE.properties b/plugins/transforms/databasejoin/src/main/resources/org/apache/hop/pipeline/transforms/databasejoin/messages/messages_de_DE.properties
index 19c9d03..e6561a6 100644
--- a/plugins/transforms/databasejoin/src/main/resources/org/apache/hop/pipeline/transforms/databasejoin/messages/messages_de_DE.properties
+++ b/plugins/transforms/databasejoin/src/main/resources/org/apache/hop/pipeline/transforms/databasejoin/messages/messages_de_DE.properties
@@ -17,8 +17,8 @@
 #
 #
 #
-BaseTransform.TypeLongDesc.DatabaseJoin=Datenbank-Join
-BaseTransform.TypeTooltipDesc.DatabaseJoin=F\u00FChrt eine Datenbankabfrage mit Parameter aus dem Datenstrom durch.
+DatabaseJoin.Name=Datenbank-Join
+DatabaseJoin.Description=F\u00FChrt eine Datenbankabfrage mit Parameter aus dem Datenstrom durch.
 DatabaseJoinDialog.Shell.Title=Datenbank-Join
 DatabaseJoinDialog.TransformName.Label=Schrittname 
 DatabaseJoinDialog.SQL.Label=SQL 
diff --git a/plugins/transforms/databasejoin/src/main/resources/org/apache/hop/pipeline/transforms/databasejoin/messages/messages_en_US.properties b/plugins/transforms/databasejoin/src/main/resources/org/apache/hop/pipeline/transforms/databasejoin/messages/messages_en_US.properties
index d4e6055..eed4027 100644
--- a/plugins/transforms/databasejoin/src/main/resources/org/apache/hop/pipeline/transforms/databasejoin/messages/messages_en_US.properties
+++ b/plugins/transforms/databasejoin/src/main/resources/org/apache/hop/pipeline/transforms/databasejoin/messages/messages_en_US.properties
@@ -14,8 +14,8 @@
 # See the License for the specific language governing permissions and
 # limitations under the License.
 #
-BaseTransform.TypeLongDesc.DatabaseJoin=Database join
-BaseTransform.TypeTooltipDesc.DatabaseJoin=Execute a database query using stream values as parameters
+DatabaseJoin.Name=Database join
+DatabaseJoin.Description=Execute a database query using stream values as parameters
 DatabaseJoinMeta.CheckResult.ErrorOccurred=An error occurred\: 
 DatabaseJoinDialog.InvalidConnection.DialogMessage=Please select a valid connection\!
 DatabaseJoinDialog.useVarsjoin.Label=Replace variables
@@ -62,3 +62,12 @@ DatabaseJoinMeta.CheckResult.InvalidDBQuery=Couldn''t verify the database query\
 DatabaseJoinDialog.GetFields.Button=\ &Get Fields 
 DatabaseJoin.Log.CheckingRow=Checking row\: 
 DatabaseJoin.Init.ConnectionMissing=Database connection is missing for transform [{0}]\!
+DatabaseJoinMeta.Injection.Connection=Connection
+DatabaseJoinMeta.Injection.SQL=SQL
+DatabaseJoinMeta.Injection.RowLimit=Number of rows to return
+DatabaseJoinMeta.Injection.OuterJoin=Outer join ? (Y/N)
+DatabaseJoinMeta.Injection.Field=Field
+DatabaseJoinMeta.Injection.Parameters=The parameter fields to use
+DatabaseJoinMeta.Injection.Parameter.Name=Field name
+DatabaseJoinMeta.Injection.Parameter.Type=Field type
+DatabaseJoinMeta.Injection.ReplaceVariables=Replace variables in SQL script ? (Y/N)
diff --git a/plugins/transforms/databasejoin/src/main/resources/org/apache/hop/pipeline/transforms/databasejoin/messages/messages_es_AR.properties b/plugins/transforms/databasejoin/src/main/resources/org/apache/hop/pipeline/transforms/databasejoin/messages/messages_es_AR.properties
index 643a0b1..6be1ed8 100644
--- a/plugins/transforms/databasejoin/src/main/resources/org/apache/hop/pipeline/transforms/databasejoin/messages/messages_es_AR.properties
+++ b/plugins/transforms/databasejoin/src/main/resources/org/apache/hop/pipeline/transforms/databasejoin/messages/messages_es_AR.properties
@@ -17,8 +17,8 @@
 #
 #
 #
-BaseTransform.TypeLongDesc.DatabaseJoin=Consulta base de datos
-BaseTransform.TypeTooltipDesc.DatabaseJoin=Ejecutar una consulta de base de datos utilizando valores de flujos como par\u00E1meteros
+DatabaseJoin.Name=Consulta base de datos
+DatabaseJoin.Description=Ejecutar una consulta de base de datos utilizando valores de flujos como par\u00E1meteros
 DatabaseJoinMeta.CheckResult.ErrorOccurred=Se ha producido un error\: 
 DatabaseJoinMeta.Exception.UnableToSaveTransformMeta=No se ha podido guardar la informaci\u00F3n del paso en el cat\u00E1logo para el paso con id\=
 DatabaseJoinDialog.InvalidConnection.DialogMessage=\u00A1Por favor seleccione una conexi\u00F3n v\u00E1lida\!
diff --git a/plugins/transforms/databasejoin/src/main/resources/org/apache/hop/pipeline/transforms/databasejoin/messages/messages_es_ES.properties b/plugins/transforms/databasejoin/src/main/resources/org/apache/hop/pipeline/transforms/databasejoin/messages/messages_es_ES.properties
index 34f5da1..f03d4c5 100644
--- a/plugins/transforms/databasejoin/src/main/resources/org/apache/hop/pipeline/transforms/databasejoin/messages/messages_es_ES.properties
+++ b/plugins/transforms/databasejoin/src/main/resources/org/apache/hop/pipeline/transforms/databasejoin/messages/messages_es_ES.properties
@@ -17,8 +17,8 @@
 #
 #
 #
-BaseTransform.TypeLongDesc.DatabaseJoin=Consulta base de datos
-BaseTransform.TypeTooltipDesc.DatabaseJoin=Ejecutar una consulta de base de datos utilizando valores de flujos como par\u00E1meteros
+DatabaseJoin.Name=Consulta base de datos
+DatabaseJoin.Description=Ejecutar una consulta de base de datos utilizando valores de flujos como par\u00E1meteros
 DatabaseJoinDialog.Shell.Title=Consulta a base de datos
 DatabaseJoinDialog.TransformName.Label=Nombre de paso 
 DatabaseJoinDialog.SQL.Label=SQL 
diff --git a/plugins/transforms/databasejoin/src/main/resources/org/apache/hop/pipeline/transforms/databasejoin/messages/messages_fr_FR.properties b/plugins/transforms/databasejoin/src/main/resources/org/apache/hop/pipeline/transforms/databasejoin/messages/messages_fr_FR.properties
index a56e11b..283f530 100644
--- a/plugins/transforms/databasejoin/src/main/resources/org/apache/hop/pipeline/transforms/databasejoin/messages/messages_fr_FR.properties
+++ b/plugins/transforms/databasejoin/src/main/resources/org/apache/hop/pipeline/transforms/databasejoin/messages/messages_fr_FR.properties
@@ -17,13 +17,13 @@
 #
 #
 #
-BaseTransform.TypeLongDesc.DatabaseJoin=Jointure base de donn\u00E9es
-BaseTransform.TypeTooltipDesc.DatabaseJoin=Ex\u00E9cuter une requ\u00EAte SQL en utilisant des param\u00E8tres
+DatabaseJoin.Description=Jointure base de donn\u00E9es
+DatabaseJoin.Description=Ex\u00E9cuter une requ\u00EAte SQL en utilisant des param\u00E8tres
 DatabaseJoinMeta.CheckResult.ErrorOccurred=Apache Hop a rencontr\u00E9e une erreur\: 
 DatabaseJoinMeta.Exception.UnableToSaveTransformMeta=Impossible de sauvegarder dans le r\u00E9f\u00E9rentiel  les informations de la transformation avec l''id\=
 DatabaseJoinDialog.InvalidConnection.DialogMessage=Veuillez svp s\u00E9lectionner une connexion valide\!
 DatabaseJoinDialog.useVarsjoin.Label=Remplacer variables dans script
-DatabaseJoinDialog.useVarsjoin.Tooltip=Remplacer les variables d''environnement\ndans le script SQL.
+DatabaseJoinDialog.useVarsjoin.Tooltip=Remplacer les variables d''environnement dans le script SQL.
 DatabaseJoinDialog.Limit.Label=Nombre de lignes \u00E0 retourner
 DatabaseJoinMeta.Log.DatabaseErrorOccurred=Apache Hop a rencontr\u00E9 une erreur de base de donn\u00E9es\: 
 DatabaseJoin.Log.DatabaseError=L''ex\u00E9cution va \u00EAtre arr\u00EAt\u00E9e suite \u00E0 une erreur\: 
diff --git a/plugins/transforms/databasejoin/src/main/resources/org/apache/hop/pipeline/transforms/databasejoin/messages/messages_ja_JP.properties b/plugins/transforms/databasejoin/src/main/resources/org/apache/hop/pipeline/transforms/databasejoin/messages/messages_ja_JP.properties
index 04e7499..3d29f4d 100644
--- a/plugins/transforms/databasejoin/src/main/resources/org/apache/hop/pipeline/transforms/databasejoin/messages/messages_ja_JP.properties
+++ b/plugins/transforms/databasejoin/src/main/resources/org/apache/hop/pipeline/transforms/databasejoin/messages/messages_ja_JP.properties
@@ -17,8 +17,8 @@
 #
 #
 #
-BaseTransform.TypeLongDesc.DatabaseJoin=\u30C7\u30FC\u30BF\u30D9\u30FC\u30B9\u7D50\u5408
-BaseTransform.TypeTooltipDesc.DatabaseJoin=Database join\n\u30D1\u30E9\u30E1\u30FC\u30BF\u3068\u3057\u3066\u30B9\u30C8\u30EA\u30FC\u30E0\u5024\u3092\u4F7F\u7528\u3057\u3001\u30C7\u30FC\u30BF\u30D9\u30FC\u30B9\u30AF\u30A8\u30EA\u30FC\u3092\u5B9F\u884C\u3057\u307E\u3059\u3002
+DatabaseJoin.Name=\u30C7\u30FC\u30BF\u30D9\u30FC\u30B9\u7D50\u5408
+DatabaseJoin.Description=Database join\n\u30D1\u30E9\u30E1\u30FC\u30BF\u3068\u3057\u3066\u30B9\u30C8\u30EA\u30FC\u30E0\u5024\u3092\u4F7F\u7528\u3057\u3001\u30C7\u30FC\u30BF\u30D9\u30FC\u30B9\u30AF\u30A8\u30EA\u30FC\u3092\u5B9F\u884C\u3057\u307E\u3059\u3002
 DatabaseJoinMeta.CheckResult.ErrorOccurred=An error occurred\: 
 DatabaseJoinDialog.InvalidConnection.DialogMessage=\u30C7\u30FC\u30BF\u30BD\u30FC\u30B9\u3092\u9078\u629E\u3057\u3066\u304F\u3060\u3055\u3044\u3002
 DatabaseJoinDialog.useVarsjoin.Label=\u30D1\u30E9\u30E1\u30FC\u30BF\u3092\u4F7F\u7528\u3059\u308B
diff --git a/plugins/transforms/databasejoin/src/main/resources/org/apache/hop/pipeline/transforms/databasejoin/messages/messages_zh_CN.properties b/plugins/transforms/databasejoin/src/main/resources/org/apache/hop/pipeline/transforms/databasejoin/messages/messages_zh_CN.properties
index d405191..8b86f79 100644
--- a/plugins/transforms/databasejoin/src/main/resources/org/apache/hop/pipeline/transforms/databasejoin/messages/messages_zh_CN.properties
+++ b/plugins/transforms/databasejoin/src/main/resources/org/apache/hop/pipeline/transforms/databasejoin/messages/messages_zh_CN.properties
@@ -17,8 +17,8 @@
 #
 #
 #
-BaseTransform.TypeLongDesc.DatabaseJoin=\u6570\u636E\u5E93\u8FDE\u63A5
-BaseTransform.TypeTooltipDesc.DatabaseJoin=\u4F7F\u7528\u6570\u636E\u6D41\u91CC\u7684\u503C\u4F5C\u4E3A\u53C2\u6570\u6267\u884C\u4E00\u4E2A\u6570\u636E\u5E93\u67E5\u8BE2
+DatabaseJoin.Name=\u6570\u636E\u5E93\u8FDE\u63A5
+DatabaseJoin.Description=\u4F7F\u7528\u6570\u636E\u6D41\u91CC\u7684\u503C\u4F5C\u4E3A\u53C2\u6570\u6267\u884C\u4E00\u4E2A\u6570\u636E\u5E93\u67E5\u8BE2
 DatabaseJoinDialog.Shell.Title=Database join
 DatabaseJoinDialog.TransformName.Label=\u6b65\u9aa4\u540d\u79f0 
 DatabaseJoinDialog.SQL.Label=SQL 
diff --git a/plugins/transforms/databasejoin/src/test/java/org/apache/hop/pipeline/transforms/databasejoin/DatabaseJoinMetaTest.java b/plugins/transforms/databasejoin/src/test/java/org/apache/hop/pipeline/transforms/databasejoin/DatabaseJoinMetaTest.java
index 73212bd..60216fa 100644
--- a/plugins/transforms/databasejoin/src/test/java/org/apache/hop/pipeline/transforms/databasejoin/DatabaseJoinMetaTest.java
+++ b/plugins/transforms/databasejoin/src/test/java/org/apache/hop/pipeline/transforms/databasejoin/DatabaseJoinMetaTest.java
@@ -16,58 +16,59 @@
  */
 package org.apache.hop.pipeline.transforms.databasejoin;
 
+import org.apache.commons.lang.builder.EqualsBuilder;
 import org.apache.hop.core.HopEnvironment;
 import org.apache.hop.core.exception.HopException;
 import org.apache.hop.core.plugins.PluginRegistry;
+import org.apache.hop.core.row.IValueMeta;
 import org.apache.hop.junit.rules.RestoreHopEngineEnvironment;
-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.*;
 import org.junit.Before;
+import org.junit.BeforeClass;
 import org.junit.ClassRule;
 import org.junit.Test;
 
 import java.util.*;
 
-public class DatabaseJoinMetaTest implements IInitializer<ITransformMeta> {
-  LoadSaveTester loadSaveTester;
+public class DatabaseJoinMetaTest implements IInitializer<DatabaseJoinMeta> {
+  LoadSaveTester<DatabaseJoinMeta> loadSaveTester;
   Class<DatabaseJoinMeta> testMetaClass = DatabaseJoinMeta.class;
 
   @ClassRule public static RestoreHopEngineEnvironment env = new RestoreHopEngineEnvironment();
 
-  @Before
-  public void setUpLoadSave() throws Exception {
+  @BeforeClass
+  public static void setUpBeforeClass() throws HopException {
     HopEnvironment.init();
     PluginRegistry.init(false);
+  }
+  
+  @Before
+  public void setUpLoadSave() throws Exception {
     List<String> attributes =
         Arrays.asList(
             "sql",
             "rowLimit",
             "outerJoin",
-            "variableReplace",
-            "databaseMeta",
-            "parameterField",
-            "parameterType");
+            "replaceVariables",
+            "connection",
+            "parameters");
 
     Map<String, String> getterMap = new HashMap<>();
+//    getterMap.put("parameters", "getParameters");
+//    getterMap.put("databaseMeta", "getDatabaseMeta");
+    
     Map<String, String> setterMap = new HashMap<>();
-
+    //setterMap.put("parameters", "setParameters");
+    
     Map<String, IFieldLoadSaveValidator<?>> attrValidatorMap = new HashMap<>();
-
-    attrValidatorMap.put(
-        "parameterField", new ArrayLoadSaveValidator<>(new StringLoadSaveValidator(), 5));
-
-    attrValidatorMap.put(
-        "parameterType",
-        new PrimitiveIntArrayLoadSaveValidator(new NonZeroIntLoadSaveValidator(7), 5));
-
-    attrValidatorMap.put("databaseMeta", new DatabaseMetaLoadSaveValidator());
+    attrValidatorMap.put("parameters", new ListLoadSaveValidator<>(new ParameterFieldLoadSaveValidator(), 5));    
 
     Map<String, IFieldLoadSaveValidator<?>> typeValidatorMap = new HashMap<>();
-
+    
     loadSaveTester =
-        new LoadSaveTester(
+        new LoadSaveTester<>(
             testMetaClass,
             attributes,
             new ArrayList<>(),
@@ -80,16 +81,35 @@ public class DatabaseJoinMetaTest implements IInitializer<ITransformMeta> {
 
   // Call the allocate method on the LoadSaveTester meta class
   @Override
-  public void modify(ITransformMeta someMeta) {
-    if (someMeta instanceof DatabaseJoinMeta) {
-      ((DatabaseJoinMeta) someMeta).allocate(5);
-    }
+  public void modify(DatabaseJoinMeta someMeta) {
+
   }
 
   @Test
   public void testSerialization() throws HopException {
     loadSaveTester.testSerialization();
   }
+  
+  public class ParameterFieldLoadSaveValidator implements IFieldLoadSaveValidator<ParameterField> {
+    final Random rand = new Random();
+
+    @Override
+    public ParameterField getTestObject() {
+      ParameterField field = new ParameterField();
+      field.setName(UUID.randomUUID().toString());
+      field.setType(IValueMeta.TYPE_STRING);
 
-  // Note - cloneTest() removed because the load/save tester has a comprehensive clone test.
+      return field;
+    }
+
+    @Override
+    public boolean validateTestObject(ParameterField testObject, Object actual) {
+      if (!(actual instanceof ParameterField)) {
+        return false;
+      }
+      ParameterField another = (ParameterField) actual;
+      return new EqualsBuilder().append(testObject.getName(), another.getName())
+          .append(testObject.getType(), another.getType()).isEquals();
+    }
+  }
 }