diff --git a/src/main/java/generators/ASTGenerator.java b/src/main/java/generators/ASTGenerator.java index 6050c9a..bf0d91f 100644 --- a/src/main/java/generators/ASTGenerator.java +++ b/src/main/java/generators/ASTGenerator.java @@ -15,11 +15,14 @@ public class ASTGenerator { public static final String getterPrefix = "get"; public static final String setterPrefix = "set"; + public static final String addMethodPrefix = "add"; 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 final String mapValues = "values"; + public static final String mapKeySet = "keySet"; public static String toComponentName(String name) { return name.substring(0, 1).toUpperCase() + name.substring(1); @@ -87,49 +90,99 @@ 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 field12 = null; + if (!pullEdge1.toMany()) { + field12 = createField(class1, pullEdge1.getName(), type2); // class1 -> class2 (PULL) + } else { + MapType typeKeyToType2 = codebase.getMapType(pullEdge1.getKeyTypeName(), name2); + field12 = createField(class1, pullEdge1.getName() + mapPostfix, typeKeyToType2); // class1 -> {class2} (PULL) + } FieldDeclaration field23 = null; models.algebra.Type keyType = null; if (!pullEdge2.toMany()) { - field23 = createField(class2, pullEdge2.getName(), type3); // class2 -> class3 (PULL) + 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) + field23 = createField(class2, pullEdge2.getName() + mapPostfix, typeKeyToType3); // class2 -> {class3} (PULL) } - FieldDeclaration field13 = createField(class1, pullEdge2.getName(), type3); // class1 -> class3 (create) + FieldDeclaration field13 = null; + if (!primitivePullDelta.isMultipleDefinition()) { + field13 = createField(class1, pullEdge2.getName(), type3); // class1 -> class3 (define) + } else { + String keyName = pullEdge2.getKeyTypeName(); + if (keyName == null) { + keyName = pullEdge1.getKeyTypeName(); + } + MapType typeKeyToType3 = codebase.getMapType(keyName, name3); + keyType = typeKeyToType3.getKeyType(); + field13 = createField(class1, pullEdge2.getName() + mapPostfix, typeKeyToType3); // class1 -> {class3} (define) + } // 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; + 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); + MethodInvocation callGetter = new MethodInvocation(field3, mapGet, args); // name3Map.get(name3Id) + return23.setExpression(callGetter); // return name3Map.get(name3Id); } getter.addUniqueStatement(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 + MethodDeclaration coordionator = null; + if (!primitivePullDelta.isMultipleDefinition() || pullEdge1.toMany()) { + coordionator = createMethod(class1, updateMethodPrefix + toComponentName(pullEdge2.getName())); + } else { + coordionator = createMethod(class1, addMethodPrefix + 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) + 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.addUniqueStatement(assignmentStatement); + MethodInvocation callGetter = new MethodInvocation(field2, getter.getName(), args); // name2.getName3() + if (!primitivePullDelta.isMultipleDefinition()) { + Assignment assignment = new Assignment(field3, callGetter); // this.name3 = name2.getName3(); + ExpressionStatement assignmentStatement = new ExpressionStatement(assignment); + coordionator.addUniqueStatement(assignmentStatement); + } else { + if (!pullEdge1.toMany()) { + VariableDeclaration idVar = new VariableDeclaration(keyType, pullEdge2.getName() + idPostfix); + args = new ArrayList<>(); + args.add(new Variable(idVar.getName())); + args.add(callGetter); + coordionator.addUniqueStatement(new ExpressionStatement(new MethodInvocation(field3, mapPut, args))); // this.name3Map.put(name3Id, name2.getName3()); + } else { + EnhancedForStatement collectionLoop = new EnhancedForStatement(); // for (key2 loopVar: name2Map.keySet()) + String loopVarName = pullEdge1.getName() + idPostfix; + keyType = ((MapType) field12.getType()).getKeyType(); + VariableDeclaration loopVar = new VariableDeclaration(keyType, loopVarName); + MethodInvocation keysGetter = new MethodInvocation(field2, mapKeySet); + args = new ArrayList<>(); + args.add(new Variable(loopVarName)); + MethodInvocation valueGetter = new MethodInvocation(field2, mapGet, args); + Block loopBody = new Block(); + args = new ArrayList<>(); + args.add(new Variable(loopVarName)); + args.add(new MethodInvocation(valueGetter, getter.getName())); + loopBody.addStatement(new ExpressionStatement(new MethodInvocation(field3, mapPut, args))); // this.name3Map.put(loopVar, name2Map.get(loopVar).getName3()); + collectionLoop.setParameter(loopVar); + collectionLoop.setExpression(keysGetter); + collectionLoop.setBody(loopBody); + coordionator.addUniqueStatement(collectionLoop); + } + } return codebase; } @@ -148,21 +201,21 @@ 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 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) + 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) + field13 = createField(class1, pushEdge.getName() + mapPostfix, typeKeyToType3); // class1 -> {class3} (PUSH) } - FieldDeclaration field32 = createField(class3, pullEdge.getName(), type2); // class3 -> class2 (create) + FieldDeclaration field32 = createField(class3, pullEdge.getName(), type2); // class3 -> class2 (define) // Construct setter method MethodDeclaration setter = null; - if (!pushEdge.toMany()) { + if (!pushEdge.toMany() || primitivePullPushDelta.isMultipleDefinition()) { setter = createMethod(class3, setterPrefix + toComponentName(name2)); } else { setter = createConstructor(class3); @@ -175,13 +228,32 @@ setter.addUniqueStatement(assignmentStatement); // Construct coordinator method - MethodDeclaration coordionator = createMethod(class1, updateMethodPrefix + toComponentName(name2)); + MethodDeclaration coordionator = null; + if (!pushEdge.toMany() || primitivePullPushDelta.isMultipleDefinition()) { + coordionator = createMethod(class1, updateMethodPrefix + toComponentName(name3)); + } else { + coordionator = createMethod(class1, addMethodPrefix + toComponentName(name3)); + } 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.addUniqueStatement(new ExpressionStatement(callSetter)); + if (!pushEdge.toMany() || primitivePullPushDelta.isMultipleDefinition()) { + if (!primitivePullPushDelta.isMultipleDefinition()) { + MethodInvocation callSetter = new MethodInvocation(field3, setter.getName(), args); // name3.setName2(name2) + coordionator.addUniqueStatement(new ExpressionStatement(callSetter)); + } else { + EnhancedForStatement broadcastLoop = new EnhancedForStatement(); // for (type3 loopVar: name3Map.values()) + String loopVarName = pushEdge.getName(); + VariableDeclaration loopVar = new VariableDeclaration(type3, loopVarName); + MethodInvocation valuesGetter = new MethodInvocation(field3, mapValues); + MethodInvocation callSetter = new MethodInvocation(new Variable(loopVarName), setter.getName(), args); // loopVar.setName2(name2) + Block loopBody = new Block(); + loopBody.addStatement(new ExpressionStatement(callSetter)); + broadcastLoop.setParameter(loopVar); + broadcastLoop.setExpression(valuesGetter); + broadcastLoop.setBody(loopBody); + coordionator.addUniqueStatement(broadcastLoop); + } } else { VariableDeclaration idVar = new VariableDeclaration(keyType, pushEdge.getName() + idPostfix); coordionator.addParameter(idVar); diff --git a/src/main/java/models/deltaAlgebra/PrimitivePullDelta.java b/src/main/java/models/deltaAlgebra/PrimitivePullDelta.java index 59c17ff..bfbbd58 100644 --- a/src/main/java/models/deltaAlgebra/PrimitivePullDelta.java +++ b/src/main/java/models/deltaAlgebra/PrimitivePullDelta.java @@ -7,6 +7,7 @@ public class PrimitivePullDelta extends PrimitiveDelta { private ReferenceEdge pullEdge1 = null; private ReferenceEdge pullEdge2 = null; + private boolean multipleDefinition = false; public PrimitivePullDelta(ReferenceEdge pullEdge1, ReferenceEdge pullEdge2, String dataName) { super(dataName); @@ -14,6 +15,13 @@ this.pullEdge2 = pullEdge2; } + public PrimitivePullDelta(ReferenceEdge pullEdge1, ReferenceEdge pullEdge2, String dataName, boolean multipleDefinition) { + super(dataName); + this.pullEdge1 = pullEdge1; + this.pullEdge2 = pullEdge2; + this.multipleDefinition = multipleDefinition; + } + @Override public ObjectNode getCoordinator() { return (ObjectNode) pullEdge1.getSource(); @@ -51,9 +59,13 @@ return pullEdge2; } + public boolean isMultipleDefinition() { + return multipleDefinition; + } + @Override public PrimitivePullDelta copy() { - return new PrimitivePullDelta(pullEdge1, pullEdge2, dataName); + return new PrimitivePullDelta(pullEdge1, pullEdge2, dataName, multipleDefinition); } @Override diff --git a/src/main/java/models/deltaAlgebra/PrimitivePullPushDelta.java b/src/main/java/models/deltaAlgebra/PrimitivePullPushDelta.java index ded83ce..8fba5de 100644 --- a/src/main/java/models/deltaAlgebra/PrimitivePullPushDelta.java +++ b/src/main/java/models/deltaAlgebra/PrimitivePullPushDelta.java @@ -7,6 +7,7 @@ public class PrimitivePullPushDelta extends PrimitiveDelta { private ReferenceEdge pullEdge = null; private ReferenceEdge pushEdge = null; + private boolean multipleDefinition = false; public PrimitivePullPushDelta(ReferenceEdge pullEdge, ReferenceEdge pushEdge, String dataName) { super(dataName); @@ -14,6 +15,13 @@ this.pushEdge = pushEdge; } + public PrimitivePullPushDelta(ReferenceEdge pullEdge, ReferenceEdge pushEdge, String dataName, boolean multipleDefinition) { + super(dataName); + this.pullEdge = pullEdge; + this.pushEdge = pushEdge; + this.multipleDefinition = multipleDefinition; + } + @Override public ObjectNode getCoordinator() { return (ObjectNode) pushEdge.getSource(); @@ -51,9 +59,13 @@ return pushEdge; } + public boolean isMultipleDefinition() { + return multipleDefinition; + } + @Override public PrimitivePullPushDelta copy() { - return new PrimitivePullPushDelta(pullEdge, pushEdge, dataName); + return new PrimitivePullPushDelta(pullEdge, pushEdge, dataName, multipleDefinition); } @Override diff --git a/src/main/java/models/deltaAlgebra/ReferenceEdge.java b/src/main/java/models/deltaAlgebra/ReferenceEdge.java index 6fe1628..5c1547e 100644 --- a/src/main/java/models/deltaAlgebra/ReferenceEdge.java +++ b/src/main/java/models/deltaAlgebra/ReferenceEdge.java @@ -28,6 +28,13 @@ this.keyTypeName = keyTypeName; } + public ReferenceEdge(ReferenceEdge referenceEdge) { + super(referenceEdge.getSource(), referenceEdge.getDestination()); + this.name = referenceEdge.getName(); + this.multiplicity = referenceEdge.getMultiplicity(); + this.keyTypeName = referenceEdge.getKeyTypeName(); + } + public String getName() { return name; } @@ -52,6 +59,10 @@ return keyTypeName; } + public void setKeyTypeName(String keyTypeName) { + this.keyTypeName = keyTypeName; + } + public boolean isIdentical() { return source.equals(destination); } diff --git a/src/main/java/models/objectOrientedTransfer/DataTransferDesign.java b/src/main/java/models/objectOrientedTransfer/DataTransferDesign.java index c3e6174..ecffd8f 100644 --- a/src/main/java/models/objectOrientedTransfer/DataTransferDesign.java +++ b/src/main/java/models/objectOrientedTransfer/DataTransferDesign.java @@ -69,14 +69,16 @@ public DeltaComplex createDefaultDeltaComlex(DataTransferContext transferContext) throws IllegalRelationException { if (transferContext.getTransferStyle() == PushPullValue.PUSH) { // PUSH transfer + + // Construct all deltas. + Stack deltaStack = new Stack<>(); + ReferenceEdge bottomReference = constructDefaultDeltas(transferContext, deltaStack); + + DeltaComplex deltaComplex = null; if (transferContext.getTransferMultiplicity() == MultiplicityValue.ManyToOne || transferContext.getTransferMultiplicity() == MultiplicityValue.OneToOne) { // Simple PUSH - - // Construct all deltas. - Stack deltaStack = new Stack<>(); - ReferenceEdge bottomReference = constructDefaultDeltas(transferContext, deltaStack); - + // Add the data transfer delta. ObjectNode srcObj = (ObjectNode) bottomReference.getSource(); ObjectNode dstObj = (ObjectNode) transferContext.getDataType(); @@ -84,25 +86,40 @@ 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; + deltaComplex = new DeltaComplex(dataTransferDelta); } else { // Broadcasting + bottomReference = new ReferenceEdge(bottomReference); + bottomReference.setKeyTypeName(transferContext.getDstResource().getEdges().getLast().getKeyTypeName()); + bottomReference.setMultiplicity(MultiplicityValue.OneToMany); + + // 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, true); // PUSH data transfer + Delta dataTransferDelta = new Delta(primDelta); + deltaComplex = new DeltaComplex(dataTransferDelta); } + + // Add initialization deltas. + while (!deltaStack.isEmpty()) { + deltaComplex.attach(deltaStack.pop()); + } + return deltaComplex; } else { + // PULL transfer + + // Construct all deltas. + Stack deltaStack = new Stack<>(); + ReferenceEdge bottomReference = constructDefaultDeltas(transferContext, deltaStack); + + DeltaComplex deltaComplex = null; if (transferContext.getTransferMultiplicity() == MultiplicityValue.OneToMany || transferContext.getTransferMultiplicity() == MultiplicityValue.OneToOne) { // Simple PULL - // Construct all deltas. - Stack deltaStack = new Stack<>(); - ReferenceEdge bottomReference = constructDefaultDeltas(transferContext, deltaStack); - // Add the data transfer delta. ObjectNode srcObj = (ObjectNode) bottomReference.getDestination(); ObjectNode dstObj = (ObjectNode) transferContext.getDataType(); @@ -110,18 +127,29 @@ 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; + deltaComplex = new DeltaComplex(dataTransferDelta); } else { // Data collecting + bottomReference = new ReferenceEdge(bottomReference); + bottomReference.setKeyTypeName(transferContext.getSrcResource().getEdges().getLast().getKeyTypeName()); + bottomReference.setMultiplicity(MultiplicityValue.OneToMany); + + // 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, true); // PULL data transfer + Delta dataTransferDelta = new Delta(primDelta); + deltaComplex = new DeltaComplex(dataTransferDelta); } + + // Add initialization deltas. + while (!deltaStack.isEmpty()) { + deltaComplex.attach(deltaStack.pop()); + } + return deltaComplex; } - return null; } private ReferenceEdge constructDefaultDeltas(DataTransferContext transferContext, Stack deltaStack) throws IllegalRelationException { @@ -215,31 +243,37 @@ } } - 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. - + if (!toOne) { + boolean multipleDefinition = false; + if ((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. + toOne = true; + } else { + // If the specified multiplicity of destination objects and their potential multiplicity are both many, + // then the reference to select one destination object from potential multiple objects is needed. + multipleDefinition = true; + } // 2) Create a component identifying delta. PrimitiveDelta componentSelectingDelta = null; - for (ReferenceEdge dstEdge: manyDestinations) { + for (ReferenceEdge dstEdge : manyDestinations) { if (componentSelectingDelta == null) { srcObj = (ObjectNode) prevReference.getSource(); dstObj = (ObjectNode) dstEdge.getDestination(); String dataName = dstObj.getName(); dataName = dataName.substring(0, 1).toLowerCase() + dataName.substring(1); - componentSelectingDelta = new PrimitivePullDelta(prevReference, dstEdge, dataName); + componentSelectingDelta = new PrimitivePullDelta(prevReference, dstEdge, dataName, multipleDefinition); primitiveDeltaList.add(componentSelectingDelta); Delta delta = null; - for (PrimitiveDelta primDelta: primitiveDeltaList) { + for (PrimitiveDelta primDelta : primitiveDeltaList) { if (delta == null) { delta = new Delta(primDelta); } else { delta = new Delta(primDelta, delta); } } - deltaStack.push(delta); // add a component identifying delta + deltaStack.push(delta); // add a component identifying delta primitiveDeltaList.clear(); prevReference = new ReferenceEdge(srcObj, dstObj, dataName); } else { @@ -247,11 +281,10 @@ dstObj = (ObjectNode) dstEdge.getDestination(); String dataName = dstObj.getName(); dataName = dataName.substring(0, 1).toLowerCase() + dataName.substring(1); - primitiveDeltaList.add(new PrimitivePullDelta(prevReference, dstEdge, dataName)); + primitiveDeltaList.add(new PrimitivePullDelta(prevReference, dstEdge, dataName, multipleDefinition)); prevReference = new ReferenceEdge(srcObj, dstObj, dataName); } } - toOne = true; } // 3) Create a component obtaining delta. if (primitiveDeltaList.size() > 0) {