diff --git a/src/main/java/Main.java b/src/main/java/Main.java new file mode 100644 index 0000000..610356b --- /dev/null +++ b/src/main/java/Main.java @@ -0,0 +1,37 @@ +import java.util.ArrayList; +import java.util.List; + +import generators.ASTGenerator; +import models.objectOrientedTransfer.*; + +public class Main { + + public static void main(String[] args) { + List srcEdges = new ArrayList<>(); + List dstEdges = new ArrayList<>(); + ObjectNode companies = new ObjectNode("Companies"); + ObjectNode company = new ObjectNode("Company"); + ObjectNode customers = new ObjectNode("Customers"); + ObjectNode customer = new ObjectNode("Customer"); + ObjectNode address = new ObjectNode("String"); +// ReferenceEdge srcEdge = new ReferenceEdge(companies, company, "company"); + ReferenceEdge srcEdge = new ReferenceEdge(companies, company, "company", "String"); + srcEdges.add(srcEdge); +// ReferenceEdge dstEdge = new ReferenceEdge(customers, customer, "customer"); + ReferenceEdge dstEdge = new ReferenceEdge(customers, customer, "customer", "String"); + dstEdges.add(dstEdge); + List relations = new ArrayList<>(); + Relation transferRelation = new Relation(srcEdges, dstEdges, MultiplicityValue.OneToMany); + DataTransferContext context = new DataTransferContext(relations, transferRelation, address, "address", PushPullValue.PULL); + + DataTransferDesign design; + try { + design = new DataTransferDesign(context); + System.out.println(ASTGenerator.generate(design)); + } catch (IllegalRelationException e) { + e.printStackTrace(); + } + + } + +} diff --git a/src/main/java/ast/Assignment.java b/src/main/java/ast/Assignment.java index 98f87a0..78cc19e 100644 --- a/src/main/java/ast/Assignment.java +++ b/src/main/java/ast/Assignment.java @@ -37,6 +37,6 @@ @Override public String toString() { - return left.toString() + " " + "+" + " " + right.toString(); + return left.toString() + " " + "=" + " " + right.toString(); } } diff --git a/src/main/java/generators/ASTGenerator.java b/src/main/java/generators/ASTGenerator.java new file mode 100644 index 0000000..8ed2456 --- /dev/null +++ b/src/main/java/generators/ASTGenerator.java @@ -0,0 +1,262 @@ +package generators; + +import java.util.ArrayList; +import java.util.List; + +import ast.*; +import models.algebra.Type; +import models.dataConstraintModel.MapType; +import models.objectOrientedTransfer.*; + +public class ASTGenerator { + public static final String getterPrefix = "get"; + public static final String setterPrefix = "set"; + public static final String updateMethodPrefix = "update"; + public static final String idPostfix = "Id"; + public static final String mapPostfix = "Map"; + public static final String mapGet = "get"; + public static final String mapPut = "put"; + + public static String toComponentName(String name) { + return name.substring(0, 1).toUpperCase() + name.substring(1); + } + + public static String toVariableName(String name) { + return name.substring(0, 1).toLowerCase() + name.substring(1); + } + + public static Codebase generate(DataTransferDesign dataTransferDesign) { + Codebase codebase = new Codebase(); + DeltaComplex deltaComplex = dataTransferDesign.getDeltaComplex(); + for (Delta delta: deltaComplex.split()) { + codebase = weaveDelta(codebase, delta); + } + return codebase; + } + + public static Codebase weaveDelta(Codebase codebase, Delta delta) { + List primitiveDeltas = delta.split(); + if (primitiveDeltas.size() == 1) { + return weavePrimitiveDelta(codebase, primitiveDeltas.getFirst()); + } else { + // To do. + return codebase; + } + } + + public static Codebase weavePrimitiveDelta(Codebase codebase, PrimitiveDelta primitiveDelta) { + if (primitiveDelta instanceof PrimitivePullDelta) { + codebase = weavePrimitivePullDelta(codebase, (PrimitivePullDelta) primitiveDelta); + } else if (primitiveDelta instanceof PrimitivePullPushDelta) { + codebase = weavePrimitivePullPushDelta(codebase, (PrimitivePullPushDelta) primitiveDelta); + } else if (primitiveDelta instanceof PrimitivePushDelta) { + codebase = weavePrimitivePushDelta(codebase, (PrimitivePushDelta) primitiveDelta); + } + return codebase; + } + + private static Codebase weavePrimitivePullDelta(Codebase codebase, PrimitivePullDelta primitivePullDelta) { + ReferenceEdge pullEdge1 = primitivePullDelta.getPullEdge1(); + ReferenceEdge pullEdge2 = primitivePullDelta.getPullEdge2(); + ObjectNode obj1 = (ObjectNode) pullEdge1.getSource(); + ObjectNode obj2 = (ObjectNode) pullEdge1.getDestination(); + ObjectNode obj3 = (ObjectNode) pullEdge2.getDestination(); + String name1 = toComponentName(obj1.getName()); + String name2 = toComponentName(obj2.getName()); + String name3 = toComponentName(obj3.getName()); + TypeDeclaration class1 = createClass(codebase, name1); + TypeDeclaration class2 = createClass(codebase, name2); + TypeDeclaration class3 = createClass(codebase, name3); + models.algebra.Type type1 = codebase.getComponentType(name1); + models.algebra.Type type2 = codebase.getComponentType(name2); + models.algebra.Type type3 = codebase.getComponentType(name3); + FieldDeclaration field12 = createField(class1, pullEdge1.getName(), type2); // class1 -> class2 (PULL) + FieldDeclaration field23 = null; + models.algebra.Type keyType = null; + if (!pullEdge2.toMany()) { + field23 = createField(class2, pullEdge2.getName(), type3); // class2 -> class3 (PULL) + } else { + MapType typeKeyToType3 = codebase.getMapType(pullEdge2.getKeyTypeName(), name3); + keyType = typeKeyToType3.getKeyType(); + field23 = createField(class2, pullEdge2.getName() + mapPostfix, typeKeyToType3); // class2 -> {class3} (PULL) + } + FieldDeclaration field13 = createField(class1, pullEdge2.getName(), type3); // class1 -> class3 (create) + + // Construct getter method + MethodDeclaration getter = createMethod(class2, getterPrefix + toComponentName(pullEdge2.getName())); + ReturnStatement return23 = new ReturnStatement(); + if (!pullEdge2.toMany()) { + return23.setExpression(new FieldAccess(new ThisExpression(), field23.getName())); // return this.name3; + } else { + VariableDeclaration idVar = new VariableDeclaration(keyType, pullEdge2.getName() + idPostfix); + getter.addParameter(idVar); + FieldAccess field3 = new FieldAccess(field23.getName()); + List args = new ArrayList<>(); + args.add(new Variable(idVar.getName())); + MethodInvocation callGetter = new MethodInvocation(field3, mapGet, args); // name3Map.get(name3Id) + return23.setExpression(callGetter); // return name3Map.get(name3Id); + } + getter.addStatement(return23); + getter.setReturnType(type3); + + // Construct coordinator method + MethodDeclaration coordionator = createMethod(class1, updateMethodPrefix + toComponentName(pullEdge2.getName())); + FieldAccess field3 = new FieldAccess(new ThisExpression(), field13.getName()); // this.name3 + FieldAccess field2 = new FieldAccess(field12.getName()); + List args = new ArrayList<>(); + if (pullEdge2.toMany()) { + VariableDeclaration idVar = new VariableDeclaration(keyType, pullEdge2.getName() + idPostfix); + coordionator.addParameter(idVar); + args.add(new Variable(idVar.getName())); // name2.getName3(name3Id) + } + MethodInvocation callGetter = new MethodInvocation(field2, getter.getName(), args); // name2.getName3() + Assignment assignment = new Assignment(field3, callGetter); // this.name3 = name2.getName3(); + ExpressionStatement assignmentStatement = new ExpressionStatement(assignment); + coordionator.addStatement(assignmentStatement); + return codebase; + } + + private static Codebase weavePrimitivePullPushDelta(Codebase codebase, PrimitivePullPushDelta primitivePullPushDelta) { + ReferenceEdge pullEdge = primitivePullPushDelta.getPullEdge(); + ReferenceEdge pushEdge = primitivePullPushDelta.getPushEdge(); + ObjectNode obj1 = (ObjectNode) pullEdge.getSource(); + ObjectNode obj2 = (ObjectNode) pullEdge.getDestination(); + ObjectNode obj3 = (ObjectNode) pushEdge.getDestination(); + String name1 = toComponentName(obj1.getName()); + String name2 = toComponentName(obj2.getName()); + String name3 = toComponentName(obj3.getName()); + TypeDeclaration class1 = createClass(codebase, name1); + TypeDeclaration class2 = createClass(codebase, name2); + TypeDeclaration class3 = createClass(codebase, name3); + models.algebra.Type type1 = codebase.getComponentType(name1); + models.algebra.Type type2 = codebase.getComponentType(name2); + models.algebra.Type type3 = codebase.getComponentType(name3); + FieldDeclaration field12 = createField(class1, pullEdge.getName(), type2); // class1 -> class2 (PULL) + FieldDeclaration field13 = null; + models.algebra.Type keyType = null; + if (!pushEdge.toMany()) { + field13 = createField(class1, pushEdge.getName(), type3); // class1 -> class3 (PUSH) + } else { + MapType typeKeyToType3 = codebase.getMapType(pushEdge.getKeyTypeName(), name3); + keyType = typeKeyToType3.getKeyType(); + field13 = createField(class1, pushEdge.getName() + mapPostfix, typeKeyToType3); // class1 -> {class3} (PUSH) + } + FieldDeclaration field32 = createField(class3, pullEdge.getName(), type2); // class3 -> class2 (create) + + // Construct setter method + MethodDeclaration setter = null; + if (!pushEdge.toMany()) { + setter = createMethod(class3, setterPrefix + toComponentName(name2)); + } else { + setter = createConstructor(class3); + } + VariableDeclaration param2 = new VariableDeclaration(type2, toVariableName(name2)); + setter.addParameter(param2); + FieldAccess field2 = new FieldAccess(new ThisExpression(), field32.getName()); // this.name2 + Assignment assignment = new Assignment(field2, new Variable(toVariableName(name2))); // this.name2 = name2; + ExpressionStatement assignmentStatement = new ExpressionStatement(assignment); + setter.addStatement(assignmentStatement); + + // Construct coordinator method + MethodDeclaration coordionator = createMethod(class1, updateMethodPrefix + toComponentName(name2)); + List args = new ArrayList<>(); + args.add(new FieldAccess(field12.getName())); + FieldAccess field3 = new FieldAccess(field13.getName()); + if (!pushEdge.toMany()) { + MethodInvocation callSetter = new MethodInvocation(field3, setter.getName(), args); // name3.setName2(name2) + coordionator.addStatement(new ExpressionStatement(callSetter)); + } else { + VariableDeclaration idVar = new VariableDeclaration(keyType, pushEdge.getName() + idPostfix); + coordionator.addParameter(idVar); + ClassInstanceCreation callConstructor = new ClassInstanceCreation((SimpleType) type3.getImplementationType(), args); // new Name3(name2) + args = new ArrayList<>(); + args.add(new Variable(idVar.getName())); + args.add(callConstructor); + coordionator.addStatement(new ExpressionStatement(new MethodInvocation(field3, mapPut, args))); // name3Map.put(name3Id, new new Name3(name2)); + } + return codebase; + } + + private static Codebase weavePrimitivePushDelta(Codebase codebase, PrimitivePushDelta primitivePushDelta) { + ReferenceEdge pushEdge1 = primitivePushDelta.getPushEdge1(); + ReferenceEdge pushEdge2 = primitivePushDelta.getPushEdge2(); + ObjectNode obj1 = (ObjectNode) pushEdge1.getSource(); + ObjectNode obj2 = (ObjectNode) pushEdge1.getDestination(); + ObjectNode obj3 = (ObjectNode) pushEdge2.getDestination(); + String name1 = toComponentName(obj1.getName()); + String name2 = toComponentName(obj2.getName()); + String name3 = toComponentName(obj3.getName()); + TypeDeclaration class1 = createClass(codebase, name1); + TypeDeclaration class2 = createClass(codebase, name2); + TypeDeclaration class3 = createClass(codebase, name3); + models.algebra.Type type1 = codebase.getComponentType(name1); + models.algebra.Type type2 = codebase.getComponentType(name2); + models.algebra.Type type3 = codebase.getComponentType(name3); + FieldDeclaration field12 = createField(class1, pushEdge1.getName(), type2); // class1 -> class2 (PUSH) + FieldDeclaration field23 = createField(class2, pushEdge2.getName(), type3); // class2 -> class3 (PUSH) + FieldDeclaration field31 = createField(class3, toVariableName(name1), type1); // class3 -> class1 (create) + + // Construct setter in class3 + MethodDeclaration setter3 = createMethod(class3, setterPrefix + toComponentName(name1)); + VariableDeclaration param1 = new VariableDeclaration(type1, name1); + setter3.addParameter(param1); + FieldAccess field1 = new FieldAccess(new ThisExpression(), field31.getName()); // this.name1 + Assignment assignment = new Assignment(field1, new Variable(toVariableName(name1))); // this.name1 = name1; + ExpressionStatement assignmentStatement = new ExpressionStatement(assignment); + setter3.addStatement(assignmentStatement); + + // Construct setter in class2 + MethodDeclaration setter2 = createMethod(class2, setterPrefix + toComponentName(name1)); + param1 = new VariableDeclaration(type1, toVariableName(name1)); + setter2.addParameter(param1); + FieldAccess field3 = new FieldAccess(field23.getName()); + List args = new ArrayList<>(); + args.add(new Variable(param1.getName())); + MethodInvocation callSetter = new MethodInvocation(field3, setter3.getName(), args); // name3.setName1(name1) + setter2.addStatement(new ExpressionStatement(callSetter)); + + // Construct coordinator method + MethodDeclaration coordionator = createMethod(class1, updateMethodPrefix + toComponentName(name1)); + FieldAccess field2 = new FieldAccess(field12.getName()); + args = new ArrayList<>(); + args.add(new ThisExpression()); + callSetter = new MethodInvocation(field2, setter2.getName(), args); // name2.setName1(this) + coordionator.addStatement(new ExpressionStatement(callSetter)); + return codebase; + } + + private static TypeDeclaration createClass(Codebase codebase, String name) { + if (codebase.getCompilationUnit(name) != null) return codebase.getCompilationUnit(name).types().getFirst(); + TypeDeclaration type = new TypeDeclaration(name); + CompilationUnit compilationUnit = new CompilationUnit(type); + codebase.addCompilationUnit(name, compilationUnit); + return type; + } + + private static MethodDeclaration createMethod(TypeDeclaration type, String name) { + for (MethodDeclaration method: type.getMethods()) { + if (method.getName().equals(name)) return method; + } + MethodDeclaration method = new MethodDeclaration(name); + type.addMethod(method); + return method; + } + + private static MethodDeclaration createConstructor(TypeDeclaration type) { + for (MethodDeclaration method: type.getMethods()) { + if (method.getName().equals(type.getTypeName())) return method; + } + MethodDeclaration method = new MethodDeclaration(type.getTypeName(), true); // constructor + type.addMethod(method); + return method; + } + + private static FieldDeclaration createField(TypeDeclaration type, String fieldName, models.algebra.Type fieldType) { + for (FieldDeclaration field: type.getFields()) { + if (field.getName().equals(fieldName)) return field; + } + FieldDeclaration field = new FieldDeclaration(fieldType, fieldName); + type.addField(field); + return field; + } +} diff --git a/src/main/java/generators/Codebase.java b/src/main/java/generators/Codebase.java new file mode 100644 index 0000000..2b5ae0f --- /dev/null +++ b/src/main/java/generators/Codebase.java @@ -0,0 +1,63 @@ +package generators; + +import java.util.Collection; +import java.util.HashMap; +import java.util.Map; + +import ast.CompilationUnit; +import ast.SimpleType; +import models.algebra.Type; +import models.dataConstraintModel.MapType; + +public class Codebase { + private Map classes = new HashMap<>(); + private Map componentTypes = new HashMap<>(); + private Map standardTypes = new HashMap<>(); + + public Codebase() { + } + + public Collection getCompilationUnits() { + return classes.values(); + } + + public CompilationUnit getCompilationUnit(String name) { + return classes.get(name); + } + + public models.algebra.Type getComponentType(String typeName) { + return componentTypes.get(typeName); + } + + public models.algebra.Type getOrCreateStandardType(String typeName) { + models.algebra.Type type = standardTypes.get(typeName); + if (type == null) { + type = new models.algebra.Type(typeName, new SimpleType(typeName)); + standardTypes.put(typeName, type); + } + return type; + } + + public MapType getMapType(String keyTypeName, String valueTypeName) { + models.algebra.Type valueType = componentTypes.get(valueTypeName); + if (valueType == null) { + valueType = getOrCreateStandardType(valueTypeName); + } + models.algebra.Type keyType = getOrCreateStandardType(keyTypeName); + return new MapType("map", new SimpleType("HashMap<>"), new SimpleType("Map<" + keyTypeName + ", " + valueTypeName + ">"), keyType, valueType); + } + + public void addCompilationUnit(String name, CompilationUnit compilationUnit) { + classes.put(name, compilationUnit); + models.algebra.Type newType = new models.algebra.Type(name, new SimpleType(name)); + componentTypes.put(name, newType); + } + + public String toString() { + String code = ""; + for (CompilationUnit cu: classes.values()) { + code += cu.toString(); + } + return code; + } +} diff --git a/src/main/java/models/dataConstraintModel/MapType.java b/src/main/java/models/dataConstraintModel/MapType.java new file mode 100644 index 0000000..b9f3233 --- /dev/null +++ b/src/main/java/models/dataConstraintModel/MapType.java @@ -0,0 +1,49 @@ +package models.dataConstraintModel; + +import models.algebra.Type; + +public class MapType extends Type { + protected Type keyType = null; + protected Type valueType = null; + + public MapType(String typeName, ITypeImpl implementationType) { + super(typeName, implementationType); + } + + public MapType(String typeName, ITypeImpl implementationType, ITypeImpl interfaceType) { + super(typeName, implementationType, interfaceType); + } + + public MapType(String typeName, ITypeImpl implementationType, ITypeImpl interfaceType, Type parentMapType) { + super(typeName, implementationType, interfaceType, parentMapType); + } + + public MapType(String typeName, ITypeImpl implementationType, ITypeImpl interfaceType, Type keyType, Type valueType) { + super(typeName, implementationType, interfaceType); + this.keyType = keyType; + this.valueType = valueType; + } + + public MapType(String typeName, ITypeImpl implementationType, ITypeImpl interfaceType, Type parentMapType, Type keyType, Type valueType) { + super(typeName, implementationType, interfaceType, parentMapType); + this.keyType = keyType; + this.valueType = valueType; + } + + public Type getKeyType() { + return keyType; + } + + public void setKeyType(Type keyType) { + this.keyType = keyType; + } + + public Type getValueType() { + return valueType; + } + + public void setValueType(Type valueType) { + this.valueType = valueType; + } + +} diff --git a/src/main/java/models/objectOrientedTransfer/DataTransferContext.java b/src/main/java/models/objectOrientedTransfer/DataTransferContext.java index 611fcfe..2bc8f02 100644 --- a/src/main/java/models/objectOrientedTransfer/DataTransferContext.java +++ b/src/main/java/models/objectOrientedTransfer/DataTransferContext.java @@ -15,8 +15,7 @@ private String dataName; private PushPullValue transferStyle; - public DataTransferContext(List relations, Relation transferRelation, - ObjectNode dataType, String dataName, PushPullValue transferStyle, MultiplicityValue transferMultiplicity) { + public DataTransferContext(List relations, Relation transferRelation, ObjectNode dataType, String dataName, PushPullValue transferStyle) { this.relations = relations; this.transferRelation = transferRelation; this.dataType = dataType; diff --git a/src/main/java/models/objectOrientedTransfer/DataTransferDesign.java b/src/main/java/models/objectOrientedTransfer/DataTransferDesign.java index b66a73f..a650dac 100644 --- a/src/main/java/models/objectOrientedTransfer/DataTransferDesign.java +++ b/src/main/java/models/objectOrientedTransfer/DataTransferDesign.java @@ -29,51 +29,47 @@ // Construct all deltas. Stack deltaStack = new Stack<>(); ReferenceEdge bottomReference = constructDefaultDeltas(transferContext, deltaStack); - Delta dataTransferDelta = deltaStack.pop(); - if (dataTransferDelta != null) { - // Add the data transfer delta. - ObjectNode srcObj = (ObjectNode) bottomReference.getSource(); - ObjectNode dstObj = (ObjectNode) transferContext.getDataType(); - String dataName = dstObj.getName(); - dataName = dataName.substring(0, 1).toLowerCase() + dataName.substring(1); - ReferenceEdge dataEdge = new ReferenceEdge(srcObj, dstObj, dataName); - dataTransferDelta = dataTransferDelta.combine(new PrimitivePullPushDelta(dataEdge, bottomReference, dataName)); // PUSH data transfer - DeltaComplex deltaComplex = new DeltaComplex(dataTransferDelta); - - // Add initialization deltas. - while (!deltaStack.isEmpty()) { - deltaComplex.attach(deltaStack.pop()); - } - return deltaComplex; + + // Add the data transfer delta. + ObjectNode srcObj = (ObjectNode) bottomReference.getSource(); + ObjectNode dstObj = (ObjectNode) transferContext.getDataType(); + String dataName = transferContext.getDataName(); + ReferenceEdge dataEdge = new ReferenceEdge(srcObj, dstObj, dataName); + PrimitivePullPushDelta primDelta = new PrimitivePullPushDelta(dataEdge, bottomReference, dataName); // PUSH data transfer + Delta dataTransferDelta = new Delta(primDelta); + DeltaComplex deltaComplex = new DeltaComplex(dataTransferDelta); + + // Add initialization deltas. + while (!deltaStack.isEmpty()) { + deltaComplex.attach(deltaStack.pop()); } + return deltaComplex; } else { // Broadcasting } } else { - if (transferContext.getTransferMultiplicity() == MultiplicityValue.ManyToOne + if (transferContext.getTransferMultiplicity() == MultiplicityValue.OneToMany || transferContext.getTransferMultiplicity() == MultiplicityValue.OneToOne) { // Simple PULL // Construct all deltas. Stack deltaStack = new Stack<>(); ReferenceEdge bottomReference = constructDefaultDeltas(transferContext, deltaStack); - Delta dataTransferDelta = deltaStack.pop(); - if (dataTransferDelta != null) { - // Add the data transfer delta. - ObjectNode srcObj = (ObjectNode) bottomReference.getDestination(); - ObjectNode dstObj = (ObjectNode) transferContext.getDataType(); - String dataName = dstObj.getName(); - dataName = dataName.substring(0, 1).toLowerCase() + dataName.substring(1); - ReferenceEdge dataEdge = new ReferenceEdge(srcObj, dstObj, dataName); - dataTransferDelta = dataTransferDelta.combine(new PrimitivePullDelta(bottomReference, dataEdge, dataName)); // PULL data transfer - DeltaComplex deltaComplex = new DeltaComplex(dataTransferDelta); - - // Add initialization deltas. - while (!deltaStack.isEmpty()) { - deltaComplex.attach(deltaStack.pop()); - } - return deltaComplex; + + // Add the data transfer delta. + ObjectNode srcObj = (ObjectNode) bottomReference.getDestination(); + ObjectNode dstObj = (ObjectNode) transferContext.getDataType(); + String dataName = transferContext.getDataName(); + ReferenceEdge dataEdge = new ReferenceEdge(srcObj, dstObj, dataName); + PrimitivePullDelta primDelta = new PrimitivePullDelta(bottomReference, dataEdge, dataName); // PULL data transfer + Delta dataTransferDelta = new Delta(primDelta); + DeltaComplex deltaComplex = new DeltaComplex(dataTransferDelta); + + // Add initialization deltas. + while (!deltaStack.isEmpty()) { + deltaComplex.attach(deltaStack.pop()); } + return deltaComplex; } else { // Data collecting } @@ -118,7 +114,7 @@ throw new IllegalRelationException(); } } else { - if (newDstResource.get(i).getMultiplicity() == MultiplicityValue.OneToMany) { + if (newDstResource.get(i).toMany()) { toOne = false; } if (toOne) { @@ -128,48 +124,49 @@ } } } + + // 1) Create container passing deltas. + List primitiveDeltaList = new ArrayList<>(); + for (ReferenceEdge dstEdge: oneDestination) { + srcObj = (ObjectNode) prevReference.getSource(); + dstObj = (ObjectNode) dstEdge.getDestination(); + String dataName = dstObj.getName(); + dataName = dataName.substring(0, 1).toLowerCase() + dataName.substring(1); + primitiveDeltaList.add(new PrimitivePullDelta(prevReference, dstEdge, dataName)); + prevReference = new ReferenceEdge(srcObj, dstObj, dataName); + } + for (int i = 0; i < newSrcResource.size(); i++) { + ReferenceEdge srcEdge = newSrcResource.get(i); + if (i < srcResource.size()) { + if (!srcResource.get(i).equals(srcEdge)) { + throw new IllegalRelationException(); + } + } else { + srcObj = (ObjectNode) srcEdge.getDestination(); + dstObj = (ObjectNode) prevReference.getDestination(); + String dataName = dstObj.getName(); + dataName = dataName.substring(0, 1).toLowerCase() + dataName.substring(1); + primitiveDeltaList.add(new PrimitivePullPushDelta(prevReference, srcEdge, dataName)); + Delta delta = null; + for (PrimitiveDelta primDelta: primitiveDeltaList) { + if (delta == null) { + delta = new Delta(primDelta); + } else { + delta = new Delta(primDelta, delta); + } + } + deltaStack.push(delta); // add a container passing delta + primitiveDeltaList.clear(); + prevReference = new ReferenceEdge(srcObj, dstObj, dataName); + } + } + if (!toOne && ((transferStyle == PushPullValue.PUSH && (relation.getMultiplicity() == MultiplicityValue.ManyToOne || relation.getMultiplicity() == MultiplicityValue.OneToOne)) || (transferStyle != PushPullValue.PUSH && (relation.getMultiplicity() == MultiplicityValue.OneToMany || relation.getMultiplicity() == MultiplicityValue.OneToOne)))) { // If the specified multiplicity of destination objects does not match to their potential multiplicity, // then the reference to select one destination object from potential multiple objects is needed. - // 1) Create container passing deltas. - List primitiveDeltaList = new ArrayList<>(); - for (ReferenceEdge dstEdge: oneDestination) { - srcObj = (ObjectNode) prevReference.getSource(); - dstObj = (ObjectNode) dstEdge.getDestination(); - String dataName = dstObj.getName(); - dataName = dataName.substring(0, 1).toLowerCase() + dataName.substring(1); - primitiveDeltaList.add(new PrimitivePullDelta(prevReference, dstEdge, dataName)); - prevReference = new ReferenceEdge(srcObj, dstObj, dataName); - } - for (int i = 0; i < newSrcResource.size(); i++) { - ReferenceEdge srcEdge = newSrcResource.get(i); - if (i < srcResource.size()) { - if (!srcResource.get(i).equals(srcEdge)) { - throw new IllegalRelationException(); - } - } else { - srcObj = (ObjectNode) srcEdge.getDestination(); - dstObj = (ObjectNode) prevReference.getDestination(); - String dataName = dstObj.getName(); - dataName = dataName.substring(0, 1).toLowerCase() + dataName.substring(1); - primitiveDeltaList.add(new PrimitivePullPushDelta(prevReference, srcEdge, dataName)); - Delta delta = null; - for (PrimitiveDelta primDelta: primitiveDeltaList) { - if (delta == null) { - delta = new Delta(primDelta); - } else { - delta = new Delta(primDelta, delta); - } - } - deltaStack.push(delta); // add a container passing delta - primitiveDeltaList.clear(); - prevReference = new ReferenceEdge(srcObj, dstObj, dataName); - } - } - // 2) Create a component identifying delta. PrimitiveDelta componentSelectingDelta = null; for (ReferenceEdge dstEdge: manyDestinations) { diff --git a/src/main/java/models/objectOrientedTransfer/Delta.java b/src/main/java/models/objectOrientedTransfer/Delta.java index 08b0c0e..1a8a80d 100644 --- a/src/main/java/models/objectOrientedTransfer/Delta.java +++ b/src/main/java/models/objectOrientedTransfer/Delta.java @@ -4,8 +4,7 @@ import java.util.List; /** - * A program structure related to specific data transfer. - * Deltas can be generated from a data transfer context. + * A closed delta, which is executable on some preconditions. * * @author Nitta * @@ -42,10 +41,24 @@ return pushEdges; } + /** + * binding composition + * (this + delta) + * + * @param delta + * @return this + delta + */ public Delta combine(PrimitiveDelta delta) { return new Delta(delta, this); } + /** + * binding composition + * (this + delta) + * + * @param delta + * @return this + delta + */ public Delta combine(Delta delta) { Delta preDelta = this.copy(); for (PrimitiveDelta atomicDelta: delta.split()) { @@ -54,6 +67,11 @@ return preDelta; } + /** + * if this = d1 + d2 + ... + dn + * + * @return [d1, d2, ..., dn] + */ public List split() { if (subDelta == null) { List atomicDeltaSequence = new ArrayList<>(); @@ -66,6 +84,9 @@ } public Delta copy() { + if (subDelta == null) { + return new Delta(bottomDelta.copy()); + } return new Delta(bottomDelta.copy(), subDelta.copy()); } } diff --git a/src/main/java/models/objectOrientedTransfer/DeltaComplex.java b/src/main/java/models/objectOrientedTransfer/DeltaComplex.java index 0ede815..f301548 100644 --- a/src/main/java/models/objectOrientedTransfer/DeltaComplex.java +++ b/src/main/java/models/objectOrientedTransfer/DeltaComplex.java @@ -3,6 +3,12 @@ import java.util.ArrayList; import java.util.List; +/** + * A dependency-composed closed delta + * + * @author Nitta + * + */ public class DeltaComplex { private Delta frontierDelta; private DeltaComplex subComplex = null; @@ -16,11 +22,22 @@ this.subComplex = subComplex; } + /** + * dependency composition + * (this = delta | this) + * + * @param delta + */ public void attach(Delta delta) { this.subComplex = this.copy(); this.frontierDelta = delta; } + /** + * if this = d1 | d2 | ... | dn + * + * @return [d1, d2, ..., dn] + */ public List split() { if (subComplex == null) { List deltaSequence = new ArrayList<>(); @@ -32,6 +49,17 @@ return deltaSequence; } + public DeltaComplex flatten() { + DeltaComplex flattenComplex = subComplex; + if (flattenComplex != null) { + flattenComplex = flattenComplex.flatten(); + } + for (PrimitiveDelta primDelta: frontierDelta.split().reversed()) { + flattenComplex = new DeltaComplex(new Delta(primDelta), flattenComplex); + } + return flattenComplex; + } + public Delta collapse() { Delta allDelta = null; for (Delta delta: this.split()) { @@ -45,7 +73,9 @@ } public DeltaComplex copy() { - DeltaComplex newComplex = new DeltaComplex(frontierDelta.copy(), subComplex.copy()); - return newComplex; + if (subComplex == null) { + return new DeltaComplex(frontierDelta.copy()); + } + return new DeltaComplex(frontierDelta.copy(), subComplex.copy()); } } diff --git a/src/main/java/models/objectOrientedTransfer/PrimitiveDelta.java b/src/main/java/models/objectOrientedTransfer/PrimitiveDelta.java index 8b0c645..3c7099d 100644 --- a/src/main/java/models/objectOrientedTransfer/PrimitiveDelta.java +++ b/src/main/java/models/objectOrientedTransfer/PrimitiveDelta.java @@ -2,6 +2,12 @@ import java.util.List; +/** + * A primitive open/closed delta, which is a minimal program fragment to transfer a reference. + * + * @author Nitta + * + */ abstract public class PrimitiveDelta { protected String dataName; diff --git a/src/main/java/models/objectOrientedTransfer/PrimitivePullDelta.java b/src/main/java/models/objectOrientedTransfer/PrimitivePullDelta.java index 7c68e94..bf3037f 100644 --- a/src/main/java/models/objectOrientedTransfer/PrimitivePullDelta.java +++ b/src/main/java/models/objectOrientedTransfer/PrimitivePullDelta.java @@ -37,6 +37,14 @@ return (ObjectNode) pullEdge2.getDestination(); } + public ReferenceEdge getPullEdge1() { + return pullEdge1; + } + + public ReferenceEdge getPullEdge2() { + return pullEdge2; + } + public PrimitivePullDelta copy() { return new PrimitivePullDelta(pullEdge1, pullEdge2, dataName); } diff --git a/src/main/java/models/objectOrientedTransfer/PrimitivePullPushDelta.java b/src/main/java/models/objectOrientedTransfer/PrimitivePullPushDelta.java index 8f210ed..8fa3e07 100644 --- a/src/main/java/models/objectOrientedTransfer/PrimitivePullPushDelta.java +++ b/src/main/java/models/objectOrientedTransfer/PrimitivePullPushDelta.java @@ -37,6 +37,14 @@ return (ObjectNode) pullEdge.getDestination(); } + public ReferenceEdge getPullEdge() { + return pullEdge; + } + + public ReferenceEdge getPushEdge() { + return pushEdge; + } + public PrimitivePullPushDelta copy() { return new PrimitivePullPushDelta(pullEdge, pushEdge, dataName); } diff --git a/src/main/java/models/objectOrientedTransfer/PrimitivePushDelta.java b/src/main/java/models/objectOrientedTransfer/PrimitivePushDelta.java index 1fd0614..63d0635 100644 --- a/src/main/java/models/objectOrientedTransfer/PrimitivePushDelta.java +++ b/src/main/java/models/objectOrientedTransfer/PrimitivePushDelta.java @@ -37,6 +37,14 @@ return (ObjectNode) pushEdge1.getSource(); } + public ReferenceEdge getPushEdge1() { + return pushEdge1; + } + + public ReferenceEdge getPushEdge2() { + return pushEdge2; + } + @Override public PrimitivePushDelta copy() { return new PrimitivePushDelta(pushEdge1, pushEdge2, dataName); diff --git a/src/main/java/models/objectOrientedTransfer/ReferenceEdge.java b/src/main/java/models/objectOrientedTransfer/ReferenceEdge.java index 7ffd092..07e73f8 100644 --- a/src/main/java/models/objectOrientedTransfer/ReferenceEdge.java +++ b/src/main/java/models/objectOrientedTransfer/ReferenceEdge.java @@ -5,12 +5,26 @@ public class ReferenceEdge extends Edge { protected String name; protected MultiplicityValue multiplicity; + protected String keyTypeName = null; public ReferenceEdge(ObjectNode src, ObjectNode dst, String name) { super(src, dst); this.name = name; this.multiplicity = MultiplicityValue.OneToOne; } + + public ReferenceEdge(ObjectNode src, ObjectNode dst, String name, MultiplicityValue multiplicity) { + super(src, dst); + this.name = name; + this.multiplicity = multiplicity; + } + + public ReferenceEdge(ObjectNode src, ObjectNode dst, String name, String keyTypeName) { + super(src, dst); + this.name = name; + this.multiplicity = MultiplicityValue.OneToMany; + this.keyTypeName = keyTypeName; + } public String getName() { return name; @@ -27,5 +41,12 @@ public void setMultiplicity(MultiplicityValue multiplicity) { this.multiplicity = multiplicity; } + + public boolean toMany() { + return multiplicity == MultiplicityValue.OneToMany || multiplicity == MultiplicityValue.ManyToMany; + } + public String getKeyTypeName() { + return keyTypeName; + } } diff --git a/src/main/java/models/objectOrientedTransfer/Relation.java b/src/main/java/models/objectOrientedTransfer/Relation.java index 2938b37..c61d852 100644 --- a/src/main/java/models/objectOrientedTransfer/Relation.java +++ b/src/main/java/models/objectOrientedTransfer/Relation.java @@ -7,6 +7,12 @@ private List dstResource; private MultiplicityValue multiplicity; + public Relation(List srcResource, List dstResource, MultiplicityValue multiplicity) { + this.srcResource = srcResource; + this.dstResource = dstResource; + this.multiplicity = multiplicity; + } + public List getSrcResource() { return srcResource; }