diff --git a/models/Memento.Json b/models/Memento.Json index d521a4d..f86f548 100644 --- a/models/Memento.Json +++ b/models/Memento.Json @@ -4,19 +4,19 @@ { "relations": [], "transfer": { - "src": "Main.Star", - "dst": "Main.States", - "data": {"type": "Memento", "name": "memento"}, - "style": "PULL", + "src": "Star", + "dst": "States", + "data": {"type": "StarMementoInternal", "name": "memento"}, + "style": "PUSH", "multiplicity": "1:1" } }, { "relations": [], "transfer": { - "src": "Main.States", - "dst": "Main.Star", - "data": {"type": "Memento", "name": "memento"}, + "src": "States", + "dst": "Star", + "data": {"type": "StarMementoInternal", "name": "memento"}, "style": "PUSH", "multiplicity": "1:1" } diff --git a/models/designPattern/Decorator.Json b/models/designPattern/Decorator.Json index 76fd619..1bde11c 100644 --- a/models/designPattern/Decorator.Json +++ b/models/designPattern/Decorator.Json @@ -1,10 +1,18 @@ { - "relations": [], - "transfer": { - "src": "SimpleTroll", - "dst": "Client", - "data": { "type": "String", "name": "data" }, - "style": "PULL", - "multiplicity": "1:1" - } + "name" : "Decorator", + "contexts" : [ + { + "relations": [], + "transfer": { + "src": "SimpleTroll", + "dst": "Client", + "data": { + "type": "String", + "name": "data" + }, + "style": "PULL", + "multiplicity": "1:1" + } + } + ] } \ No newline at end of file diff --git a/src/main/java/designPatternExtensions/PresenterInsertion.java b/src/main/java/designPatternExtensions/PresenterInsertion.java index 4957343..09a8751 100644 --- a/src/main/java/designPatternExtensions/PresenterInsertion.java +++ b/src/main/java/designPatternExtensions/PresenterInsertion.java @@ -8,12 +8,15 @@ private ObjectNode dst; private ObjectNode presenter; private PushPullValue pushPullValue; + private boolean removeDirectDependency = false; - public PresenterInsertion(ObjectNode src, ObjectNode dst, ObjectNode presenter, PushPullValue pushPullValue) { + public PresenterInsertion(ObjectNode src, ObjectNode dst, ObjectNode presenter, + PushPullValue pushPullValue, boolean removeDirectDependency) { this.src = src; this.dst = dst; this.presenter = presenter; this.pushPullValue = pushPullValue; + this.removeDirectDependency = removeDirectDependency; } public ObjectNode getSrc() { @@ -30,4 +33,6 @@ public PushPullValue getPushPullValue() { return pushPullValue; } + public boolean getRemoveDirectDependency() { return removeDirectDependency; } + } \ No newline at end of file diff --git a/src/main/java/designPatternExtensions/designPattern/Builder.java b/src/main/java/designPatternExtensions/designPattern/Builder.java index f3367a6..0204d58 100644 --- a/src/main/java/designPatternExtensions/designPattern/Builder.java +++ b/src/main/java/designPatternExtensions/designPattern/Builder.java @@ -19,12 +19,12 @@ DataTransferDesign design = ModelLoader.load("models/designPattern/Builder.Json"); DataTransferContext dtc = design.getTransferContexts().getFirst(); ObjectNode builder = dtc.getSrcFirstResource(); - ObjectNode main = dtc.getDstFirstResource(); + ObjectNode hero = dtc.getDstFirstResource(); // // MediatorInsertion mi = new MediatorInsertion(main, builder, new ObjectNode("Hero")); // design.addMediatorInsertion(mi); -// PresenterInsertion pi = new PresenterInsertion(main, builder, new ObjectNode("Presenter"), dtc.getTransferStyle()); +// PresenterInsertion pi = new PresenterInsertion(hero, builder, new ObjectNode("Presenter"), dtc.getTransferStyle(), true); // design.addPresenterInsertion(pi); return design; diff --git a/src/main/java/designPatternExtensions/designPattern/Decorator.java b/src/main/java/designPatternExtensions/designPattern/Decorator.java index 93a4724..43d5882 100644 --- a/src/main/java/designPatternExtensions/designPattern/Decorator.java +++ b/src/main/java/designPatternExtensions/designPattern/Decorator.java @@ -20,7 +20,7 @@ ObjectNode client = dtc.getDstFirstResource(); ObjectNode clubbedTroll = new ObjectNode("ClubbedTroll"); - MediatorInsertion mi = new MediatorInsertion(client, simpleTroll, clubbedTroll, dtc); + MediatorInsertion mi = new MediatorInsertion(simpleTroll, client, clubbedTroll, dtc); design.addMediatorInsertion(mi); InterfaceNode troll = new InterfaceNode(clubbedTroll, "Troll"); diff --git a/src/main/java/designPatternExtensions/designPattern/MediatorInsertionTest.java b/src/main/java/designPatternExtensions/designPattern/MediatorInsertionTest.java index 3a973ed..2ee6fa9 100644 --- a/src/main/java/designPatternExtensions/designPattern/MediatorInsertionTest.java +++ b/src/main/java/designPatternExtensions/designPattern/MediatorInsertionTest.java @@ -11,13 +11,13 @@ DataTransferContext dtc = design.getTransferContexts().getFirst(); ObjectNode a = dtc.getSrcFirstResource(); ObjectNode b = dtc.getDstFirstResource(); -// + // ObjectNode me = new ObjectNode("Me"); // MediatorInsertion mi = new MediatorInsertion(a, b, me, dtc.getTransferStyle()); // design.addMediatorInsertion(mi); ObjectNode presenter = new ObjectNode("Presenter"); - PresenterInsertion pi = new PresenterInsertion(a, b, presenter, dtc.getTransferStyle()); + PresenterInsertion pi = new PresenterInsertion(a, b, presenter, dtc.getTransferStyle(), false); design.addPresenterInsertion(pi); return design; diff --git a/src/main/java/designPatternExtensions/designPattern/Memento.java b/src/main/java/designPatternExtensions/designPattern/Memento.java index 982e1ac..7958294 100644 --- a/src/main/java/designPatternExtensions/designPattern/Memento.java +++ b/src/main/java/designPatternExtensions/designPattern/Memento.java @@ -1,36 +1,39 @@ package designPatternExtensions.designPattern; -import designPatternExtensions.DependencyInversion; -import designPatternExtensions.InterfaceNode; -import designPatternExtensions.MediatorInsertion; +import designPatternExtensions.*; import models.objectOrientedTransfer.*; import java.util.ArrayList; //https://github.com/iluwatar/java-design-patterns/tree/master/memento -//複数のデータ転送をまとめて扱えるようにしないとできない → 一方向でもできればいったんOK public class Memento implements DesignPattern{ public DataTransferDesign create() throws IllegalRelationException { - ObjectNode star = new ObjectNode("Star"); - ObjectNode states = new ObjectNode("States"); + DataTransferDesign design = ModelLoader.load("models/Memento.Json"); + DataTransferContext dtc = design.getTransferContexts().getFirst(); + ObjectNode star = dtc.getSrcFirstResource(); + ObjectNode states = dtc.getDstFirstResource(); + + ObjectNode presenter = new ObjectNode("Main"); + PresenterInsertion main = new PresenterInsertion(star, states, + presenter, dtc.getTransferStyle(), true); + design.addPresenterInsertion(main); + + DataTransferContext dtc2 = design.getTransferContexts().getLast(); + ObjectNode states2 = dtc2.getSrcFirstResource(); + ObjectNode star2 = dtc2.getDstFirstResource(); + + PresenterInsertion main2 = new PresenterInsertion(states2, star2, + presenter, dtc2.getTransferStyle(), true); + design.addPresenterInsertion(main2); + ObjectNode starMementoInternal = new ObjectNode("StarMementoInternal"); - - Relation transferRelation = new Relation(star, states, MultiplicityValue.OneToOne); - DataTransferContext context = new DataTransferContext( - new ArrayList<>(), transferRelation, starMementoInternal, "memento", PushPullValue.PULL - ); - - DataTransferDesign design = new DataTransferDesign(context); - - MediatorInsertion client = new MediatorInsertion(star, states, new ObjectNode("Client"), context); - design.addMediatorInsertion(client); - DependencyInversion di = new DependencyInversion( - starMementoInternal, new InterfaceNode(starMementoInternal, "StarMemento"), states + starMementoInternal, new InterfaceNode(starMementoInternal, "StarMemento") ); design.addDependencyInversion(di); return design; + } } diff --git a/src/main/java/generators/ASTGenerator.java b/src/main/java/generators/ASTGenerator.java index faa741b..be5b6b3 100644 --- a/src/main/java/generators/ASTGenerator.java +++ b/src/main/java/generators/ASTGenerator.java @@ -8,6 +8,7 @@ import designPatternExtensions.InterfaceNode; import designPatternExtensions.MediatorInsertion; import designPatternExtensions.PresenterInsertion; +import models.algebra.Type; import models.dataConstraintModel.MapType; import models.objectOrientedTransfer.*; @@ -417,14 +418,17 @@ FieldDeclaration dstField = createField(presenterClass, dstFieldName, dstType); MethodDeclaration constructor = createConstructor(presenterClass); - VariableDeclaration srcParam = new VariableDeclaration(srcType, srcFieldName); - VariableDeclaration dstParam = new VariableDeclaration(dstType, dstFieldName); - constructor.addParameter(srcParam); - constructor.addParameter(dstParam); - constructor.addUniqueStatement(new ExpressionStatement( - new Assignment(new FieldAccess(new ThisExpression(), srcField.getName()), new Variable(srcFieldName)))); - constructor.addUniqueStatement(new ExpressionStatement( - new Assignment(new FieldAccess(new ThisExpression(), dstField.getName()), new Variable(dstFieldName)))); + + if (!hasParameterNamed(constructor, srcFieldName)) { + constructor.addParameter(new VariableDeclaration(srcType, srcFieldName)); + constructor.addUniqueStatement(new ExpressionStatement( + new Assignment(new FieldAccess(new ThisExpression(), srcField.getName()), new Variable(srcFieldName)))); + } + if (!hasParameterNamed(constructor, dstFieldName)) { + constructor.addParameter(new VariableDeclaration(dstType, dstFieldName)); + constructor.addUniqueStatement(new ExpressionStatement( + new Assignment(new FieldAccess(new ThisExpression(), dstField.getName()), new Variable(dstFieldName)))); + } TypeDeclaration srcClass = createClass(codebase, srcName); TypeDeclaration dstClass = createClass(codebase, dstName); @@ -441,13 +445,13 @@ for (FieldDeclaration field: srcClass.getFields()) { if (field.getType() == null) continue; - if (field.getType().getTypeName().equals(dstType.getTypeName())) continue; // navigation field toward dst, not data - String propertyName = toComponentName(field.getName()); - if (boundProperties.contains(propertyName)) continue; // already exposed via an existing getter above + if (field.getType().getTypeName().equals(dstType.getTypeName())) continue; + + String propertyName = toComponentName(field.getType().getTypeName()); + if (boundProperties.contains(propertyName)) continue; MethodDeclaration newGetter = createMethod(srcClass, getterPrefix + propertyName); if (newGetter.getReturnType() == null) { - ReturnStatement returnStatement = new ReturnStatement(); returnStatement.setExpression(new FieldAccess(new ThisExpression(), field.getName())); newGetter.addUniqueStatement(returnStatement); @@ -458,40 +462,51 @@ } for (MethodDeclaration getter: getters) { - //Derive the setter name from the getter's type name String propertyName = getter.getName().substring(getterPrefix.length()); String setterName = setterPrefix + propertyName; - // Create a new setter if dstClass does not have one MethodDeclaration setter = createMethod(dstClass, setterName); if (setter.getReturnType() == null && (setter.getParameters() == null || setter.getParameters().isEmpty())) { - // Build the setter body only when a new setter is created models.algebra.Type propertyType = getter.getReturnType(); VariableDeclaration setterParam = new VariableDeclaration(propertyType, toVariableName(propertyName)); setter.addParameter(setterParam); - // Find the corresponding field in dstClass, or create one if it doesn't exist FieldDeclaration propertyField = createField(dstClass, toVariableName(propertyName), propertyType); setter.addUniqueStatement(new ExpressionStatement( new Assignment(new FieldAccess(new ThisExpression(), propertyField.getName()), new Variable(toVariableName(propertyName))))); } - // Add the binding method to the Presenter - String presenterMethodName = updateMethodPrefix + propertyName; + String presenterMethodName = updateMethodPrefix + dstName + propertyName; + MethodDeclaration coordinator = createMethod(presenterClass, presenterMethodName); - List getterArgs = new ArrayList<>(); - MethodInvocation callGetter = new MethodInvocation(new FieldAccess(srcField.getName()), getter.getName(), getterArgs); - List setterArgs = new ArrayList<>(); - setterArgs.add(callGetter); - MethodInvocation callSetter = new MethodInvocation(new FieldAccess(dstField.getName()), setter.getName(), setterArgs); - coordinator.addUniqueStatement(new ExpressionStatement(callSetter)); + if (coordinator.getBody() == null || coordinator.getBody().getStatements2().isEmpty()) { + List getterArgs = new ArrayList<>(); + MethodInvocation callGetter = new MethodInvocation(new FieldAccess(srcField.getName()), getter.getName(), getterArgs); + List setterArgs = new ArrayList<>(); + setterArgs.add(callGetter); + MethodInvocation callSetter = new MethodInvocation(new FieldAccess(dstField.getName()), setter.getName(), setterArgs); + coordinator.addUniqueStatement(new ExpressionStatement(callSetter)); + } } - removeDirectDependency(srcClass, dstType); - removeDirectDependency(dstClass, srcType); + if (presenterInsertion.getRemoveDirectDependency()) { + if (presenterInsertion.getPushPullValue() == PushPullValue.PUSH) { + removeDirectDependency(srcClass, dstType); + } else { + removeDirectDependency(dstClass, srcType); + } + } return codebase; } + private static boolean hasParameterNamed(MethodDeclaration method, String name) { + if (method.getParameters() == null) return false; + for (VariableDeclaration param: method.getParameters()) { + if (param.getName().equals(name)) return true; + } + return false; + } + private static void removeDirectDependency(TypeDeclaration typeDecl, models.algebra.Type otherType) { List fieldsToRemove = new ArrayList<>(); for (FieldDeclaration field: typeDecl.getFields()) { @@ -631,6 +646,13 @@ } } } + if (!method.isConstructor() && method.getParameters() != null) { + for (VariableDeclaration param: method.getParameters()) { + if (param.getType() != null && param.getType().equals(dstType)) { + param.setType(interfaceType); + } + } + } // Change method return types if (!method.isConstructor() && method.getReturnType() != null) { if (method.getReturnType().getTypeName().equals(dstType.getTypeName())) {