/*! ******************************************************************************
*
* 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.formula;
import java.math.BigDecimal;
import java.util.Date;
import java.util.Hashtable;
import java.util.Map;
import org.pentaho.di.core.exception.KettleValueException;
import org.pentaho.di.core.row.RowMetaInterface;
import org.pentaho.di.core.row.ValueMetaInterface;
import org.pentaho.reporting.libraries.base.config.Configuration;
import org.pentaho.reporting.libraries.formula.DefaultFormulaContext;
import org.pentaho.reporting.libraries.formula.ErrorValue;
import org.pentaho.reporting.libraries.formula.EvaluationException;
import org.pentaho.reporting.libraries.formula.FormulaContext;
import org.pentaho.reporting.libraries.formula.LibFormulaErrorValue;
import org.pentaho.reporting.libraries.formula.LocalizationContext;
import org.pentaho.reporting.libraries.formula.function.FunctionRegistry;
import org.pentaho.reporting.libraries.formula.operators.OperatorFactory;
import org.pentaho.reporting.libraries.formula.typing.Type;
import org.pentaho.reporting.libraries.formula.typing.TypeRegistry;
import org.pentaho.reporting.libraries.formula.typing.coretypes.AnyType;
public class RowForumulaContext implements FormulaContext {
private RowMetaInterface rowMeta;
private FormulaContext formulaContext;
private Map<String, Integer> valueIndexMap;
private Object[] rowData;
public RowForumulaContext( RowMetaInterface row ) {
this.formulaContext = new DefaultFormulaContext();
this.rowMeta = row;
this.rowData = null;
this.valueIndexMap = new Hashtable<String, Integer>();
}
public Type resolveReferenceType( Object name ) {
return AnyType.TYPE;
}
/**
* We return the content of a Value with the given name. We cache the position of the field indexes.
*
* @see org.jfree.formula.FormulaContext#resolveReference(java.lang.Object)
*/
public Object resolveReference( Object name ) throws EvaluationException {
if ( name instanceof String ) {
ValueMetaInterface valueMeta;
Integer idx = valueIndexMap.get( name );
if ( idx != null ) {
valueMeta = rowMeta.getValueMeta( idx.intValue() );
} else {
int index = rowMeta.indexOfValue( (String) name );
if ( index < 0 ) {
ErrorValue errorValue = new LibFormulaErrorValue( LibFormulaErrorValue.ERROR_INVALID_ARGUMENT );
throw new EvaluationException( errorValue );
}
valueMeta = rowMeta.getValueMeta( index );
idx = new Integer( index );
valueIndexMap.put( (String) name, idx );
}
Object valueData = rowData[idx];
try {
return getPrimitive( valueMeta, valueData );
} catch ( KettleValueException e ) {
throw new EvaluationException( LibFormulaErrorValue.ERROR_ARITHMETIC_VALUE );
}
}
return null;
}
public Configuration getConfiguration() {
return formulaContext.getConfiguration();
}
public FunctionRegistry getFunctionRegistry() {
return formulaContext.getFunctionRegistry();
}
public LocalizationContext getLocalizationContext() {
return formulaContext.getLocalizationContext();
}
public OperatorFactory getOperatorFactory() {
return formulaContext.getOperatorFactory();
}
public TypeRegistry getTypeRegistry() {
return formulaContext.getTypeRegistry();
}
public boolean isReferenceDirty( Object name ) throws EvaluationException {
return formulaContext.isReferenceDirty( name );
}
/**
* @return the row
*/
public RowMetaInterface getRowMeta() {
return rowMeta;
}
/**
* @param rowMeta
* the row to set
*/
public void setRowMeta( RowMetaInterface rowMeta ) {
this.rowMeta = rowMeta;
}
/**
* @param rowData
* the new row of data to inject
*/
public void setRowData( Object[] rowData ) {
this.rowData = rowData;
}
/**
* @return the current row of data
*/
public Object[] getRowData() {
return rowData;
}
public static Object getPrimitive( ValueMetaInterface valueMeta, Object valueData ) throws KettleValueException {
switch ( valueMeta.getType() ) {
case ValueMetaInterface.TYPE_BIGNUMBER:
return valueMeta.getBigNumber( valueData );
case ValueMetaInterface.TYPE_BINARY:
return valueMeta.getBinary( valueData );
case ValueMetaInterface.TYPE_BOOLEAN:
return valueMeta.getBoolean( valueData );
case ValueMetaInterface.TYPE_DATE:
return valueMeta.getDate( valueData );
case ValueMetaInterface.TYPE_INTEGER:
return valueMeta.getInteger( valueData );
case ValueMetaInterface.TYPE_NUMBER:
return valueMeta.getNumber( valueData );
// case ValueMetaInterface.TYPE_SERIALIZABLE: return valueMeta.(valueData);
case ValueMetaInterface.TYPE_STRING:
return valueMeta.getString( valueData );
default:
return null;
}
}
public static Class<?> getPrimitiveClass( int valueType ) {
switch ( valueType ) {
case ValueMetaInterface.TYPE_BIGNUMBER:
return BigDecimal.class;
case ValueMetaInterface.TYPE_BINARY:
return ( new byte[] {} ).getClass();
case ValueMetaInterface.TYPE_BOOLEAN:
return Boolean.class;
case ValueMetaInterface.TYPE_DATE:
return Date.class;
case ValueMetaInterface.TYPE_INTEGER:
return Long.class;
case ValueMetaInterface.TYPE_NUMBER:
return Double.class;
// case Value.VALUE_TYPE_SERIALIZABLE: return Serializable.class;
case ValueMetaInterface.TYPE_STRING:
return String.class;
default:
return null;
}
}
public Date getCurrentDate() {
return new Date();
}
}