Skip to content

Latest commit

 

History

History
210 lines (194 loc) · 7.18 KB

Sample-UserDefinedJavaClass-Main.md

File metadata and controls

210 lines (194 loc) · 7.18 KB

User Defined Java Class

https://help.hitachivantara.com/Documentation/Pentaho/9.2/Products/User_Defined_Java_Class

The code snippet for Main (under common use) is broken. Below is the fixed code

import java.math.*;
import java.util.*;
import java.util.Map.Entry;

/* All this Manipulator/FieldsUpdater stuff is just some magic to let me show
 * you an example when I have no idea what input or output fields you are going
 * to connect to the step. It looks for all the output fields and fiddles with
 * them in some field type appropriate way. Hopefully your code will look a lot
 * simpler and be more useful. ;) -Daniel
 */
private interface Manipulator {
  public Object manipulate(Object in);
  public Object create();
}
public static final class FieldsUpdater {
  public static final FieldsUpdater NUMBER =
      new FieldsUpdater(new Manipulator() {
        double numRecords = 0;
        long startTime = System.currentTimeMillis();
        public Object manipulate(Object in) {
          if (in == null)
            return create();
          return (Double) in + Math.random();
        }
        public Object create() {
          return numRecords++ / (System.currentTimeMillis() - startTime);
        }
      });
  public static final FieldsUpdater STRING =
      new FieldsUpdater(new Manipulator() {
        public Object manipulate(Object in) {
          if (in == null)
            return create();
          return "Input was " + ((String) in).length() + " characters.";
        }
        public Object create() {
          return "Hello World!";
        }
      });
  public static final FieldsUpdater DATE = new FieldsUpdater(new Manipulator() {
    Calendar cal = Calendar.getInstance();
    Date myBirthday = new Date(156517500000L);
    public Object manipulate(Object in) {
      if (in == null)
        return create();
      cal.setTime((Date) in);
      cal.set(Calendar.DAY_OF_WEEK, Calendar.SUNDAY);
      return cal.getTime();
    }
    public Object create() {
      return myBirthday;
    }
  });
  public static final FieldsUpdater BOOLEAN =
      new FieldsUpdater(new Manipulator() {
        Boolean curBool = Boolean.FALSE;
        public Object manipulate(Object in) {
          if (in == null)
            return create();
          return (Boolean) in ? Boolean.TRUE : Boolean.FALSE;
        }
        public Object create() {
          curBool = curBool ? Boolean.FALSE : Boolean.TRUE;
          return curBool;
        }
      });
  public static final FieldsUpdater INTEGER =
      new FieldsUpdater(new Manipulator() {
        int numRows = 0;
        public Object manipulate(Object in) {
          if (in == null)
            return create();
          return ((Long) in) * -1;
        }
        public Object create() {
          return numRows++;
        }
      });
  public static final FieldsUpdater BIGNUMBER =
      new FieldsUpdater(new Manipulator() {
        final BigDecimal three = new BigDecimal(3);
        BigDecimal frac =
            new BigDecimal(Integer.MAX_VALUE, MathContext.DECIMAL128);
        public Object manipulate(Object in) {
          if (in == null)
            return create();
          return ((BigDecimal) in).movePointLeft(1);
        }
        public Object create() {
          frac = frac.divide(three);
          return frac;
        }
      });

  private final Manipulator m;
  FieldsUpdater(Manipulator m) {
    this.m = m;
  }
  public Object manipulate(Object in) {
    return m.manipulate(in);
  }
  public static FieldsUpdater valueOf(String name) throws KettleStepException {
    if ("Number".equals(name))
      return NUMBER;
    else if ("String".equals(name))
      return STRING;
    else if ("Date".equals(name))
      return DATE;
    else if ("Boolean".equals(name))
      return BOOLEAN;
    else if ("Integer".equals(name))
      return INTEGER;
    else if ("BigNumber".equals(name))
      return BIGNUMBER;
    else
      throw new KettleStepException("Unknown field data type " + name);
  }
}
private final HashMap fieldsToUpdate = new HashMap();
private int rowsLeftForGenerateMode = -1;
private int outputRowSize = 0;

public boolean processRow(StepMetaInterface smi, StepDataInterface sdi)
    throws KettleException {
  // First, get a row from the default input hop
  Object[] r = getRow();

  // If the row object is null, we are done processing.
  if (r == null && !first) {
    setOutputDone();
    return false;
  }
  // If the global "first" flag is true, perform some initialization that can
  // only happen once we have read the first row of input data
  if (first) {
    first = false;

    // Set up the list of fields that will be available after this step
    // Normally, this is simpler, but in the HelloWorld sample, I don't know if
    // there is an input step connected or not.
    if (r == null) {
      rowsLeftForGenerateMode = 100;
    }
    outputRowSize = data.outputRowMeta.size();

    // Again, an extra complicated block of code to make up for the fact that I
    // don't know how you are connecting this sample to an existing
    // transformation.
    for (int i = 0; i < outputRowSize; i++) {
      ValueMetaInterface valueMeta = data.outputRowMeta.getValueMeta(i);

      FieldsUpdater mapKey = FieldsUpdater.valueOf(valueMeta.getTypeDesc());

      List fieldsForType = (List) fieldsToUpdate.get(mapKey);
      if (fieldsForType == null) {
        fieldsForType = new ArrayList();
        fieldsToUpdate.put(mapKey, fieldsForType);
      }
      fieldsForType.add(valueMeta.getName());
    }
  }

  // It is always safest to call createOutputRow() to ensure that your output
  // row's Object[] is large enough to handle any new fields you are creating in
  // this step.
  r = createOutputRow(r, outputRowSize);

  /* Now for the last piece of HellowWorld magic.  We will loop through all the
   * fields that we will be outputing, and call the appropriate manipulate() for
   * that type of field. In the real world, this is *much* simpler:
   *
   * FieldHelper fh = get(Field.Out, "myinputfield");
   * String oldFieldValue = fh.getString(r);
   * fh.setValue(r, "Adding to value: "+oldFieldValue);
   *
   * get(Field.Out, "mynewfield").setValue(r,"Hello World!");
   */
  Set entrySet = fieldsToUpdate.entrySet();
  for (Iterator entryIter = entrySet.iterator(); entryIter.hasNext();) {
    Entry entry = (Entry) entryIter.next();
    FieldsUpdater fieldsUpdater = (FieldsUpdater) entry.getKey();
    for (Iterator listIter = ((List) entry.getValue()).iterator();
         listIter.hasNext();) {
      String fieldName = (String) listIter.next();
      FieldHelper fieldHelper = get(Fields.Out, fieldName);
      fieldHelper.setValue(
          r, fieldsUpdater.manipulate(fieldHelper.getObject(r)));
    }
  }

  // putRow will send the row on to the default output hop.
  putRow(data.outputRowMeta, r);

  // This method will be continuously called until it returns false (i.e. when
  // all rows are processed). Normally, you'd just return true if you are
  // handling input rows or you'd return false when you are done generating new
  // rows.  In this case, we have the below fancy test to figure out when to
  // stop in either case.
  return (rowsLeftForGenerateMode == -1 || rowsLeftForGenerateMode-- > 0);
}

How some of the code works: https://www.online-java.com/TbE8uz0lWv