package nl.ipo.cds.admin.ba.attributemapping;
import java.beans.PropertyDescriptor;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import nl.ipo.cds.admin.ba.controller.beans.mapping.ConditionOperation;
import nl.ipo.cds.admin.ba.controller.beans.mapping.InputAttribute;
import nl.ipo.cds.admin.ba.controller.beans.mapping.Mapping;
import nl.ipo.cds.admin.ba.controller.beans.mapping.Operation;
import nl.ipo.cds.admin.ba.controller.beans.mapping.TransformOperation;
import nl.ipo.cds.attributemapping.operations.OperationInput;
import nl.ipo.cds.dao.attributemapping.InputOperationDTO;
import nl.ipo.cds.dao.attributemapping.OperationDTO;
import nl.ipo.cds.dao.attributemapping.TransformOperationDTO;
import nl.ipo.cds.domain.FeatureType;
import nl.ipo.cds.etl.operations.transform.ConditionalTransform;
import nl.ipo.cds.etl.theme.AttributeDescriptor;
import org.springframework.beans.BeanWrapper;
import org.springframework.beans.BeanWrapperImpl;
public class MappingFactory {
private final OperationDTO rootOperation;
private final FeatureType featureType;
public MappingFactory (final OperationDTO rootOperation, final FeatureType featureType) {
this.rootOperation = rootOperation;
this.featureType = featureType;
}
public Mapping buildMapping () {
final Mapping mapping = new Mapping ();
// Validate the input:
if (!(rootOperation.getOperationType () instanceof AttributeDescriptor<?>)) {
throw new IllegalStateException ("Root operation is not an attribute descriptor");
}
if (rootOperation.getInputs ().size () != 1 || !(rootOperation.getInputs ().get (0).getOperation () instanceof TransformOperationDTO)) {
throw new IllegalStateException ("Root operation is expected to have exactly one conditional input of type TransformOperation");
}
// Get the attribute descriptor:
final AttributeDescriptor<?> attributeDescriptor = (AttributeDescriptor<?>)rootOperation.getOperationType ();
mapping.setAttributeName (attributeDescriptor.getName ());
mapping.setFeatureTypeName (featureType.getName ().getLocalPart ());
mapping.setFeatureTypeNamespace (featureType.getName ().getNamespace ());
// Set operations:
mapping.setOperations (buildConditionalOperations ((TransformOperationDTO)rootOperation.getInputs ().get (0).getOperation ()));
return mapping;
}
public List<Operation> buildConditionalOperations (final TransformOperationDTO conditionalOperation) {
final List<Operation> result = new ArrayList<Operation> ();
final ConditionalTransform.Settings settings = (ConditionalTransform.Settings)conditionalOperation.getOperationProperties ();
final List<OperationInput> inputs = conditionalOperation.getInputs ();
for (int i = 0; i < inputs.size (); ++ i) {
final OperationDTO inputOperation = (OperationDTO)inputs.get (i).getOperation ();
final ConditionalTransform.Condition condition = settings != null && i < settings.getConditions ().size () ? settings.getConditions ().get (i) : null;
result.add (buildCondition (inputOperation, condition));
}
return result;
}
public ConditionOperation buildCondition (final OperationDTO inputOperation, final ConditionalTransform.Condition condition) {
final ConditionOperation operation = new ConditionOperation ();
final Map<String, Object> settings = new HashMap<String, Object> ();
final List<Operation> inputs = new ArrayList<Operation> (1);
// Construct settings:
if (condition != null) {
settings.put ("attribute", condition.getAttribute ());
settings.put ("operator", getOperatorName (condition.getOperation ()));
if (condition.getValues ().length > 0) {
settings.put ("value", condition.getValues ()[0]);
}
}
// Create the input:
if (inputOperation != null) {
inputs.add (buildOperation (inputOperation));
}
operation.setName ("[condition]");
operation.setOperationInputs (inputs);
operation.setSettings (settings);
return operation;
}
public Operation buildOperation (final OperationDTO original) {
if (original == null) {
return null;
} else if (original instanceof InputOperationDTO) {
return buildInput ((InputOperationDTO)original);
} else if (original instanceof TransformOperationDTO) {
return buildTransform ((TransformOperationDTO)original);
}
throw new IllegalStateException (String.format ("Invalid operation type %s", original.getClass ().getCanonicalName ()));
}
public InputAttribute buildInput (final InputOperationDTO original) {
final InputAttribute result = new InputAttribute ();
result.setName (original.getAttributeName ());
result.setInputAttributeType (original.getAttributeType().getJavaType().toString ());
result.setInputAttributeNamespace (featureType.getName ().getNamespace ());
return result;
}
public TransformOperation buildTransform (final TransformOperationDTO original) {
final TransformOperation result = new TransformOperation ();
final Map<String, Object> settings = new HashMap<String, Object> ();
final Object properties = original.getOperationProperties ();
// Convert settings:
if (properties != null) {
final BeanWrapper wrapper = new BeanWrapperImpl (properties);
for (final PropertyDescriptor pd: wrapper.getPropertyDescriptors ()) {
if (pd.getReadMethod () != null && pd.getWriteMethod () != null) {
settings.put (pd.getName (), wrapper.getPropertyValue (pd.getName ()));
}
}
}
// Convert inputs:
final List<Operation> inputs = new ArrayList<Operation> ();
for (final OperationInput input: original.getInputs()) {
inputs.add (buildOperation ((OperationDTO)input.getOperation ()));
}
result.setName (original.getOperationType ().getName ());
result.setSettings (settings);
result.setOperationInputs (inputs);
return result;
}
private static String getOperatorName (final ConditionalTransform.Operation operation) {
switch (operation) {
case IN:
return "in";
case IS_EMPTY:
return "empty";
case IS_NOT_EMPTY:
return "not_empty";
case IS_NOT_NULL:
return "not_null";
case IS_NULL:
return "null";
case NOT_IN:
return "not_in";
default:
return null;
}
}
}