/*! ******************************************************************************
*
* Pentaho Data Integration
*
* Copyright (C) 2002-2013 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.sapinput;
import java.util.ArrayList;
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.ValueMetaInterface;
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;
import org.pentaho.di.trans.steps.sapinput.sap.SAPConnectionFactory;
import org.pentaho.di.trans.steps.sapinput.sap.SAPException;
import org.pentaho.di.trans.steps.sapinput.sap.SAPField;
import org.pentaho.di.trans.steps.sapinput.sap.SAPRow;
import org.pentaho.di.trans.steps.sapinput.sap.impl.SAPRowIterator;
/**
* Reads information from a database table by using freehand SQL
*
* @author Matt
* @since 8-apr-2003
*/
public class SapInput extends BaseStep implements StepInterface {
private static Class<?> PKG = SapInputMeta.class; // for i18n purposes, needed by Translator2!!
private SapInputMeta meta;
private SapInputData data;
public SapInput( StepMeta stepMeta, StepDataInterface stepDataInterface, int copyNr, TransMeta transMeta,
Trans trans ) {
super( stepMeta, stepDataInterface, copyNr, transMeta, trans );
}
public boolean processRow( StepMetaInterface smi, StepDataInterface sdi ) throws KettleException {
Object[] r = getRow();
if ( r == null ) { // no more input to be expected...
setOutputDone();
return false;
}
if ( first ) {
first = false;
// Determine the output row metadata of this step
//
data.outputRowMeta = new RowMeta();
meta.getFields( data.outputRowMeta, getStepname(), null, null, this, repository, metaStore );
// Pre-calculate the indexes of the parameters for performance reasons...
//
data.parameterIndexes = new ArrayList<Integer>();
for ( SapParameter parameter : meta.getParameters() ) {
int index = getInputRowMeta().indexOfValue( parameter.getFieldName() );
if ( index < 0 ) {
throw new KettleException( "Unable to find field '" + parameter.getFieldName() + "'" );
}
data.parameterIndexes.add( index );
}
// Pre-calculate the output fields
//
data.output = new ArrayList<SAPField>();
for ( SapOutputField outputField : meta.getOutputFields() ) {
SAPField field =
new SAPField( outputField.getSapFieldName(), outputField.getTableName(), "output_"
+ outputField.getSapType().getDescription() );
data.output.add( field );
}
}
// Assemble the list of input fields for the SAP function execution...
//
ArrayList<SAPField> input = new ArrayList<SAPField>();
for ( int i = 0; i < meta.getParameters().size(); i++ ) {
SapParameter parameter = meta.getParameters().get( i );
int fieldIndex = data.parameterIndexes.get( i );
ValueMetaInterface valueMeta = getInputRowMeta().getValueMeta( fieldIndex );
Object value = valueMeta.convertToNormalStorageType( r[fieldIndex] );
// TODO: figure out if the executeFunction needs the data to be in a specific data type or format!!
// If so, value needs to be converted to the appropriate data type here.
SAPField field =
new SAPField( parameter.getParameterName(), parameter.getTableName(), "input_"
+ parameter.getSapType().getDescription(), value );
input.add( field );
}
// Get the output...
//
SAPRowIterator resultSet;
try {
resultSet = data.sapConnection.executeFunctionCursored( meta.getFunction(), input, data.output );
} catch ( SAPException e ) {
throw new KettleException( e );
}
while ( resultSet.hasNext() ) {
SAPRow sapRow = resultSet.next();
Object[] outputRowData = RowDataUtil.allocateRowData( data.outputRowMeta.size() );
int outputIndex = 0; // Makes it easier to add all sorts of fields later on, like row number, input fields, etc.
for ( SAPField field : sapRow.getFields() ) {
// TODO: Here we should check as well whether or not the correct data types are delivered from SAP.
// Make sure that we don't pass the appropriate data types : String, long, double, Date, BigDecimal, Boolean,
// byte[] ONLY!!
//
outputRowData[outputIndex++] = field.getValue();
}
// Pass the row along: row metadata and data need to correspond!!
//
putRow( data.outputRowMeta, outputRowData );
if ( getTrans().isStopped() ) {
break;
}
}
return true;
}
public void dispose( StepMetaInterface smi, StepDataInterface sdi ) {
if ( data.sapConnection != null ) {
data.sapConnection.close();
}
super.dispose( smi, sdi );
}
public boolean init( StepMetaInterface smi, StepDataInterface sdi ) {
meta = (SapInputMeta) smi;
data = (SapInputData) sdi;
if ( super.init( smi, sdi ) ) {
// Verify some basic things first...
//
boolean passed = true;
if ( meta.getFunction() == null ) {
logError( BaseMessages.getString( PKG, "SapInput.Exception.FunctionIsNeeded" ) );
passed = false;
}
if ( meta.getDatabaseMeta() == null ) {
logError( BaseMessages.getString( PKG, "SapInput.Exception.DatabaseConnectionsIsNeeded" ) );
passed = false;
}
if ( !passed ) {
return false;
}
try {
data.sapConnection = SAPConnectionFactory.create();
data.sapConnection.open( meta.getDatabaseMeta() );
return true;
} catch ( SAPException e ) {
logError( "An error occurred while connecting to SAP ERP, processing will be stopped:", e );
setErrors( 1 );
stopAll();
}
}
return false;
}
}