/*! ****************************************************************************** * * Pentaho Data Integration * * Copyright (C) 2002-2016 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.selectvalues; import java.util.ArrayList; import java.util.Arrays; import java.util.Collections; import java.util.List; 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.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.KettleValueException; import org.pentaho.di.core.exception.KettleXMLException; import org.pentaho.di.core.injection.Injection; import org.pentaho.di.core.injection.InjectionDeep; import org.pentaho.di.core.injection.InjectionSupported; 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.ValueMetaBase; import org.pentaho.di.core.row.value.ValueMetaFactory; import org.pentaho.di.core.util.EnvUtil; import org.pentaho.di.core.variables.VariableSpace; import org.pentaho.di.core.xml.XMLHandler; import org.pentaho.di.i18n.BaseMessages; import org.pentaho.di.lineage.FieldnameLineage; 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.StepInterface; import org.pentaho.di.trans.step.StepMeta; import org.pentaho.di.trans.step.StepMetaInterface; import org.pentaho.metastore.api.IMetaStore; import org.w3c.dom.Node; /** * Meta Data class for the Select Values Step. * * Created on 02-jun-2003 */ @InjectionSupported( localizationPrefix = "SelectValues.Injection.", groups = { "FIELDS", "REMOVES", "METAS" } ) public class SelectValuesMeta extends BaseStepMeta implements StepMetaInterface { private static Class<?> PKG = SelectValuesMeta.class; // for i18n purposes, needed by Translator2!! public static final int UNDEFINED = -2; // SELECT mode @InjectionDeep private SelectField[] selectFields = {}; /** * Select: flag to indicate that the non-selected fields should also be taken along, ordered by fieldname */ @Injection( name = "SELECT_UNSPECIFIED" ) private boolean selectingAndSortingUnspecifiedFields; // DE-SELECT mode /** Names of the fields to be removed! */ @Injection( name = "REMOVE_NAME", group = "REMOVES" ) private String[] deleteName = {}; // META-DATA mode @InjectionDeep private SelectMetadataChange[] meta = {}; public SelectValuesMeta() { super(); // allocate BaseStepMeta } /** * @return Returns the deleteName. */ public String[] getDeleteName() { return deleteName; } /** * @param deleteName * The deleteName to set. */ public void setDeleteName( String[] deleteName ) { this.deleteName = deleteName == null ? new String[0] : deleteName; } /** * @param selectName * The selectName to set. */ public void setSelectName( String[] selectName ) { resizeSelectFields( selectName.length ); for ( int i = 0; i < selectFields.length; i++ ) { selectFields[i].setName( selectName[i] ); } } public String[] getSelectName() { String[] selectName = new String[selectFields.length]; for ( int i = 0; i < selectName.length; i++ ) { selectName[i] = selectFields[i].getName(); } return selectName; } /** * @param selectRename * The selectRename to set. */ public void setSelectRename( String[] selectRename ) { if ( selectRename.length > selectFields.length ) { resizeSelectFields( selectRename.length ); } for ( int i = 0; i < selectFields.length; i++ ) { if ( i < selectRename.length ) { selectFields[i].setRename( selectRename[i] ); } else { selectFields[i].setRename( null ); } } } public String[] getSelectRename() { String[] selectRename = new String[selectFields.length]; for ( int i = 0; i < selectRename.length; i++ ) { selectRename[i] = selectFields[i].getRename(); } return selectRename; } /** * @param selectLength * The selectLength to set. */ public void setSelectLength( int[] selectLength ) { if ( selectLength.length > selectFields.length ) { resizeSelectFields( selectLength.length ); } for ( int i = 0; i < selectFields.length; i++ ) { if ( i < selectLength.length ) { selectFields[i].setLength( selectLength[i] ); } else { selectFields[i].setLength( UNDEFINED ); } } } public int[] getSelectLength() { int[] selectLength = new int[selectFields.length]; for ( int i = 0; i < selectLength.length; i++ ) { selectLength[i] = selectFields[i].getLength(); } return selectLength; } /** * @param selectPrecision * The selectPrecision to set. */ public void setSelectPrecision( int[] selectPrecision ) { if ( selectPrecision.length > selectFields.length ) { resizeSelectFields( selectPrecision.length ); } for ( int i = 0; i < selectFields.length; i++ ) { if ( i < selectPrecision.length ) { selectFields[i].setPrecision( selectPrecision[i] ); } else { selectFields[i].setPrecision( UNDEFINED ); } } } public int[] getSelectPrecision() { int[] selectPrecision = new int[selectFields.length]; for ( int i = 0; i < selectPrecision.length; i++ ) { selectPrecision[i] = selectFields[i].getPrecision(); } return selectPrecision; } private void resizeSelectFields( int length ) { int fillStartIndex = selectFields.length; selectFields = Arrays.copyOf( selectFields, length ); for ( int i = fillStartIndex; i < selectFields.length; i++ ) { selectFields[i] = new SelectField(); selectFields[i].setLength( UNDEFINED ); selectFields[i].setPrecision( UNDEFINED ); } } @Override public void loadXML( Node stepnode, List<DatabaseMeta> databases, IMetaStore metaStore ) throws KettleXMLException { readData( stepnode ); } public void allocate( int nrFields, int nrRemove, int nrMeta ) { allocateSelect( nrFields ); allocateRemove( nrRemove ); allocateMeta( nrMeta ); } private void allocateSelect( int nrFields ) { selectFields = new SelectField[nrFields]; for ( int i = 0; i < nrFields; i++ ) { selectFields[i] = new SelectField(); } } private void allocateRemove( int nrRemove ) { deleteName = new String[nrRemove]; } private void allocateMeta( int nrMeta ) { meta = new SelectMetadataChange[nrMeta]; for ( int i = 0; i < nrMeta; i++ ) { meta[i] = new SelectMetadataChange( this ); } } @Override public Object clone() { SelectValuesMeta retval = (SelectValuesMeta) super.clone(); int nrfields = selectFields == null ? 0 : selectFields.length; int nrremove = deleteName == null ? 0 : deleteName.length; int nrmeta = meta == null ? 0 : meta.length; retval.allocate( nrfields, nrremove, nrmeta ); for ( int i = 0; i < nrfields; i++ ) { retval.getSelectFields()[i] = selectFields[i].clone(); } System.arraycopy( deleteName, 0, retval.deleteName, 0, nrremove ); for ( int i = 0; i < nrmeta; i++ ) { // CHECKSTYLE:Indentation:OFF retval.getMeta()[i] = meta[i].clone(); } return retval; } private void readData( Node step ) throws KettleXMLException { try { Node fields = XMLHandler.getSubNode( step, "fields" ); int nrfields = XMLHandler.countNodes( fields, "field" ); int nrremove = XMLHandler.countNodes( fields, "remove" ); int nrmeta = XMLHandler.countNodes( fields, SelectMetadataChange.XML_TAG ); allocate( nrfields, nrremove, nrmeta ); for ( int i = 0; i < nrfields; i++ ) { Node line = XMLHandler.getSubNodeByNr( fields, "field", i ); selectFields[i] = new SelectField(); selectFields[i].setName( XMLHandler.getTagValue( line, "name" ) ); selectFields[i].setRename( XMLHandler.getTagValue( line, "rename" ) ); selectFields[i].setLength( Const.toInt( XMLHandler.getTagValue( line, "length" ), UNDEFINED ) ); // $NON-NtagLS-1$ selectFields[i].setPrecision( Const.toInt( XMLHandler.getTagValue( line, "precision" ), UNDEFINED ) ); } selectingAndSortingUnspecifiedFields = "Y".equalsIgnoreCase( XMLHandler.getTagValue( fields, "select_unspecified" ) ); for ( int i = 0; i < nrremove; i++ ) { Node line = XMLHandler.getSubNodeByNr( fields, "remove", i ); deleteName[i] = XMLHandler.getTagValue( line, "name" ); } for ( int i = 0; i < nrmeta; i++ ) { Node metaNode = XMLHandler.getSubNodeByNr( fields, SelectMetadataChange.XML_TAG, i ); meta[i] = new SelectMetadataChange( this ); meta[i].loadXML( metaNode ); } } catch ( Exception e ) { throw new KettleXMLException( BaseMessages.getString( PKG, "SelectValuesMeta.Exception.UnableToReadStepInfoFromXML" ), e ); } } @Override public void setDefault() { allocate( 0, 0, 0 ); } public void getSelectFields( RowMetaInterface inputRowMeta, String name ) throws KettleStepException { RowMetaInterface row; if ( selectFields != null && selectFields.length > 0 ) { // SELECT values // 0. Start with an empty row // 1. Keep only the selected values // 2. Rename the selected values // 3. Keep the order in which they are specified... (not the input order!) // row = new RowMeta(); for ( int i = 0; i < selectFields.length; i++ ) { ValueMetaInterface v = inputRowMeta.searchValueMeta( selectFields[i].getName() ); if ( v != null ) { // We found the value v = v.clone(); // Do we need to rename ? if ( !v.getName().equals( selectFields[i].getRename() ) && selectFields[i].getRename() != null && selectFields[i].getRename().length() > 0 ) { v.setName( selectFields[i].getRename() ); v.setOrigin( name ); } if ( selectFields[i].getLength() != UNDEFINED ) { v.setLength( selectFields[i].getLength() ); v.setOrigin( name ); } if ( selectFields[i].getPrecision() != UNDEFINED ) { v.setPrecision( selectFields[i].getPrecision() ); v.setOrigin( name ); } // Add to the resulting row! row.addValueMeta( v ); } } if ( selectingAndSortingUnspecifiedFields ) { // Select the unspecified fields. // Sort the fields // Add them after the specified fields... // List<String> extra = new ArrayList<String>(); for ( int i = 0; i < inputRowMeta.size(); i++ ) { String fieldName = inputRowMeta.getValueMeta( i ).getName(); if ( Const.indexOfString( fieldName, getSelectName() ) < 0 ) { extra.add( fieldName ); } } Collections.sort( extra ); for ( String fieldName : extra ) { ValueMetaInterface extraValue = inputRowMeta.searchValueMeta( fieldName ); row.addValueMeta( extraValue ); } } // OK, now remove all from r and re-add row: inputRowMeta.clear(); inputRowMeta.addRowMeta( row ); } } public void getDeleteFields( RowMetaInterface inputRowMeta ) throws KettleStepException { if ( deleteName != null && deleteName.length > 0 ) { // DESELECT values from the stream... for ( int i = 0; i < deleteName.length; i++ ) { try { inputRowMeta.removeValueMeta( deleteName[i] ); } catch ( KettleValueException e ) { throw new KettleStepException( e ); } } } } public void getMetadataFields( RowMetaInterface inputRowMeta, String name ) throws KettlePluginException { if ( meta != null && meta.length > 0 ) { // METADATA mode: change the meta-data of the values mentioned... for ( int i = 0; i < meta.length; i++ ) { SelectMetadataChange metaChange = meta[i]; int idx = inputRowMeta.indexOfValue( metaChange.getName() ); if ( idx >= 0 ) { // We found the value // This is the value we need to change: ValueMetaInterface v = inputRowMeta.getValueMeta( idx ); // Do we need to rename ? if ( !v.getName().equals( metaChange.getRename() ) && !Utils.isEmpty( metaChange.getRename() ) ) { v.setName( metaChange.getRename() ); v.setOrigin( name ); } // Change the type? if ( metaChange.getType() != ValueMetaInterface.TYPE_NONE && v.getType() != metaChange.getType() ) { v = ValueMetaFactory.cloneValueMeta( v, metaChange.getType() ); // This is now a copy, replace it in the row! // inputRowMeta.setValueMeta( idx, v ); // This also moves the data to normal storage type // v.setStorageType( ValueMetaInterface.STORAGE_TYPE_NORMAL ); } if ( metaChange.getLength() != UNDEFINED ) { v.setLength( metaChange.getLength() ); v.setOrigin( name ); } if ( metaChange.getPrecision() != UNDEFINED ) { v.setPrecision( metaChange.getPrecision() ); v.setOrigin( name ); } if ( metaChange.getStorageType() >= 0 ) { v.setStorageType( metaChange.getStorageType() ); v.setOrigin( name ); } if ( !Utils.isEmpty( metaChange.getConversionMask() ) ) { v.setConversionMask( metaChange.getConversionMask() ); v.setOrigin( name ); } v.setDateFormatLenient( metaChange.isDateFormatLenient() ); v.setDateFormatLocale( EnvUtil.createLocale( metaChange.getDateFormatLocale() ) ); v.setDateFormatTimeZone( EnvUtil.createTimeZone( metaChange.getDateFormatTimeZone() ) ); v.setLenientStringToNumber( metaChange.isLenientStringToNumber() ); if ( !Utils.isEmpty( metaChange.getEncoding() ) ) { v.setStringEncoding( metaChange.getEncoding() ); v.setOrigin( name ); } if ( !Utils.isEmpty( metaChange.getDecimalSymbol() ) ) { v.setDecimalSymbol( metaChange.getDecimalSymbol() ); v.setOrigin( name ); } if ( !Utils.isEmpty( metaChange.getGroupingSymbol() ) ) { v.setGroupingSymbol( metaChange.getGroupingSymbol() ); v.setOrigin( name ); } if ( !Utils.isEmpty( metaChange.getCurrencySymbol() ) ) { v.setCurrencySymbol( metaChange.getCurrencySymbol() ); v.setOrigin( name ); } } } } } @Override public void getFields( RowMetaInterface inputRowMeta, String name, RowMetaInterface[] info, StepMeta nextStep, VariableSpace space, Repository repository, IMetaStore metaStore ) throws KettleStepException { try { RowMetaInterface rowMeta = inputRowMeta.clone(); inputRowMeta.clear(); inputRowMeta.addRowMeta( rowMeta ); getSelectFields( inputRowMeta, name ); getDeleteFields( inputRowMeta ); getMetadataFields( inputRowMeta, name ); } catch ( Exception e ) { throw new KettleStepException( e ); } } @Override public String getXML() { StringBuilder retval = new StringBuilder( 300 ); retval.append( " <fields>" ); for ( int i = 0; i < selectFields.length; i++ ) { retval.append( " <field>" ); retval.append( " " ).append( XMLHandler.addTagValue( getXmlCode( "FIELD_NAME" ), selectFields[i] .getName() ) ); if ( selectFields[i].getRename() != null ) { retval.append( " " ).append( XMLHandler.addTagValue( getXmlCode( "FIELD_RENAME" ), selectFields[i] .getRename() ) ); } if ( selectFields[i].getPrecision() > 0 ) { retval.append( " " ).append( XMLHandler.addTagValue( getXmlCode( "FIELD_LENGTH" ), selectFields[i] .getLength() ) ); } if ( selectFields[i].getPrecision() > 0 ) { retval.append( " " ).append( XMLHandler.addTagValue( getXmlCode( "FIELD_PRECISION" ), selectFields[i] .getPrecision() ) ); } retval.append( " </field>" ); } retval.append( " " ).append( XMLHandler.addTagValue( getXmlCode( "SELECT_UNSPECIFIED" ), selectingAndSortingUnspecifiedFields ) ); for ( int i = 0; i < deleteName.length; i++ ) { retval.append( " <remove>" ); retval.append( " " ).append( XMLHandler.addTagValue( getXmlCode( "REMOVE_NAME" ), deleteName[i] ) ); retval.append( " </remove>" ); } for ( int i = 0; i < meta.length; i++ ) { retval.append( meta[i].getXML() ); } retval.append( " </fields>" ); return retval.toString(); } @Override public void readRep( Repository rep, IMetaStore metaStore, ObjectId id_step, List<DatabaseMeta> databases ) throws KettleException { try { int nrfields = rep.countNrStepAttributes( id_step, getRepCode( "FIELD_NAME" ) ); int nrremove = rep.countNrStepAttributes( id_step, getRepCode( "REMOVE_NAME" ) ); int nrmeta = rep.countNrStepAttributes( id_step, getRepCode( "META_NAME" ) ); allocate( nrfields, nrremove, nrmeta ); for ( int i = 0; i < nrfields; i++ ) { selectFields[i].setName( rep.getStepAttributeString( id_step, i, getRepCode( "FIELD_NAME" ) ) ); selectFields[i].setRename( rep.getStepAttributeString( id_step, i, getRepCode( "FIELD_RENAME" ) ) ); selectFields[i].setLength( (int) rep.getStepAttributeInteger( id_step, i, getRepCode( "FIELD_LENGTH" ) ) ); selectFields[i].setPrecision( (int) rep.getStepAttributeInteger( id_step, i, getRepCode( "FIELD_PRECISION" ) ) ); } selectingAndSortingUnspecifiedFields = rep.getStepAttributeBoolean( id_step, getRepCode( "SELECT_UNSPECIFIED" ) ); for ( int i = 0; i < nrremove; i++ ) { deleteName[i] = rep.getStepAttributeString( id_step, i, getRepCode( "REMOVE_NAME" ) ); } for ( int i = 0; i < nrmeta; i++ ) { meta[i] = new SelectMetadataChange( this ); meta[i].setName( rep.getStepAttributeString( id_step, i, getRepCode( "META_NAME" ) ) ); meta[i].setRename( rep.getStepAttributeString( id_step, i, getRepCode( "META_RENAME" ) ) ); meta[i].setType( (int) rep.getStepAttributeInteger( id_step, i, getRepCode( "META_TYPE" ) ) ); meta[i].setLength( (int) rep.getStepAttributeInteger( id_step, i, getRepCode( "META_LENGTH" ) ) ); meta[i].setPrecision( (int) rep.getStepAttributeInteger( id_step, i, getRepCode( "META_PRECISION" ) ) ); meta[i].setStorageType( ValueMetaBase.getStorageType( rep.getStepAttributeString( id_step, i, getRepCode( "META_STORAGE_TYPE" ) ) ) ); meta[i].setConversionMask( rep.getStepAttributeString( id_step, i, getRepCode( "META_CONVERSION_MASK" ) ) ); meta[i].setDateFormatLenient( Boolean.parseBoolean( rep.getStepAttributeString( id_step, i, getRepCode( "META_DATE_FORMAT_LENIENT" ) ) ) ); meta[i].setDateFormatLocale( rep.getStepAttributeString( id_step, i, getRepCode( "META_DATE_FORMAT_LOCALE" ) ) ); meta[i].setDateFormatTimeZone( rep.getStepAttributeString( id_step, i, getRepCode( "META_DATE_FORMAT_TIMEZONE" ) ) ); meta[i].setLenientStringToNumber( Boolean.parseBoolean( rep.getStepAttributeString( id_step, i, getRepCode( "META_LENIENT_STRING_TO_NUMBER" ) ) ) ); meta[i].setDecimalSymbol( rep.getStepAttributeString( id_step, i, getRepCode( "META_DECIMAL" ) ) ); meta[i].setGroupingSymbol( rep.getStepAttributeString( id_step, i, getRepCode( "META_GROUPING" ) ) ); meta[i].setCurrencySymbol( rep.getStepAttributeString( id_step, i, getRepCode( "META_CURRENCY" ) ) ); meta[i].setEncoding( rep.getStepAttributeString( id_step, i, getRepCode( "META_ENCODING" ) ) ); } } catch ( Exception e ) { throw new KettleException( BaseMessages.getString( PKG, "SelectValuesMeta.Exception.UnexpectedErrorReadingStepInfoFromRepository" ), e ); } } @Override public void saveRep( Repository rep, IMetaStore metaStore, ObjectId id_transformation, ObjectId id_step ) throws KettleException { try { for ( int i = 0; i < selectFields.length; i++ ) { rep.saveStepAttribute( id_transformation, id_step, i, getRepCode( "FIELD_NAME" ), selectFields[i].getName() ); rep.saveStepAttribute( id_transformation, id_step, i, getRepCode( "FIELD_RENAME" ), selectFields[i] .getRename() ); rep.saveStepAttribute( id_transformation, id_step, i, getRepCode( "FIELD_LENGTH" ), selectFields[i] .getLength() ); rep.saveStepAttribute( id_transformation, id_step, i, getRepCode( "FIELD_PRECISION" ), selectFields[i] .getPrecision() ); } rep.saveStepAttribute( id_transformation, id_step, getRepCode( "SELECT_UNSPECIFIED" ), selectingAndSortingUnspecifiedFields ); for ( int i = 0; i < deleteName.length; i++ ) { rep.saveStepAttribute( id_transformation, id_step, i, getRepCode( "REMOVE_NAME" ), deleteName[i] ); } for ( int i = 0; i < meta.length; i++ ) { rep.saveStepAttribute( id_transformation, id_step, i, getRepCode( "META_NAME" ), meta[i].getName() ); rep.saveStepAttribute( id_transformation, id_step, i, getRepCode( "META_RENAME" ), meta[i].getRename() ); rep.saveStepAttribute( id_transformation, id_step, i, getRepCode( "META_TYPE" ), meta[i].getType() ); rep.saveStepAttribute( id_transformation, id_step, i, getRepCode( "META_LENGTH" ), meta[i].getLength() ); rep.saveStepAttribute( id_transformation, id_step, i, getRepCode( "META_PRECISION" ), meta[i].getPrecision() ); rep.saveStepAttribute( id_transformation, id_step, i, getRepCode( "META_STORAGE_TYPE" ), ValueMetaBase .getStorageTypeCode( meta[i].getStorageType() ) ); rep.saveStepAttribute( id_transformation, id_step, i, getRepCode( "META_CONVERSION_MASK" ), meta[i] .getConversionMask() ); rep.saveStepAttribute( id_transformation, id_step, i, getRepCode( "META_DATE_FORMAT_LENIENT" ), Boolean .toString( meta[i].isDateFormatLenient() ) ); rep.saveStepAttribute( id_transformation, id_step, i, getRepCode( "META_DATE_FORMAT_LOCALE" ), meta[i] .getDateFormatLocale() == null ? null : meta[i].getDateFormatLocale().toString() ); rep.saveStepAttribute( id_transformation, id_step, i, getRepCode( "META_DATE_FORMAT_TIMEZONE" ), meta[i] .getDateFormatTimeZone() == null ? null : meta[i].getDateFormatTimeZone().toString() ); rep.saveStepAttribute( id_transformation, id_step, i, getRepCode( "META_LENIENT_STRING_TO_NUMBER" ), Boolean .toString( meta[i].isLenientStringToNumber() ) ); rep.saveStepAttribute( id_transformation, id_step, i, getRepCode( "META_DECIMAL" ), meta[i] .getDecimalSymbol() ); rep.saveStepAttribute( id_transformation, id_step, i, getRepCode( "META_GROUPING" ), meta[i] .getGroupingSymbol() ); rep.saveStepAttribute( id_transformation, id_step, i, getRepCode( "META_CURRENCY" ), meta[i] .getCurrencySymbol() ); rep.saveStepAttribute( id_transformation, id_step, i, getRepCode( "META_ENCODING" ), meta[i].getEncoding() ); } } catch ( Exception e ) { throw new KettleException( BaseMessages.getString( PKG, "SelectValuesMeta.Exception.UnableToSaveStepInfoToRepository" ) + id_step, e ); } } @Override public void check( List<CheckResultInterface> remarks, TransMeta transMeta, StepMeta stepMeta, 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_OK, BaseMessages.getString( PKG, "SelectValuesMeta.CheckResult.StepReceivingFields", prev.size() + "" ), stepMeta ); remarks.add( cr ); /* * Take care of the normal SELECT fields... */ String error_message = ""; boolean error_found = false; // Starting from selected fields in ... for ( int i = 0; i < this.selectFields.length; i++ ) { int idx = prev.indexOfValue( selectFields[i].getName() ); if ( idx < 0 ) { error_message += "\t\t" + selectFields[i].getName() + Const.CR; error_found = true; } } if ( error_found ) { error_message = BaseMessages.getString( PKG, "SelectValuesMeta.CheckResult.SelectedFieldsNotFound" ) + Const.CR + Const.CR + error_message; cr = new CheckResult( CheckResultInterface.TYPE_RESULT_ERROR, error_message, stepMeta ); remarks.add( cr ); } else { cr = new CheckResult( CheckResultInterface.TYPE_RESULT_OK, BaseMessages.getString( PKG, "SelectValuesMeta.CheckResult.AllSelectedFieldsFound" ), stepMeta ); remarks.add( cr ); } if ( this.selectFields.length > 0 ) { // Starting from prev... for ( int i = 0; i < prev.size(); i++ ) { ValueMetaInterface pv = prev.getValueMeta( i ); int idx = Const.indexOfString( pv.getName(), getSelectName() ); if ( idx < 0 ) { error_message += "\t\t" + pv.getName() + " (" + pv.getTypeDesc() + ")" + Const.CR; error_found = true; } } if ( error_found ) { error_message = BaseMessages.getString( PKG, "SelectValuesMeta.CheckResult.FieldsNotFound" ) + Const.CR + Const.CR + error_message; cr = new CheckResult( CheckResultInterface.TYPE_RESULT_COMMENT, error_message, stepMeta ); remarks.add( cr ); } else { cr = new CheckResult( CheckResultInterface.TYPE_RESULT_OK, BaseMessages.getString( PKG, "SelectValuesMeta.CheckResult.AllSelectedFieldsFound2" ), stepMeta ); remarks.add( cr ); } } /* * How about the DE-SELECT (remove) fields... */ error_message = ""; error_found = false; // Starting from selected fields in ... for ( int i = 0; i < this.deleteName.length; i++ ) { int idx = prev.indexOfValue( deleteName[i] ); if ( idx < 0 ) { error_message += "\t\t" + deleteName[i] + Const.CR; error_found = true; } } if ( error_found ) { error_message = BaseMessages.getString( PKG, "SelectValuesMeta.CheckResult.DeSelectedFieldsNotFound" ) + Const.CR + Const.CR + error_message; cr = new CheckResult( CheckResultInterface.TYPE_RESULT_ERROR, error_message, stepMeta ); remarks.add( cr ); } else { cr = new CheckResult( CheckResultInterface.TYPE_RESULT_OK, BaseMessages.getString( PKG, "SelectValuesMeta.CheckResult.AllDeSelectedFieldsFound" ), stepMeta ); remarks.add( cr ); } /* * How about the Meta-fields...? */ error_message = ""; error_found = false; // Starting from selected fields in ... for ( int i = 0; i < this.meta.length; i++ ) { int idx = prev.indexOfValue( this.meta[i].getName() ); if ( idx < 0 ) { error_message += "\t\t" + this.meta[i].getName() + Const.CR; error_found = true; } } if ( error_found ) { error_message = BaseMessages.getString( PKG, "SelectValuesMeta.CheckResult.MetadataFieldsNotFound" ) + Const.CR + Const.CR + error_message; cr = new CheckResult( CheckResultInterface.TYPE_RESULT_ERROR, error_message, stepMeta ); remarks.add( cr ); } else { cr = new CheckResult( CheckResultInterface.TYPE_RESULT_OK, BaseMessages.getString( PKG, "SelectValuesMeta.CheckResult.AllMetadataFieldsFound" ), stepMeta ); remarks.add( cr ); } } else { cr = new CheckResult( CheckResultInterface.TYPE_RESULT_ERROR, BaseMessages.getString( PKG, "SelectValuesMeta.CheckResult.FieldsNotFound2" ), stepMeta ); 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, "SelectValuesMeta.CheckResult.StepReceivingInfoFromOtherSteps" ), stepMeta ); remarks.add( cr ); } else { cr = new CheckResult( CheckResultInterface.TYPE_RESULT_ERROR, BaseMessages.getString( PKG, "SelectValuesMeta.CheckResult.NoInputReceivedError" ), stepMeta ); remarks.add( cr ); } // Check for doubles in the selected fields... int[] cnt = new int[selectFields.length]; boolean error_found = false; String error_message = ""; for ( int i = 0; i < selectFields.length; i++ ) { cnt[i] = 0; for ( int j = 0; j < selectFields.length; j++ ) { if ( selectFields[i].getName().equals( selectFields[j].getName() ) ) { cnt[i]++; } } if ( cnt[i] > 1 ) { if ( !error_found ) { // first time... error_message = BaseMessages.getString( PKG, "SelectValuesMeta.CheckResult.DuplicateFieldsSpecified" ) + Const.CR; } else { error_found = true; } error_message += BaseMessages.getString( PKG, "SelectValuesMeta.CheckResult.OccurentRow", i + " : " + selectFields[i] .getName() + " (" + cnt[i] ) + Const.CR; error_found = true; } } if ( error_found ) { cr = new CheckResult( CheckResultInterface.TYPE_RESULT_ERROR, error_message, stepMeta ); remarks.add( cr ); } } @Override public StepInterface getStep( StepMeta stepMeta, StepDataInterface stepDataInterface, int cnr, TransMeta transMeta, Trans trans ) { return new SelectValues( stepMeta, stepDataInterface, cnr, transMeta, trans ); } @Override public StepDataInterface getStepData() { return new SelectValuesData(); } /** * @return the selectingAndSortingUnspecifiedFields */ public boolean isSelectingAndSortingUnspecifiedFields() { return selectingAndSortingUnspecifiedFields; } /** * @param selectingAndSortingUnspecifiedFields * the selectingAndSortingUnspecifiedFields to set */ public void setSelectingAndSortingUnspecifiedFields( boolean selectingAndSortingUnspecifiedFields ) { this.selectingAndSortingUnspecifiedFields = selectingAndSortingUnspecifiedFields; } /** * @return the meta */ public SelectMetadataChange[] getMeta() { return meta; } /** * @param meta * the meta to set */ public void setMeta( SelectMetadataChange[] meta ) { this.meta = meta == null ? new SelectMetadataChange[0] : meta; } @Override public boolean supportsErrorHandling() { return true; } public SelectField[] getSelectFields() { return selectFields; } public void setSelectFields( SelectField[] selectFields ) { this.selectFields = selectFields == null ? new SelectField[0] : selectFields; } /** * We will describe in which way the field names change between input and output in this step. * * @return The list of field name lineage objects */ public List<FieldnameLineage> getFieldnameLineage() { List<FieldnameLineage> lineages = new ArrayList<FieldnameLineage>(); // Select values... // for ( int i = 0; i < selectFields.length; i++ ) { String input = selectFields[i].getName(); String output = selectFields[i].getRename(); // See if the select tab renames a column! // if ( !Utils.isEmpty( output ) && !input.equalsIgnoreCase( output ) ) { // Yes, add it to the list // lineages.add( new FieldnameLineage( input, output ) ); } } // Metadata // for ( int i = 0; i < getMeta().length; i++ ) { String input = getMeta()[i].getName(); String output = getMeta()[i].getRename(); // See if the select tab renames a column! // if ( !Utils.isEmpty( output ) && !input.equalsIgnoreCase( output ) ) { // See if the input is not the output of a row in the Select tab // int idx = Const.indexOfString( input, getSelectRename() ); if ( idx < 0 ) { // nothing special, add it to the list // lineages.add( new FieldnameLineage( input, output ) ); } else { // Modify the existing field name lineage entry // FieldnameLineage lineage = FieldnameLineage.findFieldnameLineageWithInput( lineages, input ); lineage.setOutputFieldname( output ); } } } return lineages; } public static class SelectField implements Cloneable { /** Select: Name of the selected field */ @Injection( name = "FIELD_NAME", group = "FIELDS" ) private String name; /** Select: Rename to ... */ @Injection( name = "FIELD_RENAME", group = "FIELDS" ) private String rename; /** Select: length of field */ @Injection( name = "FIELD_LENGTH", group = "FIELDS" ) private int length; /** Select: Precision of field (for numbers) */ @Injection( name = "FIELD_PRECISION", group = "FIELDS" ) private int precision; public String getName() { return name; } public void setName( String name ) { this.name = name; } public String getRename() { return rename; } public void setRename( String rename ) { this.rename = rename; } public int getLength() { return length; } public void setLength( int length ) { this.length = length; } public int getPrecision() { return precision; } public void setPrecision( int precision ) { this.precision = precision; } @Override public SelectField clone() { try { return (SelectField) super.clone(); } catch ( CloneNotSupportedException e ) { throw new RuntimeException( e ); } } } }