/*! ******************************************************************************
*
* 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.constant;
import java.math.BigDecimal;
import java.sql.Timestamp;
import java.util.ArrayList;
import java.util.List;
import org.pentaho.di.core.CheckResult;
import org.pentaho.di.core.CheckResultInterface;
import org.pentaho.di.core.RowMetaAndData;
import org.pentaho.di.core.exception.KettleException;
import org.pentaho.di.core.row.RowDataUtil;
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.ValueMetaFactory;
import org.pentaho.di.core.util.StringUtil;
import org.pentaho.di.i18n.BaseMessages;
import org.pentaho.di.trans.Trans;
import org.pentaho.di.trans.TransMeta;
import org.pentaho.di.trans.step.BaseStep;
import org.pentaho.di.trans.step.StepDataInterface;
import org.pentaho.di.trans.step.StepInterface;
import org.pentaho.di.trans.step.StepMeta;
import org.pentaho.di.trans.step.StepMetaInterface;
/**
* Generates a number of (empty or the same) rows
*
* @author Matt
* @since 4-apr-2003
*/
public class Constant extends BaseStep implements StepInterface {
private static Class<?> PKG = ConstantMeta.class; // for i18n purposes, needed by Translator2!!
private ConstantMeta meta;
private ConstantData data;
public Constant( StepMeta stepMeta, StepDataInterface stepDataInterface, int copyNr, TransMeta transMeta,
Trans trans ) {
super( stepMeta, stepDataInterface, copyNr, transMeta, trans );
meta = (ConstantMeta) getStepMeta().getStepMetaInterface();
data = (ConstantData) stepDataInterface;
}
public static final RowMetaAndData buildRow( ConstantMeta meta, ConstantData data,
List<CheckResultInterface> remarks ) {
RowMetaInterface rowMeta = new RowMeta();
Object[] rowData = new Object[meta.getFieldName().length];
for ( int i = 0; i < meta.getFieldName().length; i++ ) {
int valtype = ValueMetaFactory.getIdForValueMeta( meta.getFieldType()[i] );
if ( meta.getFieldName()[i] != null ) {
ValueMetaInterface value = null;
try {
value = ValueMetaFactory.createValueMeta( meta.getFieldName()[i], valtype );
} catch ( Exception exception ) {
remarks.add( new CheckResult( CheckResultInterface.TYPE_RESULT_ERROR, exception.getMessage(), null ) );
continue;
}
value.setLength( meta.getFieldLength()[i] );
value.setPrecision( meta.getFieldPrecision()[i] );
if ( meta.isSetEmptyString()[i] ) {
// Just set empty string
rowData[i] = StringUtil.EMPTY_STRING;
} else {
String stringValue = meta.getValue()[i];
// If the value is empty: consider it to be NULL.
if ( stringValue == null || stringValue.length() == 0 ) {
rowData[i] = null;
if ( value.getType() == ValueMetaInterface.TYPE_NONE ) {
String message =
BaseMessages.getString(
PKG, "Constant.CheckResult.SpecifyTypeError", value.getName(), stringValue );
remarks.add( new CheckResult( CheckResultInterface.TYPE_RESULT_ERROR, message, null ) );
}
} else {
switch ( value.getType() ) {
case ValueMetaInterface.TYPE_NUMBER:
try {
if ( meta.getFieldFormat()[i] != null
|| meta.getDecimal()[i] != null || meta.getGroup()[i] != null
|| meta.getCurrency()[i] != null ) {
if ( meta.getFieldFormat()[i] != null && meta.getFieldFormat()[i].length() >= 1 ) {
data.df.applyPattern( meta.getFieldFormat()[i] );
}
if ( meta.getDecimal()[i] != null && meta.getDecimal()[i].length() >= 1 ) {
data.dfs.setDecimalSeparator( meta.getDecimal()[i].charAt( 0 ) );
}
if ( meta.getGroup()[i] != null && meta.getGroup()[i].length() >= 1 ) {
data.dfs.setGroupingSeparator( meta.getGroup()[i].charAt( 0 ) );
}
if ( meta.getCurrency()[i] != null && meta.getCurrency()[i].length() >= 1 ) {
data.dfs.setCurrencySymbol( meta.getCurrency()[i] );
}
data.df.setDecimalFormatSymbols( data.dfs );
}
rowData[i] = new Double( data.nf.parse( stringValue ).doubleValue() );
} catch ( Exception e ) {
String message =
BaseMessages.getString(
PKG, "Constant.BuildRow.Error.Parsing.Number", value.getName(), stringValue, e
.toString() );
remarks.add( new CheckResult( CheckResultInterface.TYPE_RESULT_ERROR, message, null ) );
}
break;
case ValueMetaInterface.TYPE_STRING:
rowData[i] = stringValue;
break;
case ValueMetaInterface.TYPE_DATE:
try {
if ( meta.getFieldFormat()[i] != null ) {
data.daf.applyPattern( meta.getFieldFormat()[i] );
data.daf.setDateFormatSymbols( data.dafs );
}
rowData[i] = data.daf.parse( stringValue );
} catch ( Exception e ) {
String message =
BaseMessages.getString(
PKG, "Constant.BuildRow.Error.Parsing.Date", value.getName(), stringValue, e.toString() );
remarks.add( new CheckResult( CheckResultInterface.TYPE_RESULT_ERROR, message, null ) );
}
break;
case ValueMetaInterface.TYPE_INTEGER:
try {
rowData[i] = new Long( Long.parseLong( stringValue ) );
} catch ( Exception e ) {
String message =
BaseMessages.getString(
PKG, "Constant.BuildRow.Error.Parsing.Integer", value.getName(), stringValue, e
.toString() );
remarks.add( new CheckResult( CheckResultInterface.TYPE_RESULT_ERROR, message, null ) );
}
break;
case ValueMetaInterface.TYPE_BIGNUMBER:
try {
rowData[i] = new BigDecimal( stringValue );
} catch ( Exception e ) {
String message =
BaseMessages.getString(
PKG, "Constant.BuildRow.Error.Parsing.BigNumber", value.getName(), stringValue, e
.toString() );
remarks.add( new CheckResult( CheckResultInterface.TYPE_RESULT_ERROR, message, null ) );
}
break;
case ValueMetaInterface.TYPE_BOOLEAN:
rowData[i] =
Boolean
.valueOf( "Y".equalsIgnoreCase( stringValue ) || "TRUE".equalsIgnoreCase( stringValue ) );
break;
case ValueMetaInterface.TYPE_BINARY:
rowData[i] = stringValue.getBytes();
break;
case ValueMetaInterface.TYPE_TIMESTAMP:
try {
rowData[i] = Timestamp.valueOf( stringValue );
} catch ( Exception e ) {
String message =
BaseMessages.getString(
PKG, "Constant.BuildRow.Error.Parsing.Timestamp", value.getName(), stringValue, e
.toString() );
remarks.add( new CheckResult( CheckResultInterface.TYPE_RESULT_ERROR, message, null ) );
}
break;
default:
String message =
BaseMessages.getString(
PKG, "Constant.CheckResult.SpecifyTypeError", value.getName(), stringValue );
remarks.add( new CheckResult( CheckResultInterface.TYPE_RESULT_ERROR, message, null ) );
}
}
}
// Now add value to the row!
// This is in fact a copy from the fields row, but now with data.
rowMeta.addValueMeta( value );
} // end if
} // end for
return new RowMetaAndData( rowMeta, rowData );
}
@Override
public boolean processRow( StepMetaInterface smi, StepDataInterface sdi ) throws KettleException {
Object[] r = null;
r = getRow();
if ( r == null ) { // no more rows to be expected from the previous step(s)
setOutputDone();
return false;
}
if ( data.firstRow ) {
// The output meta is the original input meta + the
// additional constant fields.
data.firstRow = false;
data.outputMeta = getInputRowMeta().clone();
RowMetaInterface constants = data.constants.getRowMeta();
data.outputMeta.mergeRowMeta( constants );
}
// Add the constant data to the end of the row.
r = RowDataUtil.addRowData( r, getInputRowMeta().size(), data.constants.getData() );
putRow( data.outputMeta, r );
if ( log.isRowLevel() ) {
logRowlevel( BaseMessages.getString(
PKG, "Constant.Log.Wrote.Row", Long.toString( getLinesWritten() ), getInputRowMeta().getString( r ) ) );
}
if ( checkFeedback( getLinesWritten() ) ) {
if ( log.isBasic() ) {
logBasic( BaseMessages.getString( PKG, "Constant.Log.LineNr", Long.toString( getLinesWritten() ) ) );
}
}
return true;
}
@Override
public boolean init( StepMetaInterface smi, StepDataInterface sdi ) {
meta = (ConstantMeta) smi;
data = (ConstantData) sdi;
data.firstRow = true;
if ( super.init( smi, sdi ) ) {
// Create a row (constants) with all the values in it...
List<CheckResultInterface> remarks = new ArrayList<CheckResultInterface>(); // stores the errors...
data.constants = buildRow( meta, data, remarks );
if ( remarks.isEmpty() ) {
return true;
} else {
for ( int i = 0; i < remarks.size(); i++ ) {
CheckResultInterface cr = remarks.get( i );
logError( cr.getText() );
}
}
}
return false;
}
}