/*******************************************************************************
* 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.ui.engine.ui.converter;
import java.math.BigDecimal;
import java.util.ArrayList;
import java.util.LinkedHashMap;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;
import java.util.TreeMap;
import org.apache.commons.lang.StringUtils;
import org.slf4j.Logger;
import hydrograph.engine.jaxb.commontypes.TypeBaseField;
import hydrograph.engine.jaxb.commontypes.TypeBaseInSocket;
import hydrograph.engine.jaxb.commontypes.TypeExpressionField;
import hydrograph.engine.jaxb.commontypes.TypeInputField;
import hydrograph.engine.jaxb.commontypes.TypeMapField;
import hydrograph.engine.jaxb.commontypes.TypeOperationField;
import hydrograph.engine.jaxb.commontypes.TypeOperationInputFields;
import hydrograph.engine.jaxb.commontypes.TypeOperationsComponent;
import hydrograph.engine.jaxb.commontypes.TypeOperationsOutSocket;
import hydrograph.engine.jaxb.commontypes.TypeProperties;
import hydrograph.engine.jaxb.commontypes.TypeProperties.Property;
import hydrograph.engine.jaxb.commontypes.TypeTransformExpression;
import hydrograph.engine.jaxb.commontypes.TypeTransformOperation;
import hydrograph.engine.jaxb.operationstypes.Normalize;
import hydrograph.ui.common.component.config.Operations;
import hydrograph.ui.common.component.config.TypeInfo;
import hydrograph.ui.common.util.Constants;
import hydrograph.ui.common.util.ParameterUtil;
import hydrograph.ui.common.util.XMLConfigUtil;
import hydrograph.ui.datastructure.expression.ExpressionEditorData;
import hydrograph.ui.datastructure.property.ComponentsOutputSchema;
import hydrograph.ui.datastructure.property.FilterProperties;
import hydrograph.ui.datastructure.property.GridRow;
import hydrograph.ui.datastructure.property.NameValueProperty;
import hydrograph.ui.datastructure.property.mapping.MappingSheetRow;
import hydrograph.ui.datastructure.property.mapping.TransformMapping;
import hydrograph.ui.engine.constants.PropertyNameConstants;
import hydrograph.ui.engine.ui.constants.UIComponentsConstants;
import hydrograph.ui.engine.ui.helper.ConverterUiHelper;
import hydrograph.ui.graph.model.PortTypeEnum;
import hydrograph.ui.logging.factory.LogFactory;
import hydrograph.ui.propertywindow.messages.Messages;
import hydrograph.ui.propertywindow.schema.propagation.helper.SchemaPropagationHelper;
/**
* The class TransformUiConverter
*
* @author Bitwise
*
*/
public abstract class TransformUiConverter extends UiConverter {
private static final Logger LOGGER = LogFactory.INSTANCE
.getLogger(TransformUiConverter.class);
/**
* Generate common properties of transform-component that will appear in
* property window.
*
*/
@Override
public void prepareUIXML() {
super.prepareUIXML();
LOGGER.debug("Fetching common properties for -{}", componentName);
getInPort((TypeOperationsComponent) typeBaseComponent);
getOutPort((TypeOperationsComponent) typeBaseComponent);
uiComponent.setCategory(UIComponentsConstants.TRANSFORM_CATEGORY
.value());
propertyMap.put(PropertyNameConstants.RUNTIME_PROPERTIES.value(),
getRuntimeProperties());
}
/**
* Create input ports for transform component.
*
* @param TypeOperationsComponent
* the operationsComponent
*
*/
protected void getInPort(TypeOperationsComponent operationsComponent) {
LOGGER.debug("Generating InPut Ports for -{}", componentName);
if (operationsComponent.getInSocket() != null) {
for (TypeBaseInSocket inSocket : operationsComponent.getInSocket()) {
uiComponent.engageInputPort(inSocket.getId());
currentRepository.getComponentLinkList().add(
new LinkingData(inSocket.getFromComponentId(),
operationsComponent.getId(), inSocket
.getFromSocketId(), inSocket.getId()));
uiComponent.getPorts().get(inSocket.getId()).setPortType(PortTypeEnum.IN);
}
}
}
/**
* Create output ports for transform component.
*
* @param TypeOperationsComponent
* the operationsComponent
*
*/
protected void getOutPort(TypeOperationsComponent operationsComponent) {
LOGGER.debug("Generating OutPut Ports for -{}", componentName);
if (operationsComponent.getOutSocket() != null) {
for (TypeOperationsOutSocket outSocket : operationsComponent
.getOutSocket()) {
uiComponent.engageOutputPort(outSocket.getId());
if (outSocket.getPassThroughFieldOrOperationFieldOrExpressionField() != null){
propertyMap.put(Constants.PARAM_OPERATION,getUiPassThroughOrOperationFieldsOrMapFieldGrid(outSocket));
createPassThroughAndMappingFieldsForSchemaPropagation(outSocket);
}
}
}
}
/**
* Create transform property grid for transform component.
*
* @param TypeOperationsOutSocket
* the outSocket
*
* @return TransformPropertyGrid, transformPropertyGrid object which is
* responsible to display transform grid.
*/
protected TransformMapping getUiPassThroughOrOperationFieldsOrMapFieldGrid(
TypeOperationsOutSocket outSocket) {
TransformMapping atMapping = new TransformMapping();
List<MappingSheetRow> mappingSheetRows = new LinkedList<>();
for (Object property : outSocket
.getPassThroughFieldOrOperationFieldOrExpressionField()) {
MappingSheetRow mappingSheetRow = null;
if (property instanceof TypeInputField) {
List inputFieldList = new LinkedList<>();
inputFieldList.add(((TypeInputField) property).getName());
List outputFieldList = new LinkedList<>();
outputFieldList.add(((TypeInputField) property).getName());
mappingSheetRow = new MappingSheetRow(inputFieldList, null,
outputFieldList);
mappingSheetRows.add(mappingSheetRow);
} else if (property instanceof TypeMapField) {
List inputFieldList = new LinkedList<>();
inputFieldList.add(((TypeMapField) property).getSourceName());
List outputFieldList = new LinkedList<>();
outputFieldList.add(((TypeMapField) property).getName());
mappingSheetRow = new MappingSheetRow(inputFieldList, null,
outputFieldList);
mappingSheetRows.add(mappingSheetRow);
}
}
atMapping.setMappingSheetRows(mappingSheetRows);
return atMapping;
}
private void getOperationData(TransformMapping atMapping)
{
List<Object> typeTransformOpertaionList = ((TypeOperationsComponent) typeBaseComponent)
.getOperationOrExpression();
List<MappingSheetRow> mappingSheetRows = atMapping
.getMappingSheetRows();
for (Object item : typeTransformOpertaionList)
{
if(item instanceof TypeTransformOperation)
{
if(Constants.NORMALIZE.equalsIgnoreCase(uiComponent.getComponentName()))
atMapping.setExpression(false);
TypeTransformOperation transformOperation=(TypeTransformOperation)item;
mappingSheetRows.add(new MappingSheetRow(getInputFieldList(transformOperation),
getOutputFieldList(transformOperation),
getOperationClassName(transformOperation.getClazz()),transformOperation.getClazz(),
ParameterUtil.isParameter(transformOperation.getClazz()),transformOperation.getId(),getProperties(transformOperation),false,null,null,true)
);
}
else if(item instanceof TypeTransformExpression)
{
TypeTransformExpression transformExpression=(TypeTransformExpression)item;
MappingSheetRow mappingSheetRow;
if(Constants.GROUP_COMBINE.equalsIgnoreCase(uiComponent.getComponentName()))
{
mappingSheetRow=new MappingSheetRow(getInputFieldList(transformExpression),getOutputFieldList(transformExpression),
null,null,false,transformExpression.getId(),getProperties(transformExpression),true,
getExpressionEditorData(transformExpression),
getMergeExpressionEditorData(transformExpression),true);
}
else{
mappingSheetRow=new MappingSheetRow(getInputFieldList(transformExpression),getOutputFieldList(transformExpression),
null,null,false,transformExpression.getId(),getProperties(transformExpression),true,
getExpressionEditorData(transformExpression),
null,true);
}
if(Constants.NORMALIZE.equalsIgnoreCase(uiComponent.getComponentName())){
mappingSheetRow.getExpressionEditorData().getExtraFieldDatatypeMap().put(Constants._INDEX,java.lang.Integer.class);
atMapping.setExpression(true);
}
else if(Constants.AGGREGATE.equalsIgnoreCase(uiComponent.getComponentName())
||Constants.CUMULATE.equalsIgnoreCase(uiComponent.getComponentName())
||Constants.GROUP_COMBINE.equalsIgnoreCase(uiComponent.getComponentName())
)
{
mappingSheetRow.setAccumulator(transformExpression.getAccumulatorInitalValue());
if(StringUtils.isBlank(transformExpression.getAccumulatorInitalValue()))
{
mappingSheetRow.setComboDataType(Messages.DATATYPE_INTEGER);
}
else if(transformExpression.getAccumulatorInitalValue().startsWith("@{") &&
transformExpression.getAccumulatorInitalValue().
endsWith("}")){
mappingSheetRow.setAccumulatorParameter(true);
mappingSheetRow.setComboDataType(Messages.DATATYPE_INTEGER);
}else if(validateInteger(transformExpression.getAccumulatorInitalValue())){
mappingSheetRow.setComboDataType(Messages.DATATYPE_INTEGER);
mappingSheetRow.getExpressionEditorData().getExtraFieldDatatypeMap().put(Constants.ACCUMULATOR_VARIABLE,
java.lang.Integer.class);
if(mappingSheetRow.getMergeExpressionDataForGroupCombine()!=null){
mappingSheetRow.getMergeExpressionDataForGroupCombine().getExtraFieldDatatypeMap().put(Constants.ACCUMULATOR_VARIABLE,
java.lang.Integer.class);
mappingSheetRow.getMergeExpressionDataForGroupCombine().getExtraFieldDatatypeMap().put(Constants.ACCUMULATOR_VARIABLE_1,
java.lang.Integer.class);
mappingSheetRow.getMergeExpressionDataForGroupCombine().getExtraFieldDatatypeMap().put(Constants.ACCUMULATOR_VARIABLE_2,
java.lang.Integer.class);
}
}else if(validateBigDecimal(transformExpression.getAccumulatorInitalValue())){
mappingSheetRow.setComboDataType(Messages.DATATYPE_BIGDECIMAL);
mappingSheetRow.getExpressionEditorData().getExtraFieldDatatypeMap().put(Constants.ACCUMULATOR_VARIABLE,
java.math.BigDecimal.class);
if(mappingSheetRow.getMergeExpressionDataForGroupCombine()!=null){
mappingSheetRow.getMergeExpressionDataForGroupCombine().getExtraFieldDatatypeMap().put(Constants.ACCUMULATOR_VARIABLE,
java.math.BigDecimal.class);
mappingSheetRow.getMergeExpressionDataForGroupCombine().getExtraFieldDatatypeMap().put(Constants.ACCUMULATOR_VARIABLE_1,
java.math.BigDecimal.class);
mappingSheetRow.getMergeExpressionDataForGroupCombine().getExtraFieldDatatypeMap().put(Constants.ACCUMULATOR_VARIABLE_2,
java.math.BigDecimal.class);
}
}else{
mappingSheetRow.setComboDataType(Messages.DATATYPE_STRING);
mappingSheetRow.getExpressionEditorData().getExtraFieldDatatypeMap().put(Constants.ACCUMULATOR_VARIABLE,
java.lang.String.class);
if(mappingSheetRow.getMergeExpressionDataForGroupCombine()!=null){
mappingSheetRow.getMergeExpressionDataForGroupCombine().getExtraFieldDatatypeMap().put(Constants.ACCUMULATOR_VARIABLE,
java.lang.String.class);
mappingSheetRow.getMergeExpressionDataForGroupCombine().getExtraFieldDatatypeMap().put(Constants.ACCUMULATOR_VARIABLE_1,
java.lang.String.class);
mappingSheetRow.getMergeExpressionDataForGroupCombine().getExtraFieldDatatypeMap().put(Constants.ACCUMULATOR_VARIABLE_2,
java.lang.String.class);
}
}
}
mappingSheetRows.add(mappingSheetRow);
}
}
}
private ExpressionEditorData getMergeExpressionEditorData(TypeTransformExpression typeTransformExpression) {
String expression;
if(StringUtils.isBlank(typeTransformExpression.getMergeExpr())){
expression="";
}
else{
expression=typeTransformExpression.getMergeExpr();
}
ExpressionEditorData editorData=new ExpressionEditorData(expression,uiComponent.getComponentName());
if(typeTransformExpression.getInputFields()!=null){
for(TypeInputField inputField:typeTransformExpression.getInputFields().getField()){
editorData.getfieldsUsedInExpression().add(inputField.getName());
}
}
return editorData;
}
private boolean validateBigDecimal(String value){
try{
new BigDecimal(value);
return true;
}catch(Exception exception){
return false;
}
}
private boolean validateInteger(String value){
try{
Integer.valueOf(value);
return true;
}catch(Exception e){
return false;
}
}
protected ExpressionEditorData getExpressionEditorData(TypeTransformExpression typeTransformExpression) {
String expression;
if(StringUtils.isBlank(typeTransformExpression.getExpr())){
expression="";
}
else{
expression=typeTransformExpression.getExpr();
}
ExpressionEditorData editorData=new ExpressionEditorData(expression,uiComponent.getComponentName());
if(typeTransformExpression.getInputFields()!=null){
for(TypeInputField inputField:typeTransformExpression.getInputFields().getField()){
editorData.getfieldsUsedInExpression().add(inputField.getName());
}
}
return editorData;
}
protected String getOperationClassName(String fullClassPath) {
String operationClassName = Messages.CUSTOM;
Operations operations = XMLConfigUtil.INSTANCE.getComponent(uiComponent.getComponentName()).getOperations();
List<TypeInfo> typeInfos = operations.getStdOperation();
if (StringUtils.isNotBlank(fullClassPath) && !ParameterUtil.isParameter(fullClassPath)) {
String str[] = fullClassPath.split("\\.");
for (int i = 0; i < typeInfos.size(); i++) {
if(typeInfos.get(i).getName().equalsIgnoreCase(str[str.length - 1]))
{
operationClassName = str[str.length - 1];
}
}
}
return operationClassName;
}
private List<NameValueProperty> getProperties(Object item)
{
List<NameValueProperty> nameValueProperties=new LinkedList<>();
TypeProperties typeProperties = null;
if(item instanceof TypeTransformOperation)
{
TypeTransformOperation typeTransformOperation=(TypeTransformOperation)item;
typeProperties=typeTransformOperation.getProperties();
}
else if(item instanceof TypeTransformExpression)
{
TypeTransformExpression typeTransformExpression=(TypeTransformExpression)item;
typeProperties=typeTransformExpression.getProperties();
}
if(item!=null && typeProperties!=null)
{
for(Property property:typeProperties.getProperty())
{
NameValueProperty nameValueProperty=new NameValueProperty();
nameValueProperty.setPropertyName(property.getName());
nameValueProperty.setPropertyValue(getValueForPropertyTag(property.getName()));
nameValueProperties.add(nameValueProperty);
}
}
return nameValueProperties;
}
private List<FilterProperties> getOutputFieldList(Object item) {
List<FilterProperties> outputFieldList = new LinkedList<>();
if(item !=null )
{
ConverterUiHelper converterUiHelper = new ConverterUiHelper(uiComponent);
List<GridRow> gridRowList = new ArrayList<>();
if(item instanceof TypeTransformOperation)
{
TypeTransformOperation typeTransformOperation=(TypeTransformOperation)item;
if (typeTransformOperation.getOutputFields() != null) {
for (TypeBaseField record : typeTransformOperation.getOutputFields().getField()) {
GridRow gridRow=converterUiHelper.getFixedWidthSchema(record);
gridRowList.add(gridRow);
createPropagationDataForOperationFileds(gridRow);
FilterProperties filterProperties=new FilterProperties();
filterProperties.setPropertyname(record.getName());
outputFieldList.add(filterProperties);
}
}
}
else if(item instanceof TypeTransformExpression)
{
TypeTransformExpression typeTransformExpression=(TypeTransformExpression)item;
if (typeTransformExpression.getOutputFields() != null)
{
TypeBaseField record =typeTransformExpression.getOutputFields().getField();
if(record!=null){
GridRow gridRow=converterUiHelper.getFixedWidthSchema(record);
gridRowList.add(gridRow);
createPropagationDataForOperationFileds(gridRow);
FilterProperties filterProperties=new FilterProperties();
filterProperties.setPropertyname(record.getName());
outputFieldList.add(filterProperties);
}}
}
}
return outputFieldList;
}
private void createPropagationDataForOperationFileds(GridRow gridRow) {
ComponentsOutputSchema componentsOutputSchema = null;
Map<String, ComponentsOutputSchema> schemaMap = (Map<String, ComponentsOutputSchema>) propertyMap.get(Constants.SCHEMA_TO_PROPAGATE);
if (schemaMap == null) {
schemaMap = new LinkedHashMap<>();
componentsOutputSchema = new ComponentsOutputSchema();
schemaMap.put(Constants.FIXED_OUTSOCKET_ID, componentsOutputSchema);
propertyMap.put(Constants.SCHEMA_TO_PROPAGATE, schemaMap);
} else if (schemaMap.get(Constants.FIXED_OUTSOCKET_ID) == null) {
componentsOutputSchema = new ComponentsOutputSchema();
schemaMap.put(Constants.FIXED_OUTSOCKET_ID, componentsOutputSchema);
}
componentsOutputSchema = schemaMap.get(Constants.FIXED_OUTSOCKET_ID);
componentsOutputSchema.addSchemaFields(gridRow);
}
private List<FilterProperties> getInputFieldList(Object item) {
TypeOperationInputFields typeOperationInputFields = null;
if(item instanceof TypeTransformOperation)
{
TypeTransformOperation typeTransformOperation=(TypeTransformOperation)item;
typeOperationInputFields=typeTransformOperation.getInputFields();
}
else if(item instanceof TypeTransformExpression)
{
TypeTransformExpression typeTransformExpression=(TypeTransformExpression)item;
typeOperationInputFields=typeTransformExpression.getInputFields();
}
List<FilterProperties> inputfieldList = new LinkedList<>();
if(typeOperationInputFields!=null){
for (TypeInputField inputField : typeOperationInputFields.getField()) {
FilterProperties filterProperties=new FilterProperties();
filterProperties.setPropertyname(inputField.getName());
inputfieldList.add(filterProperties);
}
}
return inputfieldList;
}
private List<NameValueProperty> getMapAndPassThroughField()
{
List<TypeOperationsOutSocket> xsdOpertaionList = ((TypeOperationsComponent) typeBaseComponent)
.getOutSocket();
List<NameValueProperty> nameValueproperties=new LinkedList<>();
for(TypeOperationsOutSocket typeOperationsOutSocket:xsdOpertaionList)
{
for (Object property : typeOperationsOutSocket
.getPassThroughFieldOrOperationFieldOrExpressionField())
{
NameValueProperty nameValueProperty=new NameValueProperty();
if(property instanceof TypeInputField)
{
nameValueProperty.setPropertyName(((TypeInputField) property).getName());
nameValueProperty.setPropertyValue(((TypeInputField) property).getName());
nameValueProperty.getFilterProperty().setPropertyname(((TypeInputField) property).getName());
nameValueproperties.add(nameValueProperty);
}
else if(property instanceof TypeMapField )
{
nameValueProperty.setPropertyName(((TypeMapField) property).getSourceName());
nameValueProperty.setPropertyValue(((TypeMapField) property).getName());
nameValueProperty.getFilterProperty().setPropertyname(((TypeMapField) property).getName());
nameValueproperties.add(nameValueProperty);
}
}
}
return nameValueproperties;
}
protected Object createTransformPropertyGrid() {
TransformMapping atMapping = new TransformMapping();
getOperationData(atMapping);
atMapping.setMapAndPassthroughField(getMapAndPassThroughField());
if(Constants.NORMALIZE.equalsIgnoreCase(uiComponent.getComponentName()))
intializeOutputRecordCount(atMapping);
return atMapping;
}
private void intializeOutputRecordCount(TransformMapping atMapping) {
Normalize normalize=(Normalize)typeBaseComponent;
String expression;
if(!atMapping.isExpression()){
expression="";
}else{
expression=normalize.getOutputRecordCount().getValue();
}
ExpressionEditorData expressionEditorData=new ExpressionEditorData(expression,
uiComponent.getComponentName());
atMapping.setExpressionEditorData(expressionEditorData);
}
/**
* Generate runtime properties for component.
*
* @return Map<String,String>
*/
@Override
protected Map<String, String> getRuntimeProperties() {
LOGGER.debug("Generating Runtime Properties for -{}", componentName);
TreeMap<String, String> runtimeMap = null;
TypeProperties typeProperties = ((TypeOperationsComponent) typeBaseComponent)
.getRuntimeProperties();
if (typeProperties != null) {
runtimeMap = new TreeMap<>();
for (Property runtimeProperty : typeProperties.getProperty()) {
runtimeMap.put(runtimeProperty.getName(),
runtimeProperty.getValue());
}
}
return runtimeMap;
}
/**
* This method creates ComponentOutputSchema for pass-through and mapping fields of operation components. Also
* maintains sequence of pass-through , mapping and operation filed sequence as a temporary property within component.
*
* @param operationsOutSockets
*/
protected void createPassThroughAndMappingFieldsForSchemaPropagation(TypeOperationsOutSocket operationsOutSockets) {
ComponentsOutputSchema componentsOutputSchema = null;
List<String> schemaFieldSequence = null;
Map<String, ComponentsOutputSchema> schemaMap = (Map<String, ComponentsOutputSchema>) propertyMap
.get(Constants.SCHEMA_TO_PROPAGATE);
if (operationsOutSockets != null
&& !operationsOutSockets.getPassThroughFieldOrOperationFieldOrExpressionField().isEmpty()) {
componentsOutputSchema = new ComponentsOutputSchema();
schemaFieldSequence = new ArrayList<>();
for (Object property : operationsOutSockets.getPassThroughFieldOrOperationFieldOrExpressionField()) {
if (property instanceof TypeInputField) {
schemaFieldSequence.add(((TypeInputField) property).getName());
componentsOutputSchema.getPassthroughFields().add(((TypeInputField) property).getName());
componentsOutputSchema.addSchemaFields(SchemaPropagationHelper.INSTANCE
.createFixedWidthGridRow(((TypeInputField) property).getName()));
} else if (property instanceof TypeMapField) {
schemaFieldSequence.add(((TypeMapField) property).getName());
componentsOutputSchema.getMapFields().put(((TypeMapField) property).getName(),
((TypeMapField) property).getSourceName());
componentsOutputSchema.addSchemaFields(SchemaPropagationHelper.INSTANCE
.createFixedWidthGridRow(((TypeMapField) property).getName()));
} else if (property instanceof TypeOperationField) {
schemaFieldSequence.add(((TypeOperationField) property).getName());
}
else if (property instanceof TypeExpressionField)
{
schemaFieldSequence.add(((TypeExpressionField) property).getName());
}
}
}
if (schemaMap == null) {
schemaMap = new LinkedHashMap<>();
}
if(operationsOutSockets!=null){
schemaMap.put(operationsOutSockets.getId(), componentsOutputSchema);
}
propertyMap.put(Constants.SCHEMA_TO_PROPAGATE, schemaMap);
propertyMap.put(Constants.SCHEMA_FIELD_SEQUENCE, schemaFieldSequence);
}
protected void copySchemaFromInputPort(String inSocketId) {
if(StringUtils.isNotBlank(inSocketId))
propertyMap.put(Constants.COPY_FROM_INPUT_PORT_PROPERTY, inSocketId);
}
}