/*! ****************************************************************************** * * 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.step; import java.util.List; import org.pentaho.di.core.Const; import org.pentaho.di.core.util.Utils; import org.pentaho.di.core.changed.ChangedFlag; import org.pentaho.di.core.row.RowMeta; import org.pentaho.di.core.row.RowMetaInterface; import org.pentaho.di.core.row.ValueMetaInterface; import org.pentaho.di.core.row.value.ValueMetaInteger; import org.pentaho.di.core.row.value.ValueMetaString; import org.pentaho.di.core.variables.VariableSpace; import org.pentaho.di.core.xml.XMLHandler; import org.pentaho.di.core.xml.XMLInterface; import org.w3c.dom.Node; /** * This class contains the metadata to handle proper error handling on a step level. * * @author Matt * */ public class StepErrorMeta extends ChangedFlag implements XMLInterface, Cloneable { public static final String XML_ERROR_TAG = "error"; public static final String XML_SOURCE_STEP_TAG = "source_step"; public static final String XML_TARGET_STEP_TAG = "target_step"; /** The source step that can send the error rows */ private StepMeta sourceStep; /** The target step to send the error rows to */ private StepMeta targetStep; /** Is the error handling enabled? */ private boolean enabled; /** the name of the field value to contain the number of errors (null or empty means it's not needed) */ private String nrErrorsValuename; /** the name of the field value to contain the error description(s) (null or empty means it's not needed) */ private String errorDescriptionsValuename; /** * the name of the field value to contain the fields for which the error(s) occured (null or empty means it's not * needed) */ private String errorFieldsValuename; /** the name of the field value to contain the error code(s) (null or empty means it's not needed) */ private String errorCodesValuename; /** The maximum number of errors allowed before we stop processing with a hard error */ private String maxErrors = ""; /** The maximum percent of errors allowed before we stop processing with a hard error */ private String maxPercentErrors = ""; /** The minimum number of rows to read before the percentage evaluation takes place */ private String minPercentRows = ""; private VariableSpace variables; /** * Create a new step error handling metadata object * * @param sourceStep * The source step that can send the error rows */ public StepErrorMeta( VariableSpace space, StepMeta sourceStep ) { this.sourceStep = sourceStep; this.enabled = false; this.variables = space; } /** * Create a new step error handling metadata object * * @param sourceStep * The source step that can send the error rows * @param targetStep * The target step to send the error rows to */ public StepErrorMeta( VariableSpace space, StepMeta sourceStep, StepMeta targetStep ) { this.sourceStep = sourceStep; this.targetStep = targetStep; this.enabled = false; this.variables = space; } /** * Create a new step error handling metadata object * * @param sourceStep * The source step that can send the error rows * @param targetStep * The target step to send the error rows to * @param nrErrorsValuename * the name of the field value to contain the number of errors (null or empty means it's not needed) * @param errorDescriptionsValuename * the name of the field value to contain the error description(s) (null or empty means it's not needed) * @param errorFieldsValuename * the name of the field value to contain the fields for which the error(s) occured (null or empty means it's * not needed) * @param errorCodesValuename * the name of the field value to contain the error code(s) (null or empty means it's not needed) */ public StepErrorMeta( VariableSpace space, StepMeta sourceStep, StepMeta targetStep, String nrErrorsValuename, String errorDescriptionsValuename, String errorFieldsValuename, String errorCodesValuename ) { this.sourceStep = sourceStep; this.targetStep = targetStep; this.enabled = false; this.nrErrorsValuename = nrErrorsValuename; this.errorDescriptionsValuename = errorDescriptionsValuename; this.errorFieldsValuename = errorFieldsValuename; this.errorCodesValuename = errorCodesValuename; this.variables = space; } @Override public StepErrorMeta clone() { try { return (StepErrorMeta) super.clone(); } catch ( CloneNotSupportedException e ) { return null; } } @Override public String getXML() { StringBuilder xml = new StringBuilder( 300 ); xml.append( " " ).append( XMLHandler.openTag( StepErrorMeta.XML_ERROR_TAG ) ).append( Const.CR ); xml.append( " " ).append( XMLHandler.addTagValue( StepErrorMeta.XML_SOURCE_STEP_TAG, sourceStep != null ? sourceStep.getName() : "" ) ); xml.append( " " ).append( XMLHandler.addTagValue( StepErrorMeta.XML_TARGET_STEP_TAG, targetStep != null ? targetStep.getName() : "" ) ); xml.append( " " ).append( XMLHandler.addTagValue( "is_enabled", enabled ) ); xml.append( " " ).append( XMLHandler.addTagValue( "nr_valuename", nrErrorsValuename ) ); xml .append( " " ).append( XMLHandler.addTagValue( "descriptions_valuename", errorDescriptionsValuename ) ); xml.append( " " ).append( XMLHandler.addTagValue( "fields_valuename", errorFieldsValuename ) ); xml.append( " " ).append( XMLHandler.addTagValue( "codes_valuename", errorCodesValuename ) ); xml.append( " " ).append( XMLHandler.addTagValue( "max_errors", maxErrors ) ); xml.append( " " ).append( XMLHandler.addTagValue( "max_pct_errors", maxPercentErrors ) ); xml.append( " " ).append( XMLHandler.addTagValue( "min_pct_rows", minPercentRows ) ); xml.append( " " ).append( XMLHandler.closeTag( StepErrorMeta.XML_ERROR_TAG ) ).append( Const.CR ); return xml.toString(); } public StepErrorMeta( VariableSpace variables, Node node, List<StepMeta> steps ) { this.variables = variables; sourceStep = StepMeta.findStep( steps, XMLHandler.getTagValue( node, StepErrorMeta.XML_SOURCE_STEP_TAG ) ); targetStep = StepMeta.findStep( steps, XMLHandler.getTagValue( node, StepErrorMeta.XML_TARGET_STEP_TAG ) ); enabled = "Y".equals( XMLHandler.getTagValue( node, "is_enabled" ) ); nrErrorsValuename = XMLHandler.getTagValue( node, "nr_valuename" ); errorDescriptionsValuename = XMLHandler.getTagValue( node, "descriptions_valuename" ); errorFieldsValuename = XMLHandler.getTagValue( node, "fields_valuename" ); errorCodesValuename = XMLHandler.getTagValue( node, "codes_valuename" ); maxErrors = XMLHandler.getTagValue( node, "max_errors" ); maxPercentErrors = XMLHandler.getTagValue( node, "max_pct_errors" ); minPercentRows = XMLHandler.getTagValue( node, "min_pct_rows" ); } /** * @return the error codes valuename */ public String getErrorCodesValuename() { return errorCodesValuename; } /** * @param errorCodesValuename * the error codes valuename to set */ public void setErrorCodesValuename( String errorCodesValuename ) { this.errorCodesValuename = errorCodesValuename; } /** * @return the error descriptions valuename */ public String getErrorDescriptionsValuename() { return errorDescriptionsValuename; } /** * @param errorDescriptionsValuename * the error descriptions valuename to set */ public void setErrorDescriptionsValuename( String errorDescriptionsValuename ) { this.errorDescriptionsValuename = errorDescriptionsValuename; } /** * @return the error fields valuename */ public String getErrorFieldsValuename() { return errorFieldsValuename; } /** * @param errorFieldsValuename * the error fields valuename to set */ public void setErrorFieldsValuename( String errorFieldsValuename ) { this.errorFieldsValuename = errorFieldsValuename; } /** * @return the nr errors valuename */ public String getNrErrorsValuename() { return nrErrorsValuename; } /** * @param nrErrorsValuename * the nr errors valuename to set */ public void setNrErrorsValuename( String nrErrorsValuename ) { this.nrErrorsValuename = nrErrorsValuename; } /** * @return the target step */ public StepMeta getTargetStep() { return targetStep; } /** * @param targetStep * the target step to set */ public void setTargetStep( StepMeta targetStep ) { this.targetStep = targetStep; } /** * @return The source step can send the error rows */ public StepMeta getSourceStep() { return sourceStep; } /** * @param sourceStep * The source step can send the error rows */ public void setSourceStep( StepMeta sourceStep ) { this.sourceStep = sourceStep; } /** * @return the enabled flag: Is the error handling enabled? */ public boolean isEnabled() { return enabled; } /** * @param enabled * the enabled flag to set: Is the error handling enabled? */ public void setEnabled( boolean enabled ) { this.enabled = enabled; } public RowMetaInterface getErrorFields() { return getErrorRowMeta( 0L, null, null, null ); } public RowMetaInterface getErrorRowMeta( long nrErrors, String errorDescriptions, String fieldNames, String errorCodes ) { RowMetaInterface row = new RowMeta(); String nrErr = variables.environmentSubstitute( getNrErrorsValuename() ); if ( !Utils.isEmpty( nrErr ) ) { ValueMetaInterface v = new ValueMetaInteger( nrErr ); v.setLength( 3 ); row.addValueMeta( v ); } String errDesc = variables.environmentSubstitute( getErrorDescriptionsValuename() ); if ( !Utils.isEmpty( errDesc ) ) { ValueMetaInterface v = new ValueMetaString( errDesc ); row.addValueMeta( v ); } String errFields = variables.environmentSubstitute( getErrorFieldsValuename() ); if ( !Utils.isEmpty( errFields ) ) { ValueMetaInterface v = new ValueMetaString( errFields ); row.addValueMeta( v ); } String errCodes = variables.environmentSubstitute( getErrorCodesValuename() ); if ( !Utils.isEmpty( errCodes ) ) { ValueMetaInterface v = new ValueMetaString( errCodes ); row.addValueMeta( v ); } return row; } public void addErrorRowData( Object[] row, int startIndex, long nrErrors, String errorDescriptions, String fieldNames, String errorCodes ) { int index = startIndex; String nrErr = variables.environmentSubstitute( getNrErrorsValuename() ); if ( !Utils.isEmpty( nrErr ) ) { row[index] = new Long( nrErrors ); index++; } String errDesc = variables.environmentSubstitute( getErrorDescriptionsValuename() ); if ( !Utils.isEmpty( errDesc ) ) { row[index] = errorDescriptions; index++; } String errFields = variables.environmentSubstitute( getErrorFieldsValuename() ); if ( !Utils.isEmpty( errFields ) ) { row[index] = fieldNames; index++; } String errCodes = variables.environmentSubstitute( getErrorCodesValuename() ); if ( !Utils.isEmpty( errCodes ) ) { row[index] = errorCodes; index++; } } /** * @return the maxErrors */ public String getMaxErrors() { return maxErrors; } /** * @param maxErrors * the maxErrors to set */ public void setMaxErrors( String maxErrors ) { this.maxErrors = maxErrors; } /** * @return the maxPercentErrors */ public String getMaxPercentErrors() { return maxPercentErrors; } /** * @param maxPercentErrors * the maxPercentErrors to set */ public void setMaxPercentErrors( String maxPercentErrors ) { this.maxPercentErrors = maxPercentErrors; } /** * @return the minRowsForPercent */ public String getMinPercentRows() { return minPercentRows; } /** * @param minRowsForPercent * the minRowsForPercent to set */ public void setMinPercentRows( String minRowsForPercent ) { this.minPercentRows = minRowsForPercent; } }