org.xiforge.pentaho.di.trans.step.parsejsonstring.ParseJsonString.java Source code

Java tutorial

Introduction

Here is the source code for org.xiforge.pentaho.di.trans.step.parsejsonstring.ParseJsonString.java

Source

/*
 * Copyright (c) 2011 XiForge Team.  All rights reserved.
 * This software was developed by XiForge Team and is provided under the license of Pentaho Data Integration
 * Community version, the terms of the GNU Lesser General Public License, Version 2.1. You may not use this file
 * except in compliance with the license. If you need a copy of the license, please go to
 * http://www.gnu.org/licenses/lgpl-2.1.txt. The Original Code is XiForge PDI Parse JSON String plugin. The
 * Initial Developer is Reid Lai.
 *
 * Software distributed under the GNU Lesser Public License is distributed on an "AS IS" basis, WITHOUT WARRANTY
 * OF ANY KIND, either express or  implied. Please refer to the license for the specific language governing your
 * rights and limitations.
 */

package org.xiforge.pentaho.di.trans.step.parsejsonstring;

import java.math.BigDecimal;
import java.text.DateFormat;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import net.sf.json.JSON;
import net.sf.json.JSONArray;
import net.sf.json.JSONObject;
import net.sf.json.JSONSerializer;
import org.apache.commons.jxpath.JXPathContext;
import org.pentaho.di.core.exception.KettleException;
import org.pentaho.di.core.exception.KettleValueException;
import org.pentaho.di.core.row.RowDataUtil;
import org.pentaho.di.core.row.RowMetaInterface;
import org.pentaho.di.core.row.ValueMetaInterface;
import org.pentaho.di.i18n.BaseMessages;
import org.pentaho.di.trans.Trans;
import org.pentaho.di.trans.TransMeta;
import org.pentaho.di.trans.step.BaseStep;
import org.pentaho.di.trans.step.StepDataInterface;
import org.pentaho.di.trans.step.StepInterface;
import org.pentaho.di.trans.step.StepMeta;
import org.pentaho.di.trans.step.StepMetaInterface;

public class ParseJsonString extends BaseStep implements StepInterface {
    private static final Class<?> PKG = ParseJsonStringMeta.class;
    private ParseJsonStringMeta meta;
    private ParseJsonStringData data;

    public ParseJsonString(StepMeta stepMeta, StepDataInterface stepDataInterface, int copyNr, TransMeta transMeta,
            Trans trans) {
        super(stepMeta, stepDataInterface, copyNr, transMeta, trans);
    }

    @Override
    public boolean init(StepMetaInterface smi, StepDataInterface sdi) {
        meta = (ParseJsonStringMeta) smi;
        data = (ParseJsonStringData) sdi;

        return super.init(smi, sdi);
    }

    @Override
    public synchronized boolean processRow(StepMetaInterface smi, StepDataInterface sdi) throws KettleException {
        meta = (ParseJsonStringMeta) smi;
        data = (ParseJsonStringData) sdi;

        final Object[] r = this.getRow();

        if (r == null) {
            setOutputDone();
            return false;
        }

        if (this.first) {
            // Copy previous step metadata
            this.first = false;
            data.outputRowMeta = getInputRowMeta().clone();
            data.fieldPos = data.outputRowMeta.indexOfValue(meta.getFieldToParse());

            if (data.fieldPos < 0) {
                throw new KettleValueException(BaseMessages.getString(PKG,
                        "ParseJsonString.Log.CouldNotFindFieldToParse", meta.getFieldToParse()));
            }

            // Check if parsing field is String type
            if (!data.outputRowMeta.getValueMeta(data.fieldPos).isString()) {
                throw new KettleValueException((BaseMessages.getString(PKG,
                        "ParseJsonString.Log.FieldToParseNotValid", meta.getFieldToParse())));
            }

            // Copy Input metadata to output metadata
            data.outputRowMeta = getInputRowMeta().clone();
            // Create extra fields in output metadata
            meta.getFields(data.outputRowMeta, this.getStepname(), null, null, this);
        }

        // Output buffer to output
        putRow(data.outputRowMeta, addRowData(r));

        return true;
    }

    private Object[] addRowData(Object[] r) throws KettleException {
        // Parsing field
        final JSON json = JSONSerializer.toJSON(r[data.fieldPos].toString());
        final JXPathContext context = JXPathContext.newContext(json);
        final String[] fieldNames = meta.getFieldName();
        final RowMetaInterface rowMeta = data.outputRowMeta;

        // Parsing each path into otuput rows
        for (int i = 0; i < fieldNames.length; i++) {
            final String fieldPath = meta.getXPath()[i];
            final String fieldName = meta.getFieldName()[i];
            final Object fieldValue = context.getValue(fieldPath);
            final Integer fieldIndex = rowMeta.indexOfValue(fieldNames[i]);
            final ValueMetaInterface valueMeta = rowMeta.getValueMeta(fieldIndex);
            final DateFormat df = (valueMeta.getType() == ValueMetaInterface.TYPE_DATE)
                    ? new SimpleDateFormat(meta.getFieldFormat()[i])
                    : null;

            // safely add the unique field at the end of the output row
            r = RowDataUtil.addValueData(r, fieldIndex,
                    getRowDataValue(fieldName, valueMeta, valueMeta, fieldValue, df));
        }

        return r;
    }

    private Object getRowDataValue(final String fieldName, final ValueMetaInterface targetValueMeta,
            final ValueMetaInterface sourceValueMeta, final Object value, final DateFormat df)
            throws KettleException {
        if (value == null) {
            return value;
        }

        if (ValueMetaInterface.TYPE_STRING == targetValueMeta.getType()) {
            return targetValueMeta.convertData(sourceValueMeta, value.toString());
        }

        if (ValueMetaInterface.TYPE_NUMBER == targetValueMeta.getType()) {
            return targetValueMeta.convertData(sourceValueMeta, Double.valueOf(value.toString()));
        }

        if (ValueMetaInterface.TYPE_INTEGER == targetValueMeta.getType()) {
            return targetValueMeta.convertData(sourceValueMeta, Long.valueOf(value.toString()));
        }

        if (ValueMetaInterface.TYPE_BIGNUMBER == targetValueMeta.getType()) {
            return targetValueMeta.convertData(sourceValueMeta, new BigDecimal(value.toString()));
        }

        if (ValueMetaInterface.TYPE_BOOLEAN == targetValueMeta.getType()) {
            return targetValueMeta.convertData(sourceValueMeta, Boolean.valueOf(value.toString()));
        }

        if (ValueMetaInterface.TYPE_BINARY == targetValueMeta.getType()) {
            return targetValueMeta.convertData(sourceValueMeta, value);
        }

        if (ValueMetaInterface.TYPE_DATE == targetValueMeta.getType()) {
            try {
                return targetValueMeta.convertData(sourceValueMeta, df.parse(value.toString()));
            } catch (final ParseException e) {
                throw new KettleValueException("Unable to convert data type of value");
            }
        }

        if (value instanceof JSONObject || value instanceof JSONArray) {
            return targetValueMeta.convertData(targetValueMeta, "{" + fieldName + ":" + value.toString() + "}");
        }

        throw new KettleValueException("Unable to convert data type of value");
    }
}