/*******************************************************************************
* 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.utils;
import cascading.tuple.Fields;
import hydrograph.engine.cascading.assembly.infra.ComponentParameters;
import hydrograph.engine.core.component.entity.base.OperationEntityBase;
import hydrograph.engine.core.component.entity.elements.Operation;
import hydrograph.engine.core.component.entity.elements.OperationField;
import hydrograph.engine.core.component.entity.elements.OutSocket;
import hydrograph.engine.core.component.entity.elements.SchemaField;
import hydrograph.engine.core.component.entity.utils.OutSocketUtils;
import hydrograph.engine.expression.api.ValidationAPI;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import javax.tools.DiagnosticCollector;
import javax.tools.JavaFileObject;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.Map;
import java.util.Properties;
public class OperationFieldsCreator<T extends OperationEntityBase> {
private ArrayList<Fields> inputFieldsList;
private ArrayList<Fields> outputFieldsList;
private ArrayList<String> transformClassList;
private ArrayList<ValidationAPI> expressionObjectList;
private ArrayList<Properties> operationPropertiesList;
private Fields initPassThroughFields;
private boolean isOperationExistinOperationField;
private OperationEntityBase assemblyEntityBase;
private OutSocket outSocket;
private ComponentParameters componentParameters;
private static Logger LOG = LoggerFactory.getLogger(OperationFieldsCreator.class);
/**
* OperationFieldsCreator class is used to initialize passthrough fields
* and operation fields
*
* @param entity
* @param componentParameters
* @param outSocket
*/
public OperationFieldsCreator(T entity, ComponentParameters componentParameters, OutSocket outSocket) {
inputFieldsList = new ArrayList<Fields>();
outputFieldsList = new ArrayList<Fields>();
transformClassList = new ArrayList<String>();
operationPropertiesList = new ArrayList<Properties>();
expressionObjectList = new ArrayList<ValidationAPI>();
this.assemblyEntityBase = entity;
this.componentParameters = componentParameters;
this.outSocket = outSocket;
// initialization
initPassThroughFields();
initializeOperationFieldsForOutSocket();
}
private Fields initPassThroughFields() {
String[] passThroughFields = OutSocketUtils.getPassThroughFieldsFromOutSocket(
outSocket.getPassThroughFieldsList(), getStringArrayFromFields(componentParameters.getInputFields()));
if (passThroughFields != null && passThroughFields.length == 0 && !assemblyEntityBase.isOperationPresent()) {
return initPassThroughFields = componentParameters.getInputFields();
} else {
return initPassThroughFields = new Fields(passThroughFields);
}
}
private String[] getStringArrayFromFields(Fields fields) {
String[] arrayFields = new String[fields.size()];
for (int i = 0; i < fields.size(); i++)
arrayFields[i] = fields.get(i).toString();
return arrayFields;
}
private void initializeOperationFieldsForOutSocket() {
// check if the operation component has operation(s)
if (assemblyEntityBase.isOperationPresent()) {
for (Operation eachOperation : assemblyEntityBase.getOperationsList()) {
if (isOperationIDExistsInOperationFields(eachOperation.getOperationId(), outSocket)) {
inputFieldsList.add(new Fields(eachOperation.getOperationInputFields() == null ? new String[0]
: eachOperation.getOperationInputFields()));
outputFieldsList.add(new Fields(eachOperation.getOperationOutputFields() == null ? new String[0]
: eachOperation.getOperationOutputFields()));
transformClassList.add(eachOperation.getOperationClass());
if (eachOperation.getExpression() != null && !eachOperation.getExpression().equals("")){
ValidationAPI validationAPI = new ValidationAPI(eachOperation.getExpression(), componentParameters.getUDFPath());
expressionValidate(validationAPI);
expressionObjectList.add(validationAPI);
}else
expressionObjectList.add(null);
operationPropertiesList.add(eachOperation.getOperationProperties());
} else {
LOG.info("Operation: '" + eachOperation.getOperationId() + "' of component Id '"
+ assemblyEntityBase.getComponentId() + "' not used in out socket");
}
}
}
}
private void expressionValidate(ValidationAPI validationAPI) {
Map<String, Class<?>> schemaMap = new HashMap<String, Class<?>>();
try {
for (SchemaField schemaField : componentParameters.getSchemaFields()) {
schemaMap.put( schemaField.getFieldName(), Class.forName(schemaField.getFieldDataType()));
}
DiagnosticCollector<JavaFileObject> diagnostic = validationAPI.transformCompiler(schemaMap);
if (diagnostic.getDiagnostics().size() > 0) {
throw new RuntimeException(diagnostic.getDiagnostics().get(0).getMessage(null));
}
} catch (ClassNotFoundException e) {
e.printStackTrace();
}
}
private boolean isOperationIDExistsInOperationFields(String operationId, OutSocket outSocket) {
for (OperationField eachOperationField : outSocket.getOperationFieldList()) {
if (eachOperationField.getOperationId().equals(operationId)) {
return isOperationExistinOperationField = true;
}
}
return isOperationExistinOperationField = false;
}
/**
* @return inputFieldsList
*/
public ArrayList<Fields> getOperationalInputFieldsList() {
return inputFieldsList;
}
/**
* @return outputFieldsList
*/
public ArrayList<Fields> getOperationalOutputFieldsList() {
return outputFieldsList;
}
/**
* @return transformClassList
*/
public ArrayList<String> getOperationalTransformClassList() {
return transformClassList;
}
/**
* @return operationPropertiesList
*/
public ArrayList<Properties> getOperationalOperationPropertiesList() {
return operationPropertiesList;
}
/**
* @return PassThroughFields
*/
public Fields getPassThroughFields() {
return initPassThroughFields;
}
/**
* @return boolean value indicating whether operation field is present or
* not
*/
public boolean checkIfOperationExistsInOperationFields() {
return isOperationExistinOperationField;
}
/**
* @return expressionList
*/
public ArrayList<ValidationAPI> getOperationalExpressionList() {
return expressionObjectList;
}
}