diff --git a/src/main/java/Main.java b/src/main/java/Main.java new file mode 100644 index 0000000..248124e --- /dev/null +++ b/src/main/java/Main.java @@ -0,0 +1,35 @@ +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"); + srcEdges.add(srcEdge); + ReferenceEdge dstEdge = new ReferenceEdge(customers, customer, "customer"); + 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/generators/ASTGenerator.java b/src/main/java/generators/ASTGenerator.java new file mode 100644 index 0000000..a751df5 --- /dev/null +++ b/src/main/java/generators/ASTGenerator.java @@ -0,0 +1,187 @@ +package generators; + +import java.util.ArrayList; +import java.util.List; + +import ast.*; +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 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) { + PrimitivePullDelta primitivePullDelta = (PrimitivePullDelta) primitiveDelta; + 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, toVariableName(name2), type2); // class1 -> class2 (PULL) + FieldDeclaration field23 = createField(class2, toVariableName(name3), type3); // class2 -> class3 (PULL) + FieldDeclaration field13 = createField(class1, toVariableName(name3), type3); // class1 -> class3 (create) + + // Construct getter method + MethodDeclaration getter = createMethod(class2, getterPrefix + toComponentName(name3)); + ReturnStatement return23 = new ReturnStatement(); + return23.setExpression(new FieldAccess(new ThisExpression(), field23.getName())); // return this.name3; + getter.addStatement(return23); + + // Construct coordinator method + MethodDeclaration coordionator = createMethod(class1, getterPrefix + toComponentName(name3)); + FieldAccess field3 = new FieldAccess(new ThisExpression(), field13.getName()); // this.name3 + FieldAccess field2 = new FieldAccess(field12.getName()); + MethodInvocation callGetter = new MethodInvocation(field2, getter.getName()); // name2.getName3() + Assignment assignment = new Assignment(field3, callGetter); // this.name3 = name2.getName3(); + ExpressionStatement assignmentStatement = new ExpressionStatement(assignment); + coordionator.addStatement(assignmentStatement); + } else if (primitiveDelta instanceof PrimitivePullPushDelta) { + PrimitivePullPushDelta primitivePullPushDelta = (PrimitivePullPushDelta) primitiveDelta; + 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, toVariableName(name2), type2); // class1 -> class2 (PULL) + FieldDeclaration field13 = createField(class1, toVariableName(name3), type3); // class1 -> class3 (PUSH) + FieldDeclaration field32 = createField(class3, toVariableName(name2), type2); // class3 -> class2 (create) + + // Construct setter method + MethodDeclaration setter = createMethod(class3, setterPrefix + toComponentName(name2)); + VariableDeclaration param2 = new VariableDeclaration(type2, name2); + setter.addParameter(param2); + FieldAccess field2 = new FieldAccess(new ThisExpression(), field32.getName()); // this.name2 + Assignment assignment = new Assignment(field2, new Variable(name2)); // this.name2 = name2; + ExpressionStatement assignmentStatement = new ExpressionStatement(assignment); + setter.addStatement(assignmentStatement); + + // Construct coordinator method + MethodDeclaration coordionator = createMethod(class1, updateMethodPrefix + toComponentName(name2)); + FieldAccess field3 = new FieldAccess(field13.getName()); + List args = new ArrayList<>(); + args.add(new FieldAccess(field12.getName())); + MethodInvocation callSetter = new MethodInvocation(field3, setter.getName(), args); // name3.setName2(name2) + coordionator.addStatement(new ExpressionStatement(callSetter)); + } else if (primitiveDelta instanceof PrimitivePushDelta) { + PrimitivePushDelta primitivePushDelta = (PrimitivePushDelta) primitiveDelta; + 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, toVariableName(name2), type2); // class1 -> class2 (PUSH) + FieldDeclaration field23 = createField(class2, toVariableName(name3), 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(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, 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 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..031e474 --- /dev/null +++ b/src/main/java/generators/Codebase.java @@ -0,0 +1,45 @@ +package generators; + +import java.util.Collection; +import java.util.HashMap; +import java.util.Map; + +import ast.CompilationUnit; +import ast.SimpleType; +import models.algebra.Type; + +public class Codebase { + private Map classes; + private Map componentTypes; + + public Codebase() { + classes = new HashMap<>(); + componentTypes = new HashMap<>(); + } + + public Collection getCompilationUnits() { + return classes.values(); + } + + public CompilationUnit getCompilationUnit(String name) { + return classes.get(name); + } + + public Type getComponentType(String name) { + return componentTypes.get(name); + } + + public void addCompilationUnit(String name, CompilationUnit compilationUnit) { + classes.put(name, compilationUnit); + Type newType = new 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/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..f64fd4e 100644 --- a/src/main/java/models/objectOrientedTransfer/DataTransferDesign.java +++ b/src/main/java/models/objectOrientedTransfer/DataTransferDesign.java @@ -29,51 +29,63 @@ // 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; + Delta dataTransferDelta = null; + if (!deltaStack.isEmpty()) { + dataTransferDelta = deltaStack.pop(); } + // 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); + PrimitivePullPushDelta primDelta = new PrimitivePullPushDelta(dataEdge, bottomReference, dataName); // PUSH data transfer + if (dataTransferDelta == null) { + dataTransferDelta = new Delta(primDelta); + } else { + dataTransferDelta = dataTransferDelta.combine(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; + Delta dataTransferDelta = null; + if (!deltaStack.isEmpty()) { + dataTransferDelta = deltaStack.pop(); } + // 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); + PrimitivePullDelta primDelta = new PrimitivePullDelta(bottomReference, dataEdge, dataName); // PULL data transfer + if (dataTransferDelta == null) { + dataTransferDelta = new Delta(primDelta); + } else { + dataTransferDelta = dataTransferDelta.combine(primDelta); + } + DeltaComplex deltaComplex = new DeltaComplex(dataTransferDelta); + + // Add initialization deltas. + while (!deltaStack.isEmpty()) { + deltaComplex.attach(deltaStack.pop()); + } + return deltaComplex; } else { // Data collecting } diff --git a/src/main/java/models/objectOrientedTransfer/Delta.java b/src/main/java/models/objectOrientedTransfer/Delta.java index 08b0c0e..33b87b4 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<>(); diff --git a/src/main/java/models/objectOrientedTransfer/DeltaComplex.java b/src/main/java/models/objectOrientedTransfer/DeltaComplex.java index 0ede815..363f7fe 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<>(); 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/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; }