/*! ****************************************************************************** * * Pentaho Data Integration * * Copyright (C) 2002-2017 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.transexecutor; import java.util.ArrayList; import java.util.List; import java.util.Map; import org.pentaho.di.core.CheckResult; import org.pentaho.di.core.CheckResultInterface; import org.pentaho.di.core.Const; import org.pentaho.di.core.util.Utils; import org.pentaho.di.core.ObjectLocationSpecificationMethod; import org.pentaho.di.core.database.DatabaseMeta; import org.pentaho.di.core.exception.KettleException; import org.pentaho.di.core.exception.KettlePluginException; 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.row.value.ValueMetaFactory; 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.HasRepositoryInterface; import org.pentaho.di.repository.ObjectId; import org.pentaho.di.repository.Repository; import org.pentaho.di.repository.RepositoryDirectory; import org.pentaho.di.repository.RepositoryDirectoryInterface; import org.pentaho.di.repository.RepositoryImportLocation; import org.pentaho.di.repository.RepositoryObject; import org.pentaho.di.repository.RepositoryObjectType; import org.pentaho.di.repository.StringObjectId; import org.pentaho.di.resource.ResourceDefinition; import org.pentaho.di.resource.ResourceEntry; import org.pentaho.di.resource.ResourceEntry.ResourceType; import org.pentaho.di.resource.ResourceNamingInterface; import org.pentaho.di.resource.ResourceReference; import org.pentaho.di.trans.StepWithMappingMeta; import org.pentaho.di.trans.Trans; import org.pentaho.di.trans.TransMeta; import org.pentaho.di.trans.TransMeta.TransformationType; 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.pentaho.di.trans.step.errorhandling.Stream; import org.pentaho.di.trans.step.errorhandling.StreamIcon; import org.pentaho.di.trans.step.errorhandling.StreamInterface; import org.pentaho.di.trans.step.errorhandling.StreamInterface.StreamType; import org.pentaho.metastore.api.IMetaStore; import org.w3c.dom.Node; /** * Meta-data for the Trans Executor step. * * @author Matt * @since 18-mar-2013 */ public class TransExecutorMeta extends StepWithMappingMeta implements StepMetaInterface, HasRepositoryInterface { private static Class<?> PKG = TransExecutorMeta.class; // for i18n purposes, needed by Translator2!! static final String F_EXECUTION_RESULT_TARGET_STEP = "execution_result_target_step"; static final String F_RESULT_FILE_TARGET_STEP = "result_files_target_step"; static final String F_EXECUTOR_OUTPUT_STEP = "executors_output_step"; /** * The number of input rows that are sent as result rows to the job in one go, defaults to "1" */ private String groupSize; /** * Optional name of a field to group rows together that are sent together to the job as result rows (empty default) */ private String groupField; /** * Optional time in ms that is spent waiting and accumulating rows before they are given to the job as result rows * (empty default, "0") */ private String groupTime; private TransExecutorParameters parameters; private String executionResultTargetStep; private StepMeta executionResultTargetStepMeta; /** * The optional name of the output field that will contain the execution time of the transformation in (Integer in ms) */ private String executionTimeField; /** * The optional name of the output field that will contain the execution result (Boolean) */ private String executionResultField; /** * The optional name of the output field that will contain the number of errors (Integer) */ private String executionNrErrorsField; /** * The optional name of the output field that will contain the number of rows read (Integer) */ private String executionLinesReadField; /** * The optional name of the output field that will contain the number of rows written (Integer) */ private String executionLinesWrittenField; /** * The optional name of the output field that will contain the number of rows input (Integer) */ private String executionLinesInputField; /** * The optional name of the output field that will contain the number of rows output (Integer) */ private String executionLinesOutputField; /** * The optional name of the output field that will contain the number of rows rejected (Integer) */ private String executionLinesRejectedField; /** * The optional name of the output field that will contain the number of rows updated (Integer) */ private String executionLinesUpdatedField; /** * The optional name of the output field that will contain the number of rows deleted (Integer) */ private String executionLinesDeletedField; /** * The optional name of the output field that will contain the number of files retrieved (Integer) */ private String executionFilesRetrievedField; /** * The optional name of the output field that will contain the exit status of the last executed shell script (Integer) */ private String executionExitStatusField; /** * The optional name of the output field that will contain the log text of the transformation execution (String) */ private String executionLogTextField; /** * The optional name of the output field that will contain the log channel ID of the transformation execution (String) */ private String executionLogChannelIdField; /** * The optional step to send the result rows to */ private String outputRowsSourceStep; private StepMeta outputRowsSourceStepMeta; private String[] outputRowsField; private int[] outputRowsType; private int[] outputRowsLength; private int[] outputRowsPrecision; /** * The optional step to send the result files to */ private String resultFilesTargetStep; private StepMeta resultFilesTargetStepMeta; private String resultFilesFileNameField; /** * These fields are related to executor step's "basic" output stream, where a copy of input data will be placed */ private String executorsOutputStep; private StepMeta executorsOutputStepMeta; /** * This repository object is injected from the outside at runtime or at design time. It comes from either Spoon or * Trans */ private Repository repository; private IMetaStore metaStore; public TransExecutorMeta() { super(); // allocate BaseStepMeta parameters = new TransExecutorParameters(); this.allocate( 0 ); } public void allocate( int nrFields ) { outputRowsField = new String[nrFields]; outputRowsType = new int[nrFields]; outputRowsLength = new int[nrFields]; outputRowsPrecision = new int[nrFields]; } public Object clone() { TransExecutorMeta retval = (TransExecutorMeta) super.clone(); int nrFields = outputRowsField.length; retval.allocate( nrFields ); System.arraycopy( outputRowsField, 0, retval.outputRowsField, 0, nrFields ); System.arraycopy( outputRowsType, 0, retval.outputRowsType, 0, nrFields ); System.arraycopy( outputRowsLength, 0, retval.outputRowsLength, 0, nrFields ); System.arraycopy( outputRowsPrecision, 0, retval.outputRowsPrecision, 0, nrFields ); return retval; } public String getXML() { StringBuilder retval = new StringBuilder( 300 ); retval.append( " " ).append( XMLHandler.addTagValue( "specification_method", specificationMethod == null ? null : specificationMethod.getCode() ) ); retval.append( " " ).append( XMLHandler.addTagValue( "trans_object_id", transObjectId == null ? null : transObjectId.toString() ) ); // Export a little bit of extra information regarding the reference since it doesn't really matter outside the same // repository. // if ( repository != null && transObjectId != null ) { try { RepositoryObject objectInformation = repository.getObjectInformation( transObjectId, RepositoryObjectType.TRANSFORMATION ); if ( objectInformation != null ) { transName = objectInformation.getName(); directoryPath = objectInformation.getRepositoryDirectory().getPath(); } } catch ( KettleException e ) { // Ignore object reference problems. It simply means that the reference is no longer valid. } } retval.append( " " ).append( XMLHandler.addTagValue( "trans_name", transName ) ); retval.append( " " ).append( XMLHandler.addTagValue( "filename", fileName ) ); retval.append( " " ).append( XMLHandler.addTagValue( "directory_path", directoryPath ) ); retval.append( " " ).append( XMLHandler.addTagValue( "group_size", groupSize ) ); retval.append( " " ).append( XMLHandler.addTagValue( "group_field", groupField ) ); retval.append( " " ).append( XMLHandler.addTagValue( "group_time", groupTime ) ); // Add the mapping parameters too // retval.append( " " ).append( parameters.getXML() ).append( Const.CR ); // The output side... // retval.append( " " ).append( XMLHandler.addTagValue( F_EXECUTION_RESULT_TARGET_STEP, executionResultTargetStepMeta == null ? null : executionResultTargetStepMeta.getName() ) ); retval.append( " " ).append( XMLHandler.addTagValue( "execution_time_field", executionTimeField ) ); retval.append( " " ).append( XMLHandler.addTagValue( "execution_result_field", executionResultField ) ); retval.append( " " ).append( XMLHandler.addTagValue( "execution_errors_field", executionNrErrorsField ) ); retval.append( " " ).append( XMLHandler.addTagValue( "execution_lines_read_field", executionLinesReadField ) ); retval.append( " " ).append( XMLHandler.addTagValue( "execution_lines_written_field", executionLinesWrittenField ) ); retval.append( " " ).append( XMLHandler.addTagValue( "execution_lines_input_field", executionLinesInputField ) ); retval.append( " " ).append( XMLHandler.addTagValue( "execution_lines_output_field", executionLinesOutputField ) ); retval.append( " " ).append( XMLHandler.addTagValue( "execution_lines_rejected_field", executionLinesRejectedField ) ); retval.append( " " ).append( XMLHandler.addTagValue( "execution_lines_updated_field", executionLinesUpdatedField ) ); retval.append( " " ).append( XMLHandler.addTagValue( "execution_lines_deleted_field", executionLinesDeletedField ) ); retval.append( " " ).append( XMLHandler.addTagValue( "execution_files_retrieved_field", executionFilesRetrievedField ) ); retval.append( " " ).append( XMLHandler.addTagValue( "execution_exit_status_field", executionExitStatusField ) ); retval.append( " " ).append( XMLHandler.addTagValue( "execution_log_text_field", executionLogTextField ) ); retval.append( " " ).append( XMLHandler.addTagValue( "execution_log_channelid_field", executionLogChannelIdField ) ); retval.append( " " ).append( XMLHandler.addTagValue( "result_rows_target_step", outputRowsSourceStepMeta == null ? null : outputRowsSourceStepMeta.getName() ) ); for ( int i = 0; i < outputRowsField.length; i++ ) { retval.append( " " ).append( XMLHandler.openTag( "result_rows_field" ) ); retval.append( XMLHandler.addTagValue( "name", outputRowsField[i], false ) ); retval.append( XMLHandler.addTagValue( "type", ValueMetaFactory.getValueMetaName( outputRowsType[i] ), false ) ); retval.append( XMLHandler.addTagValue( "length", outputRowsLength[i], false ) ); retval.append( XMLHandler.addTagValue( "precision", outputRowsPrecision[i], false ) ); retval.append( XMLHandler.closeTag( "result_rows_field" ) ).append( Const.CR ); } retval.append( " " ).append( XMLHandler.addTagValue( F_RESULT_FILE_TARGET_STEP, resultFilesTargetStepMeta == null ? null : resultFilesTargetStepMeta.getName() ) ); retval.append( " " ).append( XMLHandler.addTagValue( "result_files_file_name_field", resultFilesFileNameField ) ); retval.append( " " ).append( XMLHandler.addTagValue( F_EXECUTOR_OUTPUT_STEP, executorsOutputStepMeta == null ? null : executorsOutputStepMeta.getName() ) ); return retval.toString(); } public void loadXML( Node stepnode, List<DatabaseMeta> databases, IMetaStore metaStore ) throws KettleXMLException { try { String method = XMLHandler.getTagValue( stepnode, "specification_method" ); specificationMethod = ObjectLocationSpecificationMethod.getSpecificationMethodByCode( method ); String transId = XMLHandler.getTagValue( stepnode, "trans_object_id" ); transObjectId = Utils.isEmpty( transId ) ? null : new StringObjectId( transId ); transName = XMLHandler.getTagValue( stepnode, "trans_name" ); fileName = XMLHandler.getTagValue( stepnode, "filename" ); directoryPath = XMLHandler.getTagValue( stepnode, "directory_path" ); groupSize = XMLHandler.getTagValue( stepnode, "group_size" ); groupField = XMLHandler.getTagValue( stepnode, "group_field" ); groupTime = XMLHandler.getTagValue( stepnode, "group_time" ); // Load the mapping parameters too.. // Node mappingParametersNode = XMLHandler.getSubNode( stepnode, TransExecutorParameters.XML_TAG ); parameters = new TransExecutorParameters( mappingParametersNode ); // The output side... // executionResultTargetStep = XMLHandler.getTagValue( stepnode, F_EXECUTION_RESULT_TARGET_STEP ); executionTimeField = XMLHandler.getTagValue( stepnode, "execution_time_field" ); executionResultField = XMLHandler.getTagValue( stepnode, "execution_result_field" ); executionNrErrorsField = XMLHandler.getTagValue( stepnode, "execution_errors_field" ); executionLinesReadField = XMLHandler.getTagValue( stepnode, "execution_lines_read_field" ); executionLinesWrittenField = XMLHandler.getTagValue( stepnode, "execution_lines_written_field" ); executionLinesInputField = XMLHandler.getTagValue( stepnode, "execution_lines_input_field" ); executionLinesOutputField = XMLHandler.getTagValue( stepnode, "execution_lines_output_field" ); executionLinesRejectedField = XMLHandler.getTagValue( stepnode, "execution_lines_rejected_field" ); executionLinesUpdatedField = XMLHandler.getTagValue( stepnode, "execution_lines_updated_field" ); executionLinesDeletedField = XMLHandler.getTagValue( stepnode, "execution_lines_deleted_field" ); executionFilesRetrievedField = XMLHandler.getTagValue( stepnode, "execution_files_retrieved_field" ); executionExitStatusField = XMLHandler.getTagValue( stepnode, "execution_exit_status_field" ); executionLogTextField = XMLHandler.getTagValue( stepnode, "execution_log_text_field" ); executionLogChannelIdField = XMLHandler.getTagValue( stepnode, "execution_log_channelid_field" ); outputRowsSourceStep = XMLHandler.getTagValue( stepnode, "result_rows_target_step" ); int nrFields = XMLHandler.countNodes( stepnode, "result_rows_field" ); allocate( nrFields ); for ( int i = 0; i < nrFields; i++ ) { Node fieldNode = XMLHandler.getSubNodeByNr( stepnode, "result_rows_field", i ); outputRowsField[i] = XMLHandler.getTagValue( fieldNode, "name" ); outputRowsType[i] = ValueMetaFactory.getIdForValueMeta( XMLHandler.getTagValue( fieldNode, "type" ) ); outputRowsLength[i] = Const.toInt( XMLHandler.getTagValue( fieldNode, "length" ), -1 ); outputRowsPrecision[i] = Const.toInt( XMLHandler.getTagValue( fieldNode, "precision" ), -1 ); } resultFilesTargetStep = XMLHandler.getTagValue( stepnode, F_RESULT_FILE_TARGET_STEP ); resultFilesFileNameField = XMLHandler.getTagValue( stepnode, "result_files_file_name_field" ); executorsOutputStep = XMLHandler.getTagValue( stepnode, F_EXECUTOR_OUTPUT_STEP ); } catch ( Exception e ) { throw new KettleXMLException( BaseMessages.getString( PKG, "TransExecutorMeta.Exception.ErrorLoadingTransExecutorDetailsFromXML" ), e ); } } public void readRep( Repository rep, IMetaStore metaStore, ObjectId id_step, List<DatabaseMeta> databases ) throws KettleException { String method = rep.getStepAttributeString( id_step, "specification_method" ); specificationMethod = ObjectLocationSpecificationMethod.getSpecificationMethodByCode( method ); String transId = rep.getStepAttributeString( id_step, "trans_object_id" ); transObjectId = Utils.isEmpty( transId ) ? null : new StringObjectId( transId ); transName = rep.getStepAttributeString( id_step, "trans_name" ); fileName = rep.getStepAttributeString( id_step, "filename" ); directoryPath = rep.getStepAttributeString( id_step, "directory_path" ); groupSize = rep.getStepAttributeString( id_step, "group_size" ); groupField = rep.getStepAttributeString( id_step, "group_field" ); groupTime = rep.getStepAttributeString( id_step, "group_time" ); parameters = new TransExecutorParameters( rep, id_step ); executionResultTargetStep = rep.getStepAttributeString( id_step, F_EXECUTION_RESULT_TARGET_STEP ); executionTimeField = rep.getStepAttributeString( id_step, "execution_time_field" ); executionResultField = rep.getStepAttributeString( id_step, "execution_result_field" ); executionNrErrorsField = rep.getStepAttributeString( id_step, "execution_errors_field" ); executionLinesReadField = rep.getStepAttributeString( id_step, "execution_lines_read_field" ); executionLinesWrittenField = rep.getStepAttributeString( id_step, "execution_lines_written_field" ); executionLinesInputField = rep.getStepAttributeString( id_step, "execution_lines_input_field" ); executionLinesOutputField = rep.getStepAttributeString( id_step, "execution_lines_output_field" ); executionLinesRejectedField = rep.getStepAttributeString( id_step, "execution_lines_rejected_field" ); executionLinesUpdatedField = rep.getStepAttributeString( id_step, "execution_lines_updated_field" ); executionLinesDeletedField = rep.getStepAttributeString( id_step, "execution_lines_deleted_field" ); executionFilesRetrievedField = rep.getStepAttributeString( id_step, "execution_files_retrieved_field" ); executionExitStatusField = rep.getStepAttributeString( id_step, "execution_exit_status_field" ); executionLogTextField = rep.getStepAttributeString( id_step, "execution_log_text_field" ); executionLogChannelIdField = rep.getStepAttributeString( id_step, "execution_log_channelid_field" ); outputRowsSourceStep = rep.getStepAttributeString( id_step, "result_rows_target_step" ); int nrFields = rep.countNrStepAttributes( id_step, "result_rows_field_name" ); allocate( nrFields ); for ( int i = 0; i < nrFields; i++ ) { outputRowsField[i] = rep.getStepAttributeString( id_step, i, "result_rows_field_name" ); outputRowsType[i] = ValueMetaFactory.getIdForValueMeta( rep.getStepAttributeString( id_step, i, "result_rows_field_type" ) ); outputRowsLength[i] = (int) rep.getStepAttributeInteger( id_step, i, "result_rows_field_length" ); outputRowsPrecision[i] = (int) rep.getStepAttributeInteger( id_step, i, "result_rows_field_precision" ); } resultFilesTargetStep = rep.getStepAttributeString( id_step, F_RESULT_FILE_TARGET_STEP ); resultFilesFileNameField = rep.getStepAttributeString( id_step, "result_files_file_name_field" ); executorsOutputStep = rep.getStepAttributeString( id_step, F_EXECUTOR_OUTPUT_STEP ); } public void saveRep( Repository rep, IMetaStore metaStore, ObjectId id_transformation, ObjectId id_step ) throws KettleException { rep.saveStepAttribute( id_transformation, id_step, "specification_method", specificationMethod == null ? null : specificationMethod.getCode() ); rep.saveStepAttribute( id_transformation, id_step, "trans_object_id", transObjectId == null ? null : transObjectId .toString() ); rep.saveStepAttribute( id_transformation, id_step, "filename", fileName ); rep.saveStepAttribute( id_transformation, id_step, "trans_name", transName ); rep.saveStepAttribute( id_transformation, id_step, "directory_path", directoryPath ); rep.saveStepAttribute( id_transformation, id_step, "group_size", groupSize ); rep.saveStepAttribute( id_transformation, id_step, "group_field", groupField ); rep.saveStepAttribute( id_transformation, id_step, "group_time", groupTime ); // save the mapping parameters too // parameters.saveRep( rep, metaStore, id_transformation, id_step ); // The output side... // rep.saveStepAttribute( id_transformation, id_step, F_EXECUTION_RESULT_TARGET_STEP, executionResultTargetStepMeta == null ? null : executionResultTargetStepMeta.getName() ); rep.saveStepAttribute( id_transformation, id_step, "execution_time_field", executionTimeField ); rep.saveStepAttribute( id_transformation, id_step, "execution_result_field", executionResultField ); rep.saveStepAttribute( id_transformation, id_step, "execution_errors_field", executionNrErrorsField ); rep.saveStepAttribute( id_transformation, id_step, "execution_lines_read_field", executionLinesReadField ); rep.saveStepAttribute( id_transformation, id_step, "execution_lines_written_field", executionLinesWrittenField ); rep.saveStepAttribute( id_transformation, id_step, "execution_lines_input_field", executionLinesInputField ); rep.saveStepAttribute( id_transformation, id_step, "execution_lines_output_field", executionLinesOutputField ); rep.saveStepAttribute( id_transformation, id_step, "execution_lines_rejected_field", executionLinesRejectedField ); rep.saveStepAttribute( id_transformation, id_step, "execution_lines_updated_field", executionLinesUpdatedField ); rep.saveStepAttribute( id_transformation, id_step, "execution_lines_deleted_field", executionLinesDeletedField ); rep.saveStepAttribute( id_transformation, id_step, "execution_files_retrieved_field", executionFilesRetrievedField ); rep.saveStepAttribute( id_transformation, id_step, "execution_exit_status_field", executionExitStatusField ); rep.saveStepAttribute( id_transformation, id_step, "execution_log_text_field", executionLogTextField ); rep.saveStepAttribute( id_transformation, id_step, "execution_log_channelid_field", executionLogChannelIdField ); rep.saveStepAttribute( id_transformation, id_step, "result_rows_target_step", outputRowsSourceStepMeta == null ? null : outputRowsSourceStepMeta.getName() ); for ( int i = 0; i < outputRowsField.length; i++ ) { rep.saveStepAttribute( id_transformation, id_step, i, "result_rows_field_name", outputRowsField[i] ); rep.saveStepAttribute( id_transformation, id_step, i, "result_rows_field_type", ValueMetaFactory.getValueMetaName( outputRowsType[i] ) ); rep.saveStepAttribute( id_transformation, id_step, i, "result_rows_field_length", outputRowsLength[i] ); rep.saveStepAttribute( id_transformation, id_step, i, "result_rows_field_precision", outputRowsPrecision[i] ); } rep.saveStepAttribute( id_transformation, id_step, F_RESULT_FILE_TARGET_STEP, resultFilesTargetStepMeta == null ? null : resultFilesTargetStepMeta.getName() ); rep.saveStepAttribute( id_transformation, id_step, "result_files_file_name_field", resultFilesFileNameField ); rep.saveStepAttribute( id_transformation, id_step, F_EXECUTOR_OUTPUT_STEP, executorsOutputStepMeta == null ? null : executorsOutputStepMeta.getName() ); } public void setDefault() { specificationMethod = ObjectLocationSpecificationMethod.FILENAME; parameters = new TransExecutorParameters(); parameters.setInheritingAllVariables( true ); groupSize = "1"; groupField = ""; groupTime = ""; executionTimeField = "ExecutionTime"; executionResultField = "ExecutionResult"; executionNrErrorsField = "ExecutionNrErrors"; executionLinesReadField = "ExecutionLinesRead"; executionLinesWrittenField = "ExecutionLinesWritten"; executionLinesInputField = "ExecutionLinesInput"; executionLinesOutputField = "ExecutionLinesOutput"; executionLinesRejectedField = "ExecutionLinesRejected"; executionLinesUpdatedField = "ExecutionLinesUpdated"; executionLinesDeletedField = "ExecutionLinesDeleted"; executionFilesRetrievedField = "ExecutionFilesRetrieved"; executionExitStatusField = "ExecutionExitStatus"; executionLogTextField = "ExecutionLogText"; executionLogChannelIdField = "ExecutionLogChannelId"; resultFilesFileNameField = "FileName"; } void prepareExecutionResultsFields( RowMetaInterface row, StepMeta nextStep ) throws KettleStepException { if ( nextStep != null && executionResultTargetStepMeta != null ) { addFieldToRow( row, executionTimeField, ValueMetaInterface.TYPE_INTEGER, 15, 0 ); addFieldToRow( row, executionResultField, ValueMetaInterface.TYPE_BOOLEAN ); addFieldToRow( row, executionNrErrorsField, ValueMetaInterface.TYPE_INTEGER, 9, 0 ); addFieldToRow( row, executionLinesReadField, ValueMetaInterface.TYPE_INTEGER, 9, 0 ); addFieldToRow( row, executionLinesWrittenField, ValueMetaInterface.TYPE_INTEGER, 9, 0 ); addFieldToRow( row, executionLinesInputField, ValueMetaInterface.TYPE_INTEGER, 9, 0 ); addFieldToRow( row, executionLinesOutputField, ValueMetaInterface.TYPE_INTEGER, 9, 0 ); addFieldToRow( row, executionLinesRejectedField, ValueMetaInterface.TYPE_INTEGER, 9, 0 ); addFieldToRow( row, executionLinesUpdatedField, ValueMetaInterface.TYPE_INTEGER, 9, 0 ); addFieldToRow( row, executionLinesDeletedField, ValueMetaInterface.TYPE_INTEGER, 9, 0 ); addFieldToRow( row, executionFilesRetrievedField, ValueMetaInterface.TYPE_INTEGER, 9, 0 ); addFieldToRow( row, executionExitStatusField, ValueMetaInterface.TYPE_INTEGER, 3, 0 ); addFieldToRow( row, executionLogTextField, ValueMetaInterface.TYPE_STRING ); addFieldToRow( row, executionLogChannelIdField, ValueMetaInterface.TYPE_STRING, 50, 0 ); } } protected void addFieldToRow( RowMetaInterface row, String fieldName, int type ) throws KettleStepException { addFieldToRow( row, fieldName, type, -1, -1 ); } protected void addFieldToRow( RowMetaInterface row, String fieldName, int type, int length, int precision ) throws KettleStepException { if ( !Utils.isEmpty( fieldName ) ) { try { ValueMetaInterface value = ValueMetaFactory.createValueMeta( fieldName, type, length, precision ); value.setOrigin( getParentStepMeta().getName() ); row.addValueMeta( value ); } catch ( KettlePluginException e ) { throw new KettleStepException( BaseMessages.getString( PKG, "TransExecutorMeta.ValueMetaInterfaceCreation", fieldName ), e ); } } } void prepareExecutionResultsFileFields( RowMetaInterface row, StepMeta nextStep ) throws KettleStepException { if ( nextStep != null && resultFilesTargetStepMeta != null && nextStep.equals( resultFilesTargetStepMeta ) ) { addFieldToRow( row, resultFilesFileNameField, ValueMetaInterface.TYPE_STRING ); } } void prepareResultsRowsFields( RowMetaInterface row ) throws KettleStepException { for ( int i = 0; i < outputRowsField.length; i++ ) { addFieldToRow( row, outputRowsField[i], outputRowsType[i], outputRowsLength[i], outputRowsPrecision[i] ); } } @Override public void getFields( RowMetaInterface inputRowMeta, String name, RowMetaInterface[] info, StepMeta nextStep, VariableSpace space, Repository repository, IMetaStore metaStore ) throws KettleStepException { if ( nextStep != null ) { if ( nextStep.equals( executionResultTargetStepMeta ) ) { inputRowMeta.clear(); prepareExecutionResultsFields( inputRowMeta, nextStep ); } else if ( nextStep.equals( resultFilesTargetStepMeta ) ) { inputRowMeta.clear(); prepareExecutionResultsFileFields( inputRowMeta, nextStep ); } else if ( nextStep.equals( outputRowsSourceStepMeta ) ) { inputRowMeta.clear(); prepareResultsRowsFields( inputRowMeta ); } // else don't call clear on inputRowMeta, it's the main output and should mimic the input } } public String[] getInfoSteps() { String[] infoSteps = getStepIOMeta().getInfoStepnames(); // Return null instead of empty array to preserve existing behavior return infoSteps.length == 0 ? null : infoSteps; } @Deprecated public static synchronized TransMeta loadTransMeta( TransExecutorMeta executorMeta, Repository rep, VariableSpace space ) throws KettleException { return loadMappingMeta( executorMeta, rep, null, space ); } public void check( List<CheckResultInterface> remarks, TransMeta transMeta, StepMeta stepinfo, RowMetaInterface prev, String[] input, String[] output, RowMetaInterface info, VariableSpace space, Repository repository, IMetaStore metaStore ) { CheckResult cr; if ( prev == null || prev.size() == 0 ) { cr = new CheckResult( CheckResultInterface.TYPE_RESULT_WARNING, BaseMessages.getString( PKG, "TransExecutorMeta.CheckResult.NotReceivingAnyFields" ), stepinfo ); remarks.add( cr ); } else { cr = new CheckResult( CheckResultInterface.TYPE_RESULT_OK, BaseMessages.getString( PKG, "TransExecutorMeta.CheckResult.StepReceivingFields", prev.size() + "" ), stepinfo ); remarks.add( cr ); } // See if we have input streams leading to this step! if ( input.length > 0 ) { cr = new CheckResult( CheckResultInterface.TYPE_RESULT_OK, BaseMessages.getString( PKG, "TransExecutorMeta.CheckResult.StepReceivingFieldsFromOtherSteps" ), stepinfo ); remarks.add( cr ); } else { cr = new CheckResult( CheckResultInterface.TYPE_RESULT_ERROR, BaseMessages.getString( PKG, "TransExecutorMeta.CheckResult.NoInputReceived" ), stepinfo ); remarks.add( cr ); } } public StepInterface getStep( StepMeta stepMeta, StepDataInterface stepDataInterface, int cnr, TransMeta tr, Trans trans ) { return new TransExecutor( stepMeta, stepDataInterface, cnr, tr, trans ); } @Override public List<ResourceReference> getResourceDependencies( TransMeta transMeta, StepMeta stepInfo ) { List<ResourceReference> references = new ArrayList<ResourceReference>( 5 ); String realFilename = transMeta.environmentSubstitute( fileName ); String realTransname = transMeta.environmentSubstitute( transName ); ResourceReference reference = new ResourceReference( stepInfo ); references.add( reference ); if ( !Utils.isEmpty( realFilename ) ) { // Add the filename to the references, including a reference to this step // meta data. // reference.getEntries().add( new ResourceEntry( realFilename, ResourceType.ACTIONFILE ) ); } else if ( !Utils.isEmpty( realTransname ) ) { // Add the filename to the references, including a reference to this step // meta data. // reference.getEntries().add( new ResourceEntry( realTransname, ResourceType.ACTIONFILE ) ); references.add( reference ); } return references; } @Override public String exportResources( VariableSpace space, Map<String, ResourceDefinition> definitions, ResourceNamingInterface resourceNamingInterface, Repository repository, IMetaStore metaStore ) throws KettleException { try { // Try to load the transformation from repository or file. // Modify this recursively too... // // NOTE: there is no need to clone this step because the caller is // responsible for this. // // First load the executor transformation metadata... // TransMeta executorTransMeta = loadTransMeta( this, repository, space ); // Also go down into the mapping transformation and export the files // there. (mapping recursively down) // String proposedNewFilename = executorTransMeta.exportResources( executorTransMeta, definitions, resourceNamingInterface, repository, metaStore ); // To get a relative path to it, we inject // ${Internal.Transformation.Filename.Directory} // String newFilename = "${" + Const.INTERNAL_VARIABLE_TRANSFORMATION_FILENAME_DIRECTORY + "}/" + proposedNewFilename; // Set the correct filename inside the XML. // executorTransMeta.setFilename( newFilename ); // exports always reside in the root directory, in case we want to turn // this into a file repository... // executorTransMeta.setRepositoryDirectory( new RepositoryDirectory() ); // change it in the entry // fileName = newFilename; return proposedNewFilename; } catch ( Exception e ) { throw new KettleException( BaseMessages.getString( PKG, "TransExecutorMeta.Exception.UnableToLoadTrans", fileName ) ); } } public StepDataInterface getStepData() { return new TransExecutorData(); } @Override public StepIOMetaInterface getStepIOMeta() { if ( ioMeta == null ) { ioMeta = new StepIOMeta( true, true, true, false, true, false ); ioMeta.addStream( new Stream( StreamType.TARGET, executionResultTargetStepMeta, BaseMessages.getString( PKG, "TransExecutorMeta.ResultStream.Description" ), StreamIcon.TARGET, null ) ); ioMeta.addStream( new Stream( StreamType.TARGET, outputRowsSourceStepMeta, BaseMessages.getString( PKG, "TransExecutorMeta.ResultRowsStream.Description" ), StreamIcon.TARGET, null ) ); ioMeta.addStream( new Stream( StreamType.TARGET, resultFilesTargetStepMeta, BaseMessages.getString( PKG, "TransExecutorMeta.ResultFilesStream.Description" ), StreamIcon.TARGET, null ) ); ioMeta.addStream( new Stream( StreamType.TARGET, executorsOutputStepMeta, BaseMessages.getString( PKG, "TransExecutorMeta.ExecutorOutputStream.Description" ), StreamIcon.OUTPUT, null ) ); } return ioMeta; } /** * When an optional stream is selected, this method is called to handled the ETL metadata implications of that. * * @param stream * The optional stream to handle. */ public void handleStreamSelection( StreamInterface stream ) { // This step targets another step. // Make sure that we don't specify the same step for more than 1 target... List<StreamInterface> targets = getStepIOMeta().getTargetStreams(); int index = targets.indexOf( stream ); StepMeta step = targets.get( index ).getStepMeta(); switch ( index ) { case 0: setExecutionResultTargetStepMeta( step ); break; case 1: setOutputRowsSourceStepMeta( step ); break; case 2: setResultFilesTargetStepMeta( step ); break; case 3: setExecutorsOutputStepMeta( step ); default: break; } } /** * Remove the cached {@link StepIOMeta} so it is recreated when it is next accessed. */ public void resetStepIoMeta() { } @Override public void searchInfoAndTargetSteps( List<StepMeta> steps ) { executionResultTargetStepMeta = StepMeta.findStep( steps, executionResultTargetStep ); outputRowsSourceStepMeta = StepMeta.findStep( steps, outputRowsSourceStep ); resultFilesTargetStepMeta = StepMeta.findStep( steps, resultFilesTargetStep ); executorsOutputStepMeta = StepMeta.findStep( steps, executorsOutputStep ); } public TransformationType[] getSupportedTransformationTypes() { return new TransformationType[] { TransformationType.Normal, }; } @Override public boolean hasRepositoryReferences() { return specificationMethod == ObjectLocationSpecificationMethod.REPOSITORY_BY_REFERENCE; } @Override public void lookupRepositoryReferences( Repository repository ) throws KettleException { // The correct reference is stored in the trans name and directory attributes... // RepositoryDirectoryInterface repositoryDirectoryInterface = RepositoryImportLocation.getRepositoryImportLocation().findDirectory( directoryPath ); transObjectId = repository.getTransformationID( transName, repositoryDirectoryInterface ); } /** * @return the mappingParameters */ public TransExecutorParameters getMappingParameters() { return parameters; } /** * @param mappingParameters * the mappingParameters to set */ public void setMappingParameters( TransExecutorParameters mappingParameters ) { this.parameters = mappingParameters; } /** * @return the repository */ public Repository getRepository() { return repository; } /** * @param repository * the repository to set */ public void setRepository( Repository repository ) { this.repository = repository; } /** * @return the parameters */ public TransExecutorParameters getParameters() { return parameters; } /** * @param parameters * the parameters to set */ public void setParameters( TransExecutorParameters parameters ) { this.parameters = parameters; } /** * @return the executionTimeField */ public String getExecutionTimeField() { return executionTimeField; } /** * @param executionTimeField * the executionTimeField to set */ public void setExecutionTimeField( String executionTimeField ) { this.executionTimeField = executionTimeField; } /** * @return the executionResultField */ public String getExecutionResultField() { return executionResultField; } /** * @param executionResultField * the executionResultField to set */ public void setExecutionResultField( String executionResultField ) { this.executionResultField = executionResultField; } /** * @return the executionNrErrorsField */ public String getExecutionNrErrorsField() { return executionNrErrorsField; } /** * @param executionNrErrorsField * the executionNrErrorsField to set */ public void setExecutionNrErrorsField( String executionNrErrorsField ) { this.executionNrErrorsField = executionNrErrorsField; } /** * @return the executionLinesReadField */ public String getExecutionLinesReadField() { return executionLinesReadField; } /** * @param executionLinesReadField * the executionLinesReadField to set */ public void setExecutionLinesReadField( String executionLinesReadField ) { this.executionLinesReadField = executionLinesReadField; } /** * @return the executionLinesWrittenField */ public String getExecutionLinesWrittenField() { return executionLinesWrittenField; } /** * @param executionLinesWrittenField * the executionLinesWrittenField to set */ public void setExecutionLinesWrittenField( String executionLinesWrittenField ) { this.executionLinesWrittenField = executionLinesWrittenField; } /** * @return the executionLinesInputField */ public String getExecutionLinesInputField() { return executionLinesInputField; } /** * @param executionLinesInputField * the executionLinesInputField to set */ public void setExecutionLinesInputField( String executionLinesInputField ) { this.executionLinesInputField = executionLinesInputField; } /** * @return the executionLinesOutputField */ public String getExecutionLinesOutputField() { return executionLinesOutputField; } /** * @param executionLinesOutputField * the executionLinesOutputField to set */ public void setExecutionLinesOutputField( String executionLinesOutputField ) { this.executionLinesOutputField = executionLinesOutputField; } /** * @return the executionLinesRejectedField */ public String getExecutionLinesRejectedField() { return executionLinesRejectedField; } /** * @param executionLinesRejectedField * the executionLinesRejectedField to set */ public void setExecutionLinesRejectedField( String executionLinesRejectedField ) { this.executionLinesRejectedField = executionLinesRejectedField; } /** * @return the executionLinesUpdatedField */ public String getExecutionLinesUpdatedField() { return executionLinesUpdatedField; } /** * @param executionLinesUpdatedField * the executionLinesUpdatedField to set */ public void setExecutionLinesUpdatedField( String executionLinesUpdatedField ) { this.executionLinesUpdatedField = executionLinesUpdatedField; } /** * @return the executionLinesDeletedField */ public String getExecutionLinesDeletedField() { return executionLinesDeletedField; } /** * @param executionLinesDeletedField * the executionLinesDeletedField to set */ public void setExecutionLinesDeletedField( String executionLinesDeletedField ) { this.executionLinesDeletedField = executionLinesDeletedField; } /** * @return the executionFilesRetrievedField */ public String getExecutionFilesRetrievedField() { return executionFilesRetrievedField; } /** * @param executionFilesRetrievedField * the executionFilesRetrievedField to set */ public void setExecutionFilesRetrievedField( String executionFilesRetrievedField ) { this.executionFilesRetrievedField = executionFilesRetrievedField; } /** * @return the executionExitStatusField */ public String getExecutionExitStatusField() { return executionExitStatusField; } /** * @param executionExitStatusField * the executionExitStatusField to set */ public void setExecutionExitStatusField( String executionExitStatusField ) { this.executionExitStatusField = executionExitStatusField; } /** * @return the executionLogTextField */ public String getExecutionLogTextField() { return executionLogTextField; } /** * @param executionLogTextField * the executionLogTextField to set */ public void setExecutionLogTextField( String executionLogTextField ) { this.executionLogTextField = executionLogTextField; } /** * @return the executionLogChannelIdField */ public String getExecutionLogChannelIdField() { return executionLogChannelIdField; } /** * @param executionLogChannelIdField * the executionLogChannelIdField to set */ public void setExecutionLogChannelIdField( String executionLogChannelIdField ) { this.executionLogChannelIdField = executionLogChannelIdField; } /** * @return the groupSize */ public String getGroupSize() { return groupSize; } /** * @param groupSize * the groupSize to set */ public void setGroupSize( String groupSize ) { this.groupSize = groupSize; } /** * @return the groupField */ public String getGroupField() { return groupField; } /** * @param groupField * the groupField to set */ public void setGroupField( String groupField ) { this.groupField = groupField; } /** * @return the groupTime */ public String getGroupTime() { return groupTime; } /** * @param groupTime * the groupTime to set */ public void setGroupTime( String groupTime ) { this.groupTime = groupTime; } @Override public boolean excludeFromCopyDistributeVerification() { return true; } /** * @return the executionResultTargetStep */ public String getExecutionResultTargetStep() { return executionResultTargetStep; } /** * @param executionResultTargetStep * the executionResultTargetStep to set */ public void setExecutionResultTargetStep( String executionResultTargetStep ) { this.executionResultTargetStep = executionResultTargetStep; } /** * @return the executionResultTargetStepMeta */ public StepMeta getExecutionResultTargetStepMeta() { return executionResultTargetStepMeta; } /** * @param executionResultTargetStepMeta * the executionResultTargetStepMeta to set */ public void setExecutionResultTargetStepMeta( StepMeta executionResultTargetStepMeta ) { this.executionResultTargetStepMeta = executionResultTargetStepMeta; } /** * @return the resultFilesFileNameField */ public String getResultFilesFileNameField() { return resultFilesFileNameField; } /** * @param resultFilesFileNameField * the resultFilesFileNameField to set */ public void setResultFilesFileNameField( String resultFilesFileNameField ) { this.resultFilesFileNameField = resultFilesFileNameField; } /** * @return The objects referenced in the step, like a mapping, a transformation, ... */ public String[] getReferencedObjectDescriptions() { return new String[] { BaseMessages.getString( PKG, "TransExecutorMeta.ReferencedObject.Description" ), }; } private boolean isTransDefined() { return !Utils.isEmpty( fileName ) || transObjectId != null || ( !Utils.isEmpty( this.directoryPath ) && !Utils .isEmpty( transName ) ); } public boolean[] isReferencedObjectEnabled() { return new boolean[] { isTransDefined(), }; } /** * Load the referenced object * * @param index * the object index to load * @param rep * the repository * @param space * the variable space to use * @return the referenced object once loaded * @throws KettleException */ public Object loadReferencedObject( int index, Repository rep, IMetaStore metaStore, VariableSpace space ) throws KettleException { return loadMappingMeta( this, rep, metaStore, space ); } public IMetaStore getMetaStore() { return metaStore; } public void setMetaStore( IMetaStore metaStore ) { this.metaStore = metaStore; } public String getOutputRowsSourceStep() { return outputRowsSourceStep; } public void setOutputRowsSourceStep( String outputRowsSourceStep ) { this.outputRowsSourceStep = outputRowsSourceStep; } public StepMeta getOutputRowsSourceStepMeta() { return outputRowsSourceStepMeta; } public void setOutputRowsSourceStepMeta( StepMeta outputRowsSourceStepMeta ) { this.outputRowsSourceStepMeta = outputRowsSourceStepMeta; } public String[] getOutputRowsField() { return outputRowsField; } public void setOutputRowsField( String[] outputRowsField ) { this.outputRowsField = outputRowsField; } public int[] getOutputRowsType() { return outputRowsType; } public void setOutputRowsType( int[] outputRowsType ) { this.outputRowsType = outputRowsType; } public int[] getOutputRowsLength() { return outputRowsLength; } public void setOutputRowsLength( int[] outputRowsLength ) { this.outputRowsLength = outputRowsLength; } public int[] getOutputRowsPrecision() { return outputRowsPrecision; } public void setOutputRowsPrecision( int[] outputRowsPrecision ) { this.outputRowsPrecision = outputRowsPrecision; } public String getResultFilesTargetStep() { return resultFilesTargetStep; } public void setResultFilesTargetStep( String resultFilesTargetStep ) { this.resultFilesTargetStep = resultFilesTargetStep; } public StepMeta getResultFilesTargetStepMeta() { return resultFilesTargetStepMeta; } public void setResultFilesTargetStepMeta( StepMeta resultFilesTargetStepMeta ) { this.resultFilesTargetStepMeta = resultFilesTargetStepMeta; } public String getExecutorsOutputStep() { return executorsOutputStep; } public void setExecutorsOutputStep( String executorsOutputStep ) { this.executorsOutputStep = executorsOutputStep; } public StepMeta getExecutorsOutputStepMeta() { return executorsOutputStepMeta; } public void setExecutorsOutputStepMeta( StepMeta executorsOutputStepMeta ) { this.executorsOutputStepMeta = executorsOutputStepMeta; } @Override public boolean cleanAfterHopFromRemove() { setExecutionResultTargetStepMeta( null ); setOutputRowsSourceStepMeta( null ); setResultFilesTargetStepMeta( null ); setExecutorsOutputStepMeta( null ); return true; } }