/******************************************************************************* * Copyright 2017 Capital One Services, LLC and Bitwise, Inc. * 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 hydrograph.engine.cascading.assembly.handlers; import cascading.flow.FlowProcess; import cascading.management.annotation.Property; import cascading.management.annotation.PropertyDescription; import cascading.management.annotation.Visibility; import cascading.operation.BaseOperation; import cascading.operation.Buffer; import cascading.operation.BufferCall; import cascading.operation.OperationCall; import cascading.tuple.Fields; import cascading.tuple.TupleEntry; import hydrograph.engine.cascading.assembly.context.CustomHandlerContext; import hydrograph.engine.cascading.utilities.ReusableRowHelper; import hydrograph.engine.cascading.utilities.TupleHelper; import hydrograph.engine.expression.api.ValidationAPI; import hydrograph.engine.expression.userfunctions.CumulateForExpression; import hydrograph.engine.expression.utils.ExpressionWrapper; import hydrograph.engine.transformation.userfunctions.base.CumulateTransformBase; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import java.util.ArrayList; import java.util.Arrays; import java.util.Iterator; import java.util.Properties; public class CumulateCustomHandler extends BaseOperation<CustomHandlerContext<CumulateTransformBase>> implements Buffer<CustomHandlerContext<CumulateTransformBase>> { /** * */ private static final long serialVersionUID = -5599319878964805478L; /** * */ private ArrayList<Properties> props; private ArrayList<String> transformClassNames; private FieldManupulatingHandler fieldManupulatingHandler; private ArrayList<ValidationAPI> expressionList; private String[] initialValues; private static Logger LOG = LoggerFactory .getLogger(CumulateCustomHandler.class); public CumulateCustomHandler( FieldManupulatingHandler fieldManupulatingHandler, ArrayList<Properties> props, ArrayList<String> transformClassNames, ArrayList<ValidationAPI> expressionObjectList, String[] strings) { super(fieldManupulatingHandler.getInputFields().size(), fieldManupulatingHandler.getOutputFields()); this.props = props; this.transformClassNames = transformClassNames; this.fieldManupulatingHandler = fieldManupulatingHandler; this.expressionList = expressionObjectList; this.initialValues = strings; if (transformClassNames != null) { LOG.trace("CumulateCustomHandler object created for: " + Arrays.toString(transformClassNames.toArray())); } else { LOG.trace("CumulateCustomHandler object created for:" + Arrays.toString(expressionObjectList.toArray())); } } public Fields getOutputFields() { return fieldManupulatingHandler.getOutputFields(); } public Fields getInputFields() { return fieldManupulatingHandler.getInputFields(); } public Fields getKeyFields() { return fieldManupulatingHandler.keyFields; } @SuppressWarnings("rawtypes") @Override public void prepare(FlowProcess flowProcess, OperationCall<CustomHandlerContext<CumulateTransformBase>> call) { Object[] accumulatorValues = new Object[initialValues.length]; CustomHandlerContext<CumulateTransformBase> context = new CustomHandlerContext<CumulateTransformBase>( fieldManupulatingHandler, transformClassNames, expressionList, initialValues, accumulatorValues); int counter = -1; for (CumulateTransformBase transformInstance : context .getTransformInstances()) { counter = counter + 1; if (transformInstance != null) { LOG.trace("calling prepare method of: " + transformInstance.getClass().getName()); if (transformInstance instanceof CumulateForExpression) { ExpressionWrapper expressionWrapper=new ExpressionWrapper(context.getSingleExpressionInstances(), ""); ((CumulateForExpression) transformInstance) .setValidationAPI(expressionWrapper); ((CumulateForExpression) transformInstance).callPrepare(); } try { transformInstance .prepare( props.get(counter), context.getInputRow(counter) .getFieldNames(), context.getOutputRow(counter) .getFieldNames(), ReusableRowHelper .getListFromFields(fieldManupulatingHandler.keyFields)); } catch (Exception e) { LOG.error( "Exception in prepare method of: " + transformInstance.getClass().getName() + ".\nArguments passed to prepare() method are: \nProperties: " + props + "\nInput Fields: " + Arrays.toString(context .getInputRow(counter) .getFieldNames().toArray()) + "\nOutput Fields: " + Arrays.toString(context .getOutputRow(counter) .getFieldNames().toArray()) + "\nKey Fields: " + Arrays.toString(ReusableRowHelper .getListFromFields( fieldManupulatingHandler.keyFields) .toArray()), e); throw new RuntimeException( "Exception in prepare method of: " + transformInstance.getClass().getName() + ".\nArguments passed to prepare() method are: \nProperties: " + props + "\nInput Fields: " + Arrays.toString(context .getInputRow(counter) .getFieldNames().toArray()) + "\nOutput Fields: " + Arrays.toString(context .getOutputRow(counter) .getFieldNames().toArray()) + "\nKey Fields: " + Arrays.toString(ReusableRowHelper .getListFromFields( fieldManupulatingHandler.keyFields) .toArray()), e); } } } // context.setAccumulatorList(accumulatorValues); call.setContext(context); } @SuppressWarnings("rawtypes") @Override public void cleanup(FlowProcess flowProcess, OperationCall<CustomHandlerContext<CumulateTransformBase>> call) { CustomHandlerContext<CumulateTransformBase> context = call.getContext(); for (CumulateTransformBase transformInstance : context .getTransformInstances()) { if (transformInstance != null) { LOG.trace("calling cleanup method of: " + transformInstance.getClass().getName()); transformInstance.cleanup(); } } } @SuppressWarnings("rawtypes") @Override public void operate(FlowProcess arg0, BufferCall<CustomHandlerContext<CumulateTransformBase>> call) { CustomHandlerContext<CumulateTransformBase> context = call.getContext(); // get all the current argument values for this grouping Iterator<TupleEntry> currentGroupOfTupleEntry = call .getArgumentsIterator(); // create a Tuple to hold our result values while (currentGroupOfTupleEntry.hasNext()) { TupleEntry currentTupleEntry = currentGroupOfTupleEntry.next(); int counter = -1; for (CumulateTransformBase transformInstance : context .getTransformInstances()) { counter = counter + 1; if (transformInstance != null) { LOG.trace("calling cumulate method of: " + transformInstance.getClass().getName()); if (transformInstance instanceof CumulateForExpression) { ((CumulateForExpression) transformInstance) .setCounter(counter); } try { transformInstance.cumulate(ReusableRowHelper .extractFromTuple(fieldManupulatingHandler .getInputPositions(counter), currentTupleEntry.getTuple(), context .getInputRow(counter)), context .getOutputRow(counter)); } catch (Exception e) { LOG.error("Exception in cumulate method of: " + transformInstance.getClass().getName() + ".\nRow being processed: " + currentTupleEntry, e); throw new RuntimeException( "Exception in cumulate method of: " + transformInstance.getClass() .getName() + ".\nRow being processed: " + currentTupleEntry, e); } } } // set output tuple entry with map field values TupleHelper.setTupleOnPositions(fieldManupulatingHandler .getMapSourceFieldPositions(), currentTupleEntry.getTuple(), fieldManupulatingHandler.getMapTargetFieldPositions(), call .getContext().getOutputTupleEntry().getTuple()); // set output tuple entry with passthrough field values TupleHelper.setTupleOnPositions(fieldManupulatingHandler .getInputPassThroughPositions(), currentTupleEntry.getTuple(), fieldManupulatingHandler .getOutputPassThroughPositions(), call.getContext() .getOutputTupleEntry().getTuple()); // set output tuple entry with operation output Fields ReusableRowHelper.setTupleEntryFromResuableRowsAndReset(call .getContext().getOutputTupleEntry(), context.getAllOutputRow(), fieldManupulatingHandler.getAllOutputPositions()); // return the result Tuple call.getOutputCollector().add(context.getOutputTupleEntry()); } for (CumulateTransformBase transformInstance : context .getTransformInstances()) { LOG.trace("calling onCompleteGroup method of: " + transformInstance.getClass().getName()); transformInstance.onCompleteGroup(); } } @Property(name = "Operation Classes", visibility = Visibility.PUBLIC) @PropertyDescription(value = "Cumulate Operations executed by this Component") public String[] getOperationClasses() { String[] classes = new String[transformClassNames.size()]; classes = transformClassNames.toArray(classes); return classes; } }