org.pentaho.di.trans.steps.rowgenerator.RowGeneratorMeta.java Source code

Java tutorial

Introduction

Here is the source code for org.pentaho.di.trans.steps.rowgenerator.RowGeneratorMeta.java

Source

/*******************************************************************************
 *
 * Pentaho Data Integration
 *
 * Copyright (C) 2002-2012 by Pentaho : http://www.pentaho.com
 *
 *******************************************************************************
 *
 * Licensed 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.pentaho.di.trans.steps.rowgenerator;

import java.text.DecimalFormat;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;

import org.apache.commons.lang.ArrayUtils;
import org.json.simple.JSONArray;
import org.json.simple.JSONObject;
import org.pentaho.di.core.CheckResult;
import org.pentaho.di.core.CheckResultInterface;
import org.pentaho.di.core.Const;
import org.pentaho.di.core.Counter;
import org.pentaho.di.core.RowMetaAndData;
import org.pentaho.di.core.database.DatabaseMeta;
import org.pentaho.di.core.exception.KettleException;
import org.pentaho.di.core.exception.KettlePageException;
import org.pentaho.di.core.exception.KettleStepException;
import org.pentaho.di.core.exception.KettleXMLException;
import org.pentaho.di.core.row.RowMetaInterface;
import org.pentaho.di.core.row.ValueMetaInterface;
import org.pentaho.di.core.variables.VariableSpace;
import org.pentaho.di.core.xml.XMLHandler;
import org.pentaho.di.i18n.BaseMessages;
import org.pentaho.di.repository.ObjectId;
import org.pentaho.di.repository.Repository;
import org.pentaho.di.trans.Trans;
import org.pentaho.di.trans.TransMeta;
import org.pentaho.di.trans.step.BaseStepMeta;
import org.pentaho.di.trans.step.StepDataInterface;
import org.pentaho.di.trans.step.StepIOMeta;
import org.pentaho.di.trans.step.StepIOMetaInterface;
import org.pentaho.di.trans.step.StepInterface;
import org.pentaho.di.trans.step.StepMeta;
import org.pentaho.di.trans.step.StepMetaInterface;
import org.w3c.dom.Node;

/*
 * Created on 4-apr-2003
 */
public class RowGeneratorMeta extends BaseStepMeta implements StepMetaInterface {
    private static Class<?> PKG = RowGeneratorMeta.class; // for i18n purposes,
    // needed by
    // Translator2!!
    // $NON-NLS-1$

    private static String[] FIELDS_DG_KEYS = new String[] { "fieldName", "fieldType", "fieldFormat", "fieldLength",
            "fieldPrecision", "currency", "decimal", "group", "value", "setEmptyString" };

    private String rowLimit;

    private String currency[];
    private String decimal[];
    private String group[];
    private String value[];

    private String fieldName[];
    private String fieldType[];
    private String fieldFormat[];

    private int fieldLength[];
    private int fieldPrecision[];
    /** Flag : set empty string **/
    private boolean setEmptyString[];

    public RowGeneratorMeta() {
        super(); // allocate BaseStepMeta
    }

    public String[] getFieldsDGKeys() {
        return FIELDS_DG_KEYS;
    }

    public Object[][] getFieldsDGValues() {
        Object[][] vals = new Object[10][];
        vals[0] = fieldName;
        vals[1] = fieldType;
        vals[2] = fieldFormat;
        vals[3] = ArrayUtils.toObject(fieldLength);
        vals[4] = ArrayUtils.toObject(fieldPrecision);
        vals[5] = currency;
        vals[6] = decimal;
        vals[7] = group;
        vals[8] = value;
        vals[9] = ArrayUtils.toObject(setEmptyString);
        return vals;
    }

    /**
     * @return Returns the currency.
     */
    public String[] getCurrency() {
        return currency;
    }

    /**
     * @param currency
     *            The currency to set.
     */
    public void setCurrency(String[] currency) {
        this.currency = currency;
    }

    /**
     * @return Returns the decimal.
     */
    public String[] getDecimal() {
        return decimal;
    }

    /**
     * @param decimal
     *            The decimal to set.
     */
    public void setDecimal(String[] decimal) {
        this.decimal = decimal;
    }

    /**
     * @return Returns the fieldFormat.
     */
    public String[] getFieldFormat() {
        return fieldFormat;
    }

    /**
     * @param fieldFormat
     *            The fieldFormat to set.
     */
    public void setFieldFormat(String[] fieldFormat) {
        this.fieldFormat = fieldFormat;
    }

    /**
     * @return Returns the fieldLength.
     */
    public int[] getFieldLength() {
        return fieldLength;
    }

    /**
     * @param fieldLength
     *            The fieldLength to set.
     */
    public void setFieldLength(int[] fieldLength) {
        this.fieldLength = fieldLength;
    }

    /**
     * @return Returns the fieldName.
     */
    public String[] getFieldName() {
        return fieldName;
    }

    /**
     * @param fieldName
     *            The fieldName to set.
     */
    public void setFieldName(String[] fieldName) {
        this.fieldName = fieldName;
    }

    /**
     * @return Returns the fieldPrecision.
     */
    public int[] getFieldPrecision() {
        return fieldPrecision;
    }

    /**
     * @param fieldPrecision
     *            The fieldPrecision to set.
     */
    public void setFieldPrecision(int[] fieldPrecision) {
        this.fieldPrecision = fieldPrecision;
    }

    /**
     * @return Returns the fieldType.
     */
    public String[] getFieldType() {
        return fieldType;
    }

    /**
     * @param fieldType
     *            The fieldType to set.
     */
    public void setFieldType(String[] fieldType) {
        this.fieldType = fieldType;
    }

    /**
     * @return Returns the group.
     */
    public String[] getGroup() {
        return group;
    }

    /**
     * @param group
     *            The group to set.
     */
    public void setGroup(String[] group) {
        this.group = group;
    }

    /**
     * @return the setEmptyString
     */
    public boolean[] isSetEmptyString() {
        return setEmptyString;
    }

    /**
     * @param setEmptyString
     *            the setEmptyString to set
     */
    public void setEmptyString(boolean[] setEmptyString) {
        this.setEmptyString = setEmptyString;
    }

    /**
     * @return Returns the rowLimit.
     */
    public String getRowLimit() {
        return rowLimit;
    }

    /**
     * @param rowLimit
     *            The rowLimit to set.
     */
    public void setRowLimit(String rowLimit) {
        this.rowLimit = rowLimit;
    }

    /**
     * @return Returns the value.
     */
    public String[] getValue() {
        return value;
    }

    /**
     * @param value
     *            The value to set.
     */
    public void setValue(String[] value) {
        this.value = value;
    }

    public void loadXML(Node stepnode, List<DatabaseMeta> databases, Map<String, Counter> counters)
            throws KettleXMLException {
        readData(stepnode);
    }

    public void allocate(int nrfields) {
        fieldName = new String[nrfields];
        fieldType = new String[nrfields];
        fieldFormat = new String[nrfields];
        fieldLength = new int[nrfields];
        fieldPrecision = new int[nrfields];
        currency = new String[nrfields];
        decimal = new String[nrfields];
        group = new String[nrfields];
        value = new String[nrfields];
        setEmptyString = new boolean[nrfields];
    }

    public Object clone() {
        RowGeneratorMeta retval = (RowGeneratorMeta) super.clone();

        int nrfields = fieldName.length;

        retval.allocate(nrfields);

        for (int i = 0; i < nrfields; i++) {
            retval.fieldName[i] = fieldName[i];
            retval.fieldType[i] = fieldType[i];
            retval.fieldFormat[i] = fieldFormat[i];
            retval.currency[i] = currency[i];
            retval.decimal[i] = decimal[i];
            retval.group[i] = group[i];
            retval.value[i] = value[i];
            retval.fieldLength[i] = fieldLength[i];
            retval.fieldPrecision[i] = fieldPrecision[i];
            retval.setEmptyString[i] = setEmptyString[i];
        }

        return retval;
    }

    @Override
    public void loadPage(Map<String, List<String>> parameterHolder) throws KettlePageException {
        try {
            JSONArray fields = XMLHandler.getPageRows(parameterHolder, fid("fields"));
            int nrfields = fields.size();

            allocate(nrfields);

            for (int i = 0; i < nrfields; i++) {
                JSONObject field = (JSONObject) fields.get(i);

                fieldName[i] = (String) field.get("fieldName");
                fieldType[i] = (String) field.get("fieldType");
                fieldFormat[i] = (String) field.get("fieldFormat");
                currency[i] = (String) field.get("currency");
                decimal[i] = (String) field.get("decimal");
                group[i] = (String) field.get("group");
                value[i] = (String) field.get("value");

                fieldLength[i] = Const.toInt(String.valueOf(field.get("fieldLength")), -1);
                fieldPrecision[i] = Const.toInt(String.valueOf(field.get("fieldPrecision")), -1);
                setEmptyString[i] = Const.toBoolean(String.valueOf(field.get("setEmptyString")), false);
            }

            rowLimit = XMLHandler.getPageValue(parameterHolder, fid("limit"));
        } catch (Exception e) {
            throw new KettlePageException("Unexpected error reading step information from the repository", e);
        }
    }

    private void readData(Node stepnode) throws KettleXMLException {
        try {
            Node fields = XMLHandler.getSubNode(stepnode, "fields");
            int nrfields = XMLHandler.countNodes(fields, "field");

            allocate(nrfields);

            String slength, sprecision;

            for (int i = 0; i < nrfields; i++) {
                Node fnode = XMLHandler.getSubNodeByNr(fields, "field", i);

                fieldName[i] = XMLHandler.getTagValue(fnode, "name");
                fieldType[i] = XMLHandler.getTagValue(fnode, "type");
                fieldFormat[i] = XMLHandler.getTagValue(fnode, "format");
                currency[i] = XMLHandler.getTagValue(fnode, "currency");
                decimal[i] = XMLHandler.getTagValue(fnode, "decimal");
                group[i] = XMLHandler.getTagValue(fnode, "group");
                value[i] = XMLHandler.getTagValue(fnode, "nullif");
                slength = XMLHandler.getTagValue(fnode, "length");
                sprecision = XMLHandler.getTagValue(fnode, "precision");

                fieldLength[i] = Const.toInt(slength, -1);
                fieldPrecision[i] = Const.toInt(sprecision, -1);
                String emptyString = XMLHandler.getTagValue(fnode, "set_empty_string");
                setEmptyString[i] = !Const.isEmpty(emptyString) && "Y".equalsIgnoreCase(emptyString);
            }

            // Is there a limit on the number of rows we process?
            rowLimit = XMLHandler.getTagValue(stepnode, "limit");
        } catch (Exception e) {
            throw new KettleXMLException("Unable to load step info from XML", e);
        }
    }

    public void setDefault() {
        int i, nrfields = 0;

        allocate(nrfields);

        DecimalFormat decimalFormat = new DecimalFormat();

        for (i = 0; i < nrfields; i++) {
            fieldName[i] = "field" + i;
            fieldType[i] = "Number";
            fieldFormat[i] = "\u00A40,000,000.00;\u00A4-0,000,000.00";
            fieldLength[i] = 9;
            fieldPrecision[i] = 2;
            currency[i] = decimalFormat.getDecimalFormatSymbols().getCurrencySymbol();
            decimal[i] = new String(new char[] { decimalFormat.getDecimalFormatSymbols().getDecimalSeparator() });
            group[i] = new String(new char[] { decimalFormat.getDecimalFormatSymbols().getGroupingSeparator() });
            value[i] = "-";
            setEmptyString[i] = false;
        }

        rowLimit = "10";
    }

    public void getFields(RowMetaInterface row, String origin, RowMetaInterface[] info, StepMeta nextStep,
            VariableSpace space) throws KettleStepException {
        List<CheckResultInterface> remarks = new ArrayList<CheckResultInterface>();
        RowMetaAndData rowMetaAndData = RowGenerator.buildRow(this, remarks, origin);
        if (!remarks.isEmpty()) {
            StringBuffer stringRemarks = new StringBuffer();
            for (CheckResultInterface remark : remarks) {
                stringRemarks.append(remark.toString()).append(Const.CR);
            }
            throw new KettleStepException(stringRemarks.toString());
        }

        for (ValueMetaInterface valueMeta : rowMetaAndData.getRowMeta().getValueMetaList()) {
            valueMeta.setOrigin(origin);
        }

        row.mergeRowMeta(rowMetaAndData.getRowMeta());
    }

    public String getXML() {
        StringBuffer retval = new StringBuffer(300);

        retval.append("    <fields>").append(Const.CR);
        for (int i = 0; i < fieldName.length; i++) {
            if (fieldName[i] != null && fieldName[i].length() != 0) {
                retval.append("      <field>").append(Const.CR);
                retval.append("        ").append(XMLHandler.addTagValue("name", fieldName[i]));
                retval.append("        ").append(XMLHandler.addTagValue("type", fieldType[i]));
                retval.append("        ").append(XMLHandler.addTagValue("format", fieldFormat[i]));
                retval.append("        ").append(XMLHandler.addTagValue("currency", currency[i]));
                retval.append("        ").append(XMLHandler.addTagValue("decimal", decimal[i]));
                retval.append("        ").append(XMLHandler.addTagValue("group", group[i]));
                retval.append("        ").append(XMLHandler.addTagValue("nullif", value[i]));
                retval.append("        ").append(XMLHandler.addTagValue("length", fieldLength[i]));
                retval.append("        ").append(XMLHandler.addTagValue("precision", fieldPrecision[i]));
                retval.append("        ").append(XMLHandler.addTagValue("set_empty_string", setEmptyString[i]));
                retval.append("      </field>").append(Const.CR);
            }
        }
        retval.append("    </fields>").append(Const.CR);
        retval.append("    ").append(XMLHandler.addTagValue("limit", rowLimit));

        return retval.toString();
    }

    public void readRep(Repository rep, ObjectId id_step, List<DatabaseMeta> databases,
            Map<String, Counter> counters) throws KettleException {
        try {
            int nrfields = rep.countNrStepAttributes(id_step, "field_name");

            allocate(nrfields);

            for (int i = 0; i < nrfields; i++) {
                fieldName[i] = rep.getStepAttributeString(id_step, i, "field_name");
                fieldType[i] = rep.getStepAttributeString(id_step, i, "field_type");

                fieldFormat[i] = rep.getStepAttributeString(id_step, i, "field_format");
                currency[i] = rep.getStepAttributeString(id_step, i, "field_currency");
                decimal[i] = rep.getStepAttributeString(id_step, i, "field_decimal");
                group[i] = rep.getStepAttributeString(id_step, i, "field_group");
                value[i] = rep.getStepAttributeString(id_step, i, "field_nullif");
                fieldLength[i] = (int) rep.getStepAttributeInteger(id_step, i, "field_length");
                fieldPrecision[i] = (int) rep.getStepAttributeInteger(id_step, i, "field_precision");
                setEmptyString[i] = rep.getStepAttributeBoolean(id_step, i, "set_empty_string", false);
            }

            long longLimit = rep.getStepAttributeInteger(id_step, "limit");
            if (longLimit <= 0) {
                rowLimit = rep.getStepAttributeString(id_step, "limit");
            } else {
                rowLimit = Long.toString(longLimit);
            }

        } catch (Exception e) {
            throw new KettleException("Unexpected error reading step information from the repository", e);
        }
    }

    public void saveRep(Repository rep, ObjectId id_transformation, ObjectId id_step) throws KettleException {
        try {
            for (int i = 0; i < fieldName.length; i++) {
                if (fieldName[i] != null && fieldName[i].length() != 0) {
                    rep.saveStepAttribute(id_transformation, id_step, i, "field_name", fieldName[i]);
                    rep.saveStepAttribute(id_transformation, id_step, i, "field_type", fieldType[i]);
                    rep.saveStepAttribute(id_transformation, id_step, i, "field_format", fieldFormat[i]);
                    rep.saveStepAttribute(id_transformation, id_step, i, "field_currency", currency[i]);
                    rep.saveStepAttribute(id_transformation, id_step, i, "field_decimal", decimal[i]);
                    rep.saveStepAttribute(id_transformation, id_step, i, "field_group", group[i]);
                    rep.saveStepAttribute(id_transformation, id_step, i, "field_nullif", value[i]);
                    rep.saveStepAttribute(id_transformation, id_step, i, "field_length", fieldLength[i]);
                    rep.saveStepAttribute(id_transformation, id_step, i, "field_precision", fieldPrecision[i]);
                    rep.saveStepAttribute(id_transformation, id_step, i, "set_empty_string", setEmptyString[i]);
                }
            }

            rep.saveStepAttribute(id_transformation, id_step, "limit", rowLimit);
        } catch (Exception e) {
            throw new KettleException("Unable to save step information to the repository for id_step=" + id_step,
                    e);
        }
    }

    public void check(List<CheckResultInterface> remarks, TransMeta transMeta, StepMeta stepMeta,
            RowMetaInterface prev, String input[], String output[], RowMetaInterface info) {
        CheckResult cr;
        if (prev != null && prev.size() > 0) {
            cr = new CheckResult(CheckResultInterface.TYPE_RESULT_ERROR,
                    BaseMessages.getString(PKG, "RowGeneratorMeta.CheckResult.NoInputStreamsError"), stepMeta);
            remarks.add(cr);
        } else {
            cr = new CheckResult(CheckResultInterface.TYPE_RESULT_OK,
                    BaseMessages.getString(PKG, "RowGeneratorMeta.CheckResult.NoInputStreamOk"), stepMeta);
            remarks.add(cr);

            String strLimit = transMeta.environmentSubstitute(rowLimit);
            if (Const.toLong(strLimit, -1L) <= 0) {
                cr = new CheckResult(CheckResultInterface.TYPE_RESULT_WARNING,
                        BaseMessages.getString(PKG, "RowGeneratorMeta.CheckResult.WarnNoRows"), stepMeta);
                remarks.add(cr);
            } else {
                cr = new CheckResult(CheckResultInterface.TYPE_RESULT_OK,
                        BaseMessages.getString(PKG, "RowGeneratorMeta.CheckResult.WillReturnRows", strLimit),
                        stepMeta);
                remarks.add(cr);
            }
        }

        // See if we have input streams leading to this step!
        if (input.length > 0) {
            cr = new CheckResult(CheckResultInterface.TYPE_RESULT_ERROR,
                    BaseMessages.getString(PKG, "RowGeneratorMeta.CheckResult.NoInputError"), stepMeta);
            remarks.add(cr);
        } else {
            cr = new CheckResult(CheckResultInterface.TYPE_RESULT_OK,
                    BaseMessages.getString(PKG, "RowGeneratorMeta.CheckResult.NoInputOk"), stepMeta);
            remarks.add(cr);
        }
    }

    public StepInterface getStep(StepMeta stepMeta, StepDataInterface stepDataInterface, int cnr,
            TransMeta transMeta, Trans trans) {
        return new RowGenerator(stepMeta, stepDataInterface, cnr, transMeta, trans);
    }

    public StepDataInterface getStepData() {
        return new RowGeneratorData();
    }

    /**
     * Returns the Input/Output metadata for this step. The generator step only
     * produces output, does not accept input!
     */
    public StepIOMetaInterface getStepIOMeta() {
        return new StepIOMeta(false, true, false, false, false, false);
    }
}