Search in sources :

Example 1 with ValueUsedListener

use of org.pentaho.di.compatibility.ValueUsedListener in project pentaho-kettle by pentaho.

the class ScriptValuesMod method addValues.

private boolean addValues(RowMetaInterface rowMeta, Object[] row) throws KettleException {
    if (first) {
        first = false;
        // What is the output row looking like?
        // 
        data.outputRowMeta = getInputRowMeta().clone();
        meta.getFields(data.outputRowMeta, getStepname(), null, null, this, repository, metaStore);
        // Determine the indexes of the fields used!
        // 
        determineUsedFields(rowMeta);
        // Get the indexes of the replaced fields...
        // 
        data.replaceIndex = new int[meta.getFieldname().length];
        for (int i = 0; i < meta.getFieldname().length; i++) {
            if (meta.getReplace()[i]) {
                data.replaceIndex[i] = rowMeta.indexOfValue(meta.getFieldname()[i]);
                if (data.replaceIndex[i] < 0) {
                    if (Utils.isEmpty(meta.getFieldname()[i])) {
                        throw new KettleStepException(BaseMessages.getString(PKG, "ScriptValuesMetaMod.Exception.FieldToReplaceNotFound", meta.getFieldname()[i]));
                    }
                    data.replaceIndex[i] = rowMeta.indexOfValue(meta.getRename()[i]);
                    if (data.replaceIndex[i] < 0) {
                        throw new KettleStepException(BaseMessages.getString(PKG, "ScriptValuesMetaMod.Exception.FieldToReplaceNotFound", meta.getRename()[i]));
                    }
                }
            } else {
                data.replaceIndex[i] = -1;
            }
        }
        // set the optimization level
        data.cx = ContextFactory.getGlobal().enterContext();
        try {
            String optimizationLevelAsString = environmentSubstitute(meta.getOptimizationLevel());
            if (!Utils.isEmpty(Const.trim(optimizationLevelAsString))) {
                data.cx.setOptimizationLevel(Integer.parseInt(optimizationLevelAsString.trim()));
                logBasic(BaseMessages.getString(PKG, "ScriptValuesMod.Optimization.Level", environmentSubstitute(meta.getOptimizationLevel())));
            } else {
                data.cx.setOptimizationLevel(Integer.parseInt(ScriptValuesMetaMod.OPTIMIZATION_LEVEL_DEFAULT));
                logBasic(BaseMessages.getString(PKG, "ScriptValuesMod.Optimization.UsingDefault", ScriptValuesMetaMod.OPTIMIZATION_LEVEL_DEFAULT));
            }
        } catch (NumberFormatException nfe) {
            throw new KettleStepException(BaseMessages.getString(PKG, "ScriptValuesMetaMod.Exception.NumberFormatException", environmentSubstitute(meta.getOptimizationLevel())));
        } catch (IllegalArgumentException iae) {
            throw new KettleException(iae.getMessage());
        }
        data.scope = data.cx.initStandardObjects(null, false);
        bFirstRun = true;
        Scriptable jsvalue = Context.toObject(this, data.scope);
        data.scope.put("_step_", data.scope, jsvalue);
        // Adding the existing Scripts to the Context
        for (int i = 0; i < meta.getNumberOfJSScripts(); i++) {
            Scriptable jsR = Context.toObject(jsScripts[i].getScript(), data.scope);
            data.scope.put(jsScripts[i].getScriptName(), data.scope, jsR);
        }
        // Adding the Name of the Transformation to the Context
        data.scope.put("_TransformationName_", data.scope, getTransMeta().getName());
        try {
            // 
            if (meta.isCompatible()) {
                Row v2Row = RowMeta.createOriginalRow(rowMeta, row);
                Scriptable jsV2Row = Context.toObject(v2Row, data.scope);
                data.scope.put("row", data.scope, jsV2Row);
            } else {
                Scriptable jsrow = Context.toObject(row, data.scope);
                data.scope.put("row", data.scope, jsrow);
            }
            // 
            for (int i = 0; i < data.fields_used.length; i++) {
                ValueMetaInterface valueMeta = rowMeta.getValueMeta(data.fields_used[i]);
                Object valueData = row[data.fields_used[i]];
                if (meta.isCompatible()) {
                    data.values_used[i] = valueMeta.createOriginalValue(valueData);
                    Scriptable jsarg = Context.toObject(data.values_used[i], data.scope);
                    data.scope.put(valueMeta.getName(), data.scope, jsarg);
                } else {
                    Object normalStorageValueData = valueMeta.convertToNormalStorageType(valueData);
                    Scriptable jsarg;
                    if (normalStorageValueData != null) {
                        jsarg = Context.toObject(normalStorageValueData, data.scope);
                    } else {
                        jsarg = null;
                    }
                    data.scope.put(valueMeta.getName(), data.scope, jsarg);
                }
            }
            // also add the meta information for the whole row
            // 
            Scriptable jsrowMeta = Context.toObject(rowMeta, data.scope);
            data.scope.put("rowMeta", data.scope, jsrowMeta);
            // 
            try {
                if (meta.getAddClasses() != null) {
                    for (int i = 0; i < meta.getAddClasses().length; i++) {
                        Object jsOut = Context.javaToJS(meta.getAddClasses()[i].getAddObject(), data.scope);
                        ScriptableObject.putProperty(data.scope, meta.getAddClasses()[i].getJSName(), jsOut);
                    }
                }
            } catch (Exception e) {
                throw new KettleValueException(BaseMessages.getString(PKG, "ScriptValuesMod.Log.CouldNotAttachAdditionalScripts"), e);
            }
            // Adding some default JavaScriptFunctions to the System
            try {
                Context.javaToJS(ScriptValuesAddedFunctions.class, data.scope);
                ((ScriptableObject) data.scope).defineFunctionProperties(ScriptValuesAddedFunctions.jsFunctionList, ScriptValuesAddedFunctions.class, ScriptableObject.DONTENUM);
            } catch (Exception ex) {
                // System.out.println(ex.toString());
                throw new KettleValueException(BaseMessages.getString(PKG, "ScriptValuesMod.Log.CouldNotAddDefaultFunctions"), ex);
            }
            // Adding some Constants to the JavaScript
            try {
                data.scope.put("SKIP_TRANSFORMATION", data.scope, Integer.valueOf(SKIP_TRANSFORMATION));
                data.scope.put("ABORT_TRANSFORMATION", data.scope, Integer.valueOf(ABORT_TRANSFORMATION));
                data.scope.put("ERROR_TRANSFORMATION", data.scope, Integer.valueOf(ERROR_TRANSFORMATION));
                data.scope.put("CONTINUE_TRANSFORMATION", data.scope, Integer.valueOf(CONTINUE_TRANSFORMATION));
            } catch (Exception ex) {
                // System.out.println("Exception Adding the Constants " + ex.toString());
                throw new KettleValueException(BaseMessages.getString(PKG, "ScriptValuesMod.Log.CouldNotAddDefaultConstants"), ex);
            }
            try {
                // Checking for StartScript
                if (strStartScript != null && strStartScript.length() > 0) {
                    Script startScript = data.cx.compileString(strStartScript, "trans_Start", 1, null);
                    startScript.exec(data.cx, data.scope);
                    if (log.isDetailed()) {
                        logDetailed(("Start Script found!"));
                    }
                } else {
                    if (log.isDetailed()) {
                        logDetailed(("No starting Script found!"));
                    }
                }
            } catch (Exception es) {
                // System.out.println("Exception processing StartScript " + es.toString());
                throw new KettleValueException(BaseMessages.getString(PKG, "ScriptValuesMod.Log.ErrorProcessingStartScript"), es);
            }
            // Now Compile our Script
            data.script = data.cx.compileString(strTransformScript, "script", 1, null);
        } catch (Exception e) {
            throw new KettleValueException(BaseMessages.getString(PKG, "ScriptValuesMod.Log.CouldNotCompileJavascript"), e);
        }
    }
    // Filling the defined TranVars with the Values from the Row
    // 
    Object[] outputRow = RowDataUtil.resizeArray(row, data.outputRowMeta.size());
    // Keep an index...
    int outputIndex = rowMeta.size();
    // Keep track of the changed values...
    // 
    final Map<Integer, Value> usedRowValues;
    if (meta.isCompatible()) {
        usedRowValues = new Hashtable<Integer, Value>();
    } else {
        usedRowValues = null;
    }
    try {
        try {
            if (meta.isCompatible()) {
                Row v2Row = RowMeta.createOriginalRow(rowMeta, row);
                Scriptable jsV2Row = Context.toObject(v2Row, data.scope);
                data.scope.put("row", data.scope, jsV2Row);
                v2Row.getUsedValueListeners().add(new ValueUsedListener() {

                    public void valueIsUsed(int index, Value value) {
                        usedRowValues.put(index, value);
                    }
                });
            } else {
                Scriptable jsrow = Context.toObject(row, data.scope);
                data.scope.put("row", data.scope, jsrow);
            }
            for (int i = 0; i < data.fields_used.length; i++) {
                ValueMetaInterface valueMeta = rowMeta.getValueMeta(data.fields_used[i]);
                Object valueData = row[data.fields_used[i]];
                if (meta.isCompatible()) {
                    data.values_used[i] = valueMeta.createOriginalValue(valueData);
                    Scriptable jsarg = Context.toObject(data.values_used[i], data.scope);
                    data.scope.put(valueMeta.getName(), data.scope, jsarg);
                } else {
                    Object normalStorageValueData = valueMeta.convertToNormalStorageType(valueData);
                    Scriptable jsarg;
                    if (normalStorageValueData != null) {
                        jsarg = Context.toObject(normalStorageValueData, data.scope);
                    } else {
                        jsarg = null;
                    }
                    data.scope.put(valueMeta.getName(), data.scope, jsarg);
                }
            }
            // also add the meta information for the hole row
            Scriptable jsrowMeta = Context.toObject(rowMeta, data.scope);
            data.scope.put("rowMeta", data.scope, jsrowMeta);
        } catch (Exception e) {
            throw new KettleValueException(BaseMessages.getString(PKG, "ScriptValuesMod.Log.UnexpectedeError"), e);
        }
        // Executing our Script
        data.script.exec(data.cx, data.scope);
        if (bFirstRun) {
            bFirstRun = false;
            // Check if we had a Transformation Status
            Object tran_stat = data.scope.get("trans_Status", data.scope);
            if (tran_stat != ScriptableObject.NOT_FOUND) {
                bWithTransStat = true;
                if (log.isDetailed()) {
                    logDetailed(("tran_Status found. Checking transformation status while script execution."));
                }
            } else {
                if (log.isDetailed()) {
                    logDetailed(("No tran_Status found. Transformation status checking not available."));
                }
                bWithTransStat = false;
            }
        }
        if (bWithTransStat) {
            iTranStat = (int) Context.toNumber(data.scope.get("trans_Status", data.scope));
        } else {
            iTranStat = CONTINUE_TRANSFORMATION;
        }
        if (iTranStat == CONTINUE_TRANSFORMATION) {
            bRC = true;
            for (int i = 0; i < meta.getFieldname().length; i++) {
                Object result = data.scope.get(meta.getFieldname()[i], data.scope);
                Object valueData = getValueFromJScript(result, i);
                if (data.replaceIndex[i] < 0) {
                    outputRow[outputIndex++] = valueData;
                } else {
                    outputRow[data.replaceIndex[i]] = valueData;
                }
            }
            // 
            if (meta.isCompatible()) {
                for (int i = 0; i < data.values_used.length; i++) {
                    ValueMetaInterface valueMeta = rowMeta.getValueMeta(data.fields_used[i]);
                    outputRow[data.fields_used[i]] = valueMeta.getValueData(data.values_used[i]);
                }
                // 
                for (Integer index : usedRowValues.keySet()) {
                    Value value = usedRowValues.get(index);
                    ValueMetaInterface valueMeta = rowMeta.getValueMeta(index);
                    outputRow[index] = valueMeta.getValueData(value);
                }
            }
            putRow(data.outputRowMeta, outputRow);
        } else {
            switch(iTranStat) {
                case SKIP_TRANSFORMATION:
                    // eat this row.
                    bRC = true;
                    break;
                case ABORT_TRANSFORMATION:
                    if (data.cx != null) {
                        Context.exit();
                    }
                    stopAll();
                    setOutputDone();
                    bRC = false;
                    break;
                case ERROR_TRANSFORMATION:
                    if (data.cx != null) {
                        Context.exit();
                    }
                    setErrors(1);
                    stopAll();
                    bRC = false;
                    break;
                default:
                    break;
            }
        // TODO: kick this "ERROR handling" junk out now that we have solid error handling in place.
        // 
        }
    } catch (Exception e) {
        throw new KettleValueException(BaseMessages.getString(PKG, "ScriptValuesMod.Log.JavascriptError"), e);
    }
    return bRC;
}
Also used : KettleException(org.pentaho.di.core.exception.KettleException) Script(org.mozilla.javascript.Script) KettleStepException(org.pentaho.di.core.exception.KettleStepException) ScriptableObject(org.mozilla.javascript.ScriptableObject) Scriptable(org.mozilla.javascript.Scriptable) KettleException(org.pentaho.di.core.exception.KettleException) EvaluatorException(org.mozilla.javascript.EvaluatorException) KettleValueException(org.pentaho.di.core.exception.KettleValueException) KettleStepException(org.pentaho.di.core.exception.KettleStepException) ValueMetaInterface(org.pentaho.di.core.row.ValueMetaInterface) Value(org.pentaho.di.compatibility.Value) ScriptableObject(org.mozilla.javascript.ScriptableObject) Row(org.pentaho.di.compatibility.Row) KettleValueException(org.pentaho.di.core.exception.KettleValueException) ValueUsedListener(org.pentaho.di.compatibility.ValueUsedListener)

Aggregations

EvaluatorException (org.mozilla.javascript.EvaluatorException)1 Script (org.mozilla.javascript.Script)1 Scriptable (org.mozilla.javascript.Scriptable)1 ScriptableObject (org.mozilla.javascript.ScriptableObject)1 Row (org.pentaho.di.compatibility.Row)1 Value (org.pentaho.di.compatibility.Value)1 ValueUsedListener (org.pentaho.di.compatibility.ValueUsedListener)1 KettleException (org.pentaho.di.core.exception.KettleException)1 KettleStepException (org.pentaho.di.core.exception.KettleStepException)1 KettleValueException (org.pentaho.di.core.exception.KettleValueException)1 ValueMetaInterface (org.pentaho.di.core.row.ValueMetaInterface)1