/**
* Licensed to the Austrian Association for Software Tool Integration (AASTI)
* under one or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information regarding copyright
* ownership. The AASTI licenses this file to you 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.openengsb.core.ekb.api.transformation;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.Set;
import org.openengsb.core.api.model.ModelDescription;
import com.google.common.base.Objects;
/**
* Describes all steps to transform an object of the source class into an object of the target class.
*/
public class TransformationDescription {
private ModelDescription sourceModel;
private ModelDescription targetModel;
private List<TransformationStep> steps;
private Map<String, Set<String>> propertyConnections;
private String fileName;
private String id;
public TransformationDescription(ModelDescription sourceModel, ModelDescription targetModel) {
this(sourceModel, targetModel, null);
}
public TransformationDescription(ModelDescription sourceModel, ModelDescription targetModel, String id) {
this.sourceModel = sourceModel;
this.targetModel = targetModel;
this.id = id;
steps = new ArrayList<TransformationStep>();
}
/**
* Adds a transformation step to this description
*/
public void addStep(String operationName, List<String> sourceFields, String targetField,
Map<String, String> parameters) {
TransformationStep step = new TransformationStep();
step.setOperationName(operationName);
step.setSourceFields(sourceFields.toArray(new String[sourceFields.size()]));
step.setTargetField(targetField);
step.setOperationParams(parameters);
steps.add(step);
}
/**
* Adds a forward transformation step to the transformation description. The value of the source field is copied to
* the target field unchanged. Both fields need to have the same object type.
*/
public void forwardField(String sourceField, String targetField) {
TransformationStep step = new TransformationStep();
step.setTargetField(targetField);
step.setSourceFields(sourceField);
step.setOperationName("forward");
steps.add(step);
}
/**
* Adds a concat transformation step to the transformation description. The values of the source fields are
* concatenated to the target field with the concat string between the source fields values. All fields need to be
* of the type String.
*/
public void concatField(String targetField, String concatString, String... sourceFields) {
TransformationStep step = new TransformationStep();
step.setTargetField(targetField);
step.setSourceFields(sourceFields);
step.setOperationParameter(TransformationConstants.CONCAT_PARAM, concatString);
step.setOperationName("concat");
steps.add(step);
}
/**
* Adds a split transformation step to the transformation description. The value of the source field is split based
* on the split string into parts. Based on the given index, the result will be set to the target field. The index
* needs to be an integer value. All fields need to be of the type String.
*/
public void splitField(String sourceField, String targetField, String splitString, String index) {
TransformationStep step = new TransformationStep();
step.setTargetField(targetField);
step.setSourceFields(sourceField);
step.setOperationParameter(TransformationConstants.SPLIT_PARAM, splitString);
step.setOperationParameter(TransformationConstants.INDEX_PARAM, index);
step.setOperationName("split");
steps.add(step);
}
/**
* Adds a split regex transformation step to the transformation description. The value of the source field is split
* based on the split string as regular expression into parts. Based on the given index, the result will be set to
* the target field. The index needs to be an integer value. All fields need to be of the type String.
*/
public void splitRegexField(String sourceField, String targetField, String regexString, String index) {
TransformationStep step = new TransformationStep();
step.setTargetField(targetField);
step.setSourceFields(sourceField);
step.setOperationParameter(TransformationConstants.REGEX_PARAM, regexString);
step.setOperationParameter(TransformationConstants.INDEX_PARAM, index);
step.setOperationName("splitRegex");
steps.add(step);
}
/**
* Adds a map transformation step to the transformation description. The value of the source field is mapped based
* on the mapping to another value which is forwarded to the target field. The values in the models need to be
* working with the values of the mapping (e.g. assigning 'hello' to Integer field will not work).
*/
public void mapField(String sourceField, String targetField, Map<String, String> mapping) {
TransformationStep step = new TransformationStep();
step.setTargetField(targetField);
step.setSourceFields(sourceField);
step.setOperationParams(mapping);
step.setOperationName("map");
steps.add(step);
}
/**
* Adds a substring step to the transformation description. The value of the source field is taken and it is tried
* to build the substring from the given index from to the given index to. From and to must be Integers written as
* String, the value of the source field must also be a String.
*/
public void substringField(String sourceField, String targetField, String from, String to) {
TransformationStep step = new TransformationStep();
step.setTargetField(targetField);
step.setSourceFields(sourceField);
step.setOperationParameter(TransformationConstants.SUBSTRING_FROM_PARAM, from);
step.setOperationParameter(TransformationConstants.SUBSTRING_TO_PARAM, to);
step.setOperationName("substring");
steps.add(step);
}
/**
* Adds a value step to the transformation description. The given value is written to the target field.
*/
public void valueField(String targetField, String value) {
TransformationStep step = new TransformationStep();
step.setTargetField(targetField);
step.setOperationParameter(TransformationConstants.VALUE_PARAM, value);
step.setOperationName("value");
steps.add(step);
}
/**
* Adds a length step to the transformation description. The step takes the object from the source field and
* calculate the length through the given method function (which needs to be implemented by the object). The result
* will be written in the target field. If the function is null, then "length" will be taken as standard function.
*/
public void lengthField(String sourceField, String targetField, String function) {
TransformationStep step = new TransformationStep();
step.setSourceFields(sourceField);
step.setTargetField(targetField);
step.setOperationParameter(TransformationConstants.LENGTH_FUNCTION_PARAM, function);
step.setOperationName("length");
steps.add(step);
}
/**
* Adds a trim step to the transformation description. The source field and the target field need to be of String
* type. Performs standard trim operation on the string of the source field and writes the result to the target
* field.
*/
public void trimField(String sourceField, String targetField) {
TransformationStep step = new TransformationStep();
step.setSourceFields(sourceField);
step.setTargetField(targetField);
step.setOperationName("trim");
steps.add(step);
}
/**
* Adds a toLower step to the transformation description. The source and the target field need to be of String type.
* Performs standard toLower operation on the string of the source field and writes the result to the target field.
*/
public void toLowerField(String sourceField, String targetField) {
TransformationStep step = new TransformationStep();
step.setSourceFields(sourceField);
step.setTargetField(targetField);
step.setOperationName("toLower");
steps.add(step);
}
/**
* Adds a toUpper step to the transformation description. The source and the target field need to be of String type.
* Performs standard toUpper operation on the string of the source field and writes the result to the target field.
*/
public void toUpperField(String sourceField, String targetField) {
TransformationStep step = new TransformationStep();
step.setSourceFields(sourceField);
step.setTargetField(targetField);
step.setOperationName("toUpper");
steps.add(step);
}
/**
* Adds a replace step to the transformation description. The source and the target field need to be of String type.
* Performs standard string replacement on the string of the source field and writes the result to the target field.
*/
public void replaceField(String sourceField, String targetField, String oldString, String newString) {
TransformationStep step = new TransformationStep();
step.setSourceFields(sourceField);
step.setTargetField(targetField);
step.setOperationParameter(TransformationConstants.REPLACE_OLD_PARAM, oldString);
step.setOperationParameter(TransformationConstants.REPLACE_NEW_PARAM, newString);
step.setOperationName("replace");
steps.add(step);
}
/**
* Adds a reverse step to the transformation description. The source and the target field need to be of String type.
* Performs standard string reversing on the string of the source field and writes the result to the target field.
*/
public void reverseField(String sourceField, String targetField) {
TransformationStep step = new TransformationStep();
step.setSourceFields(sourceField);
step.setTargetField(targetField);
step.setOperationName("reverse");
steps.add(step);
}
/**
* Adds a pad step to the transformation description. The source and the target field need to be of String type.
* Performs padding operation on the string of the source field and writes the result to the target field. The
* length describes to which size the padding should be done, the pad character describes which character to use for
* the padding. The direction describes if the padding should be done at the start or at the end. The standard value
* for the direction is at the beginning. Values for direction could be "Start" or "End".
*/
public void padField(String sourceField, String targetField, String length, String character, String direction) {
TransformationStep step = new TransformationStep();
step.setSourceFields(sourceField);
step.setTargetField(targetField);
step.setOperationParameter(TransformationConstants.PAD_LENGTH_PARAM, length);
step.setOperationParameter(TransformationConstants.PAD_CHARACTER_PARAM, character);
step.setOperationParameter(TransformationConstants.PAD_DIRECTION_PARAM, direction);
step.setOperationName("pad");
steps.add(step);
}
/**
* Adds a remove leading step to the transformation description. The source and the target field need to be of
* String type. Based on the given regular expression string the beginning of the source string will be removed
* until the given maximum length. If the length is 0, the maximum length is ignored.
*/
public void removeLeadingField(String sourceField, String targetField, String regexString, String length) {
TransformationStep step = new TransformationStep();
step.setSourceFields(sourceField);
step.setTargetField(targetField);
step.setOperationParameter(TransformationConstants.REMOVELEADING_LENGTH_PARAM, length);
step.setOperationParameter(TransformationConstants.REGEX_PARAM, regexString);
step.setOperationName("removeleading");
steps.add(step);
}
/**
* Adds an instantiate step to the transformation description. An object defined through the given target type will
* be created. For the instantiation the targetTypeInit method will be used. If this parameter is null, the
* constructor of the targetType will be used with the object type of the source object as parameter.
*/
public void instantiateField(String targetField, String targetType, String targetTypeInit, String... sourceFields) {
TransformationStep step = new TransformationStep();
step.setSourceFields(sourceFields);
step.setTargetField(targetField);
step.setOperationParameter(TransformationConstants.INSTANTIATE_TARGETTYPE_PARAM, targetType);
if (targetTypeInit != null) {
step.setOperationParameter(TransformationConstants.INSTANTIATE_INITMETHOD_PARAM, targetTypeInit);
}
step.setOperationName("instantiate");
steps.add(step);
}
public ModelDescription getSourceModel() {
return sourceModel;
}
public ModelDescription getTargetModel() {
return targetModel;
}
public List<TransformationStep> getTransformingSteps() {
return steps;
}
public String getFileName() {
return fileName;
}
public void setFileName(String fileName) {
this.fileName = fileName;
}
public String getId() {
return id;
}
public void setId(String id) {
this.id = id;
}
public Map<String, Set<String>> getPropertyConnections() {
return propertyConnections;
}
public void setPropertyConnections(Map<String, Set<String>> propertyConnections) {
this.propertyConnections = propertyConnections;
}
@Override
public int hashCode() {
Object[] obj = new Object[]{ sourceModel, steps, targetModel, id };
return Objects.hashCode(obj);
}
@Override
public boolean equals(Object obj) {
if (obj == null) {
return false;
}
if (!obj.getClass().equals(TransformationDescription.class)) {
return false;
}
TransformationDescription other = (TransformationDescription) obj;
boolean sourceEqual = Objects.equal(sourceModel, other.getSourceModel());
boolean targetEqual = Objects.equal(targetModel, other.getTargetModel());
boolean idEqual = Objects.equal(id, other.getId());
return sourceEqual && targetEqual && idEqual;
}
}