diff --git a/AlgebraicDataflowArchitectureModel/models/Audio.dtram b/AlgebraicDataflowArchitectureModel/models/Audio.dtram new file mode 100644 index 0000000..66862ef --- /dev/null +++ b/AlgebraicDataflowArchitectureModel/models/Audio.dtram @@ -0,0 +1,33 @@ +model { +channel CIO3 { + out BGMVolume(b: Double, setBGM(b2)) == b2 +} +channel CIO2 { + out soundVolume(s: Double, setSound(s2)) == s2 +} +channel CIO1 { + out audioVolume(a: Double, setAudio(a2)) == a2 +} +channel C1 { + in audioVolume(a, calc(a2, s2)) == a2 + in soundVolume(s, calc(a2, s2)) == s2 + out outputSoundVolume(os, calc(a2, s2)) == a2 * s2 +} +channel C2 { + in audioVolume(a, calc(a2, b2)) == a2 + in BGMVolume(b, calc(a2, b2)) == b2 + out outputBGMVolume(ob, calc(a2, b2)) == a2 * b2 +} +} +geometry { + node r soundVolume:220,140,80,30 + node r audioVolume:220,280,80,30 + node r outputSoundVolume:650,190,80,30 + node r BGMVolume:220,420,80,30 + node r outputBGMVolume:650,340,80,30 + node ioc CIO3:100,420,30,30 + node ioc CIO2:100,140,30,30 + node ioc CIO1:100,280,30,30 + node c C1:530,190,30,30 + node c C2:530,340,30,30 +} diff --git a/AlgebraicDataflowArchitectureModel/models/Clock.dtram b/AlgebraicDataflowArchitectureModel/models/Clock.dtram new file mode 100644 index 0000000..ae2169e --- /dev/null +++ b/AlgebraicDataflowArchitectureModel/models/Clock.dtram @@ -0,0 +1,27 @@ +model { + channel CIO1 { + out min(m: Double, tick) == mod(m + 1, 60) + } + channel Clock { + in min(m, update(m2)) == m2 + out hour(h: Double, update(m2)) == if(eq(m2, 0), mod(h + 1, 24), h) + } + channel MinUpdate { + in min(m, update(m2)) == m2 + out min_ang(m_ang: Double, update(m2)) == m2 / 30 * PI + } + channel HourUpdate { + in hour(h, update(h2)) == h2 + out hour_ang(h_ang: Double, update(h2)) == h2 / 6 * PI + } +} +geometry { + node c HourUpdate:520,340,30,30 + node c MinUpdate:520,100,30,30 + node c Clock:280,220,30,30 + node r min_ang:670,100,80,30 + node r min:250,100,80,30 + node r hour:270,340,80,30 + node r hour_ang:680,340,80,30 + node ioc CIO1:100,100,30,30 +} diff --git a/AlgebraicDataflowArchitectureModel/models/JumpGame.model b/AlgebraicDataflowArchitectureModel/models/JumpGame.model index 1981df9..4c24a56 100644 --- a/AlgebraicDataflowArchitectureModel/models/JumpGame.model +++ b/AlgebraicDataflowArchitectureModel/models/JumpGame.model @@ -1,7 +1,8 @@ init { force := pair(0.0, 0.0) time := 0.0 - move := pair(0.0, 0.0) + movex := 0.0 + movey := 0.0 mass := 1.0 ground := true acceleration := pair(0.0, 0.0) diff --git a/AlgebraicDataflowArchitectureModel/models/Map.dtram b/AlgebraicDataflowArchitectureModel/models/Map.dtram new file mode 100644 index 0000000..b1fe577 --- /dev/null +++ b/AlgebraicDataflowArchitectureModel/models/Map.dtram @@ -0,0 +1,23 @@ +model { + channel GPS_In { + out longitude(prev_long: Double, updateGPS(cur_long, cur_lat)) == cur_long + out latitude(prev_lat: Double, updateGPS(cur_long, cur_lat)) == cur_lat + } + channel LongUpdate { + in longitude(prev_long, updateLong(cur_long)) == cur_long + out mapLongitude(prev_mapLong, updateLong(cur_long)) == cur_long + } + channel LatUpdate { + in latitude(prev_lat, updateLat(cur_lat)) == cur_lat + out mapLatitude(prev_mapLat, updateLat(cur_lat)) == cur_lat + } +} +geometry { + node r mapLatitude:580,310,80,30 + node r latitude:190,310,80,30 + node r mapLongitude:580,170,80,30 + node r longitude:190,170,80,30 + node ioc GPS_In:40,60,30,30 + node c LongUpdate:410,170,30,30 + node c LatUpdate:410,310,30,30 +} diff --git a/AlgebraicDataflowArchitectureModel/models/Map.model b/AlgebraicDataflowArchitectureModel/models/Map.model new file mode 100644 index 0000000..2ea85ff --- /dev/null +++ b/AlgebraicDataflowArchitectureModel/models/Map.model @@ -0,0 +1,14 @@ +channel GPS_In { + out longitude(prev_long: Double, updateGPS(cur_long, cur_lat)) == cur_long + out latitude(prev_lat: Double, updateGPS(cur_long, cur_lat)) == cur_lat +} + +channel LongUpdate { + in longitude(prev_long, updateLong(cur_long)) == cur_long + out mapLongitude(prev_mapLong, updateLong(cur_long)) == cur_long +} + +channel LatUpdate { + in latitude(prev_lat, updateLat(cur_lat)) == cur_lat + out mapLatitude(prev_mapLat, updateLat(cur_lat)) == cur_lat +} diff --git a/AlgebraicDataflowArchitectureModel/models/SSDStore.dtram b/AlgebraicDataflowArchitectureModel/models/SSDStore.dtram new file mode 100644 index 0000000..e226ec0 --- /dev/null +++ b/AlgebraicDataflowArchitectureModel/models/SSDStore.dtram @@ -0,0 +1,33 @@ +model { + channel capacity_In { + out capacity(prev_capacity:Int, setCapacity(cur_capacity)) == cur_capacity + } + channel price_In { + out price(prev_price:Int, setPrice(cur_price)) == cur_price + } + channel siteA_Add { + out siteA(prev_products:List, addProductToSiteA(price:Int, capacity:Int)) == cons({"price": price, "capacity": capacity}, prev_products) + } + channel capacity_Update { + in siteA(prev_products:List, updateList(cur_products, cur_capacity)) == cur_products + in capacity(prev_capacity:Int, updateList(cur_products, cur_capacity)) == cur_capacity + out itemsByCapacity(prev_items:List, updateList(cur_products, cur_capacity)) == selectGE(cur_products, "capacity", cur_capacity) + } + channel price_Update { + in siteA(prev_products:List, updateList(cur_products, cur_price)) == cur_products + in price(prev_price:Int, updateList(cur_products, cur_price)) == cur_price + out itemsByPrice(prev_items:List, updateList(cur_products, cur_price)) == selectLE(cur_products, "price", cur_price) + } +} +geometry { + node r price:250,40,80,30 + node r itemsByPrice:650,110,80,30 + node r itemsByCapacity:650,280,80,30 + node r siteA:250,200,80,30 + node r capacity:250,370,80,30 + node ioc capacity_In:100,370,30,30 + node ioc price_In:100,40,30,30 + node ioc siteA_Add:100,200,30,30 + node c capacity_Update:500,280,30,30 + node c price_Update:500,110,30,30 +} diff --git a/AlgebraicDataflowArchitectureModel/models/SSDStore.model b/AlgebraicDataflowArchitectureModel/models/SSDStore.model new file mode 100644 index 0000000..e8696fe --- /dev/null +++ b/AlgebraicDataflowArchitectureModel/models/SSDStore.model @@ -0,0 +1,23 @@ +channel capacity_In { + out capacity(prev_capacity:Int, setCapacity(cur_capacity)) == cur_capacity +} + +channel price_In { + out price(prev_price:Int, setPrice(cur_price)) == cur_price +} + +channel siteA_Add { + out siteA(prev_products:List, addProductToSiteA(price:Int, capacity:Int)) == cons({"price": price, "capacity": capacity}, prev_products) +} + +channel capacity_Update { + in siteA(prev_products:List, updateList(cur_products, cur_capacity)) == cur_products + in capacity(prev_capacity:Int, updateList(cur_products, cur_capacity)) == cur_capacity + out itemsByCapacity(prev_items:List, updateList(cur_products, cur_capacity)) == selectGE(cur_products, "capacity", cur_capacity) +} + +channel price_Update { + in siteA(prev_products:List, updateList(cur_products, cur_price)) == cur_products + in price(prev_price:Int, updateList(cur_products, cur_price)) == cur_price + out itemsByPrice(prev_items:List, updateList(cur_products, cur_price)) == selectLE(cur_products, "price", cur_price) +} \ No newline at end of file diff --git a/AlgebraicDataflowArchitectureModel/models/SamplePULL.dtram b/AlgebraicDataflowArchitectureModel/models/SamplePULL.dtram new file mode 100644 index 0000000..0c06ae8 --- /dev/null +++ b/AlgebraicDataflowArchitectureModel/models/SamplePULL.dtram @@ -0,0 +1,21 @@ +model { + channel setAChannel { + out a(aValue:Int, setA(value)) == value + } + channel outBChannel { + in a(aValue:Int, calcB(aValue)) == aValue + out b(bValue:Int ,calcB(aValue)) == aValue * 2 + } + channel outCChannel { + in a(aValue:Int, calcC(aValue)) == aValue + out c(cValue:Int, calcC(aValue)) == aValue + 1 + } +} +geometry { + node r a:250,170,80,30 + node r b:580,80,80,30 + node r c:590,280,80,30 + node ioc setAChannel:90,170,30,30 + node c outBChannel:430,80,30,30 + node c outCChannel:440,280,30,30 +} diff --git a/AlgebraicDataflowArchitectureModel/models/SamplePUSH.dtram b/AlgebraicDataflowArchitectureModel/models/SamplePUSH.dtram new file mode 100644 index 0000000..c07e68b --- /dev/null +++ b/AlgebraicDataflowArchitectureModel/models/SamplePUSH.dtram @@ -0,0 +1,15 @@ +model { + channel setAChannel { + out a(aValue:Int, setA(value)) == value + } + channel updateBChannel { + in a(aValue:Int, updateB(aValue)) == aValue + out b(bValue:Int, updateB(aValue)) == bValue + aValue + } +} +geometry { + node r a:270,270,80,30 + node r b:660,270,80,30 + node ioc setAChannel:90,240,100,90 + node c updateBChannel:460,240,100,90 +} diff --git a/AlgebraicDataflowArchitectureModel/models/Triangle.model b/AlgebraicDataflowArchitectureModel/models/Triangle.model new file mode 100644 index 0000000..ebfe6b4 --- /dev/null +++ b/AlgebraicDataflowArchitectureModel/models/Triangle.model @@ -0,0 +1,13 @@ +channel cio1 { + out base(x: Double, setBase(x2)) == x2 +} + +channel cio2 { + out height(y: Double, setHeight(y2)) == y2 +} + +channel triangle { + in base(x, update(x2, y2)) == x2 + in height(y, update(x2, y2)) == y2 + out hypothenuse(z: Double, update(x2, y2)) == sqrt(x2 * x2 + y2 * y2) +} \ No newline at end of file diff --git a/AlgebraicDataflowArchitectureModel/models/Triangle2.model b/AlgebraicDataflowArchitectureModel/models/Triangle2.model new file mode 100644 index 0000000..db775bd --- /dev/null +++ b/AlgebraicDataflowArchitectureModel/models/Triangle2.model @@ -0,0 +1,13 @@ +channel cio1 { + out base(x: Double, setBase(x2)) == x2 +} + +channel cio2 { + out height(y: Double, setHeight(y2)) == y2 +} + +channel triangle { + in base(x, update: Tuple) == fst(update) + in height(y, update) == snd(update) + out hypothenuse(z: Double, update) == sqrt(fst(update) * fst(update) + snd(update) * snd(update)) +} \ No newline at end of file diff --git a/AlgebraicDataflowArchitectureModel/resources/locales/en.properties b/AlgebraicDataflowArchitectureModel/resources/locales/en.properties new file mode 100644 index 0000000..ac26d9b --- /dev/null +++ b/AlgebraicDataflowArchitectureModel/resources/locales/en.properties @@ -0,0 +1,49 @@ +# File +file=File +new=New +open=Open +save=Save +saveAs=Save As... +exit=Exit + +# New +newModel=Model +newResources=Resources... +newChannel=Channel... +newEventChannel=Event Channel +newFormulaChannel=Formula Channel + +# Edit +edit=Edit +delete=Delete + +# Layout +layout=Layout +dagLayout=DAG Layout +treeLayout=Tree Layout +circleLayout=Circle Layout + +# View +view=View +zoomIn=Zoom In +zoomOut=Zoom Out + +# Generate +generate=Generate +generateJava=Generate Plain Java Prototype +generateJAX_RS=Generate Plain JAX-RS Prototype + +# Window +window=Window +showNavigation=Show Navigation +showFlowLayer=Show Flow Layer + +# Navigation +dataFlowModeling=Data-Flow Modeling +pushpullSelection = PUSH/PULL Selection +pushpullExtension = PUSH/PULL Extension + +# PopUp Actions +changeCallOrder=Change Call Order +insertMediator=Introduce Mediator +dependsOnMediator=Depends On Mediator diff --git a/AlgebraicDataflowArchitectureModel/resources/locales/ja.properties b/AlgebraicDataflowArchitectureModel/resources/locales/ja.properties new file mode 100644 index 0000000..bc7288a --- /dev/null +++ b/AlgebraicDataflowArchitectureModel/resources/locales/ja.properties @@ -0,0 +1,49 @@ +# File +file=\u30D5\u30A1\u30A4\u30EB +new=\u65B0\u898F +open=\u958B\u304F +save=\u4FDD\u5B58 +saveAs=\u4E0A\u66F8\u304D\u4FDD\u5B58 +exit=\u9589\u3058\u308B + +# New +newModel=\u30E2\u30C7\u30EB +newResources=\u30EA\u30BD\u30FC\u30B9 +newChannel=\u30C1\u30E3\u30F3\u30CD\u30EB +newEventChannel=\u30A4\u30D9\u30F3\u30C8\u30C1\u30E3\u30F3\u30CD\u30EB +newFormulaChannel=\u30D5\u30A9\u30FC\u30DF\u30E5\u30E9\u30C1\u30E3\u30F3\u30CD\u30EB + +# Edit +edit=\u7DE8\u96C6 +delete=\u524A\u9664 + +# Layout +layout=\u30EC\u30A4\u30A2\u30A6\u30C8 +dagLayout=DAG \u30EC\u30A4\u30A2\u30A6\u30C8 +treeLayout=\u30C4\u30EA\u30FC\u30EC\u30A4\u30A2\u30A6\u30C8 +circleLayout=\u30B5\u30FC\u30AF\u30EB\u30EC\u30A4\u30A2\u30A6\u30C8 + +# View +view=\u8868\u793A +zoomIn=\u62E1\u5927 +zoomOut=\u7E2E\u5C0F + +# Generate +generate=\u30D7\u30ED\u30C8\u30BF\u30A4\u30D7\u751F\u6210 +generateJava=Java\u30D7\u30ED\u30C8\u30BF\u30A4\u30D7\u306E\u751F\u6210 +generateJAX_RS=JAX-RS\u30D7\u30ED\u30C8\u30BF\u30A4\u30D7\u306E\u751F\u6210 + +# Window +window=\u30A6\u30A3\u30F3\u30C9\u30A6 +showNavigation=\u30CA\u30D3\u30B2\u30FC\u30B7\u30E7\u30F3 +showFlowLayer=\u30D5\u30ED\u30FC\u30EC\u30A4\u30E4\u30FC + +# Navigation +dataFlowModeling=\u30C7\u30FC\u30BF\u30D5\u30ED\u30FC\u30E2\u30C7\u30EA\u30F3\u30B0 +pushpullSelection = PUSH/PULL\u306E\u9078\u629E +pushpullExtension = PUSH/PULL\u306E\u62E1\u5F35 + +# PopUp Actions +changeCallOrder=\u547C\u3073\u51FA\u3057\u9806\u306E\u5909\u66F4 +insertMediator=\u4EF2\u4ECB\u8005\u30AA\u30D6\u30B8\u30A7\u30AF\u30C8\u306E\u5C0E\u5165 +dependsOnMediator=\u4EF2\u4ECB\u8005\u30AA\u30D6\u30B8\u30A7\u30AF\u30C8\u3078\u4F9D\u5B58 \ No newline at end of file diff --git a/AlgebraicDataflowArchitectureModel/src/Main.java b/AlgebraicDataflowArchitectureModel/src/Main.java index 119bdd3..54fdaf8 100644 --- a/AlgebraicDataflowArchitectureModel/src/Main.java +++ b/AlgebraicDataflowArchitectureModel/src/Main.java @@ -1,11 +1,11 @@ -import graphicalrefactor.views.GraphicalRefactor; +import application.ApplicationWindow; public class Main { public static void main(String[] args) { - GraphicalRefactor frame = new GraphicalRefactor(); + ApplicationWindow frame = new ApplicationWindow(); frame.setVisible(true); } diff --git a/AlgebraicDataflowArchitectureModel/src/algorithms/DataTransferModelAnalyzer.java b/AlgebraicDataflowArchitectureModel/src/algorithms/DataTransferModelAnalyzer.java index 07afdf1..ff4c528 100644 --- a/AlgebraicDataflowArchitectureModel/src/algorithms/DataTransferModelAnalyzer.java +++ b/AlgebraicDataflowArchitectureModel/src/algorithms/DataTransferModelAnalyzer.java @@ -24,41 +24,42 @@ */ static public DataFlowGraph createDataFlowGraphWithStateStoringAttribute(DataTransferModel model) { DataFlowGraph graph = model.getDataFlowGraph(); - Collection channels = new HashSet<>(model.getIOChannelGenerators()); - channels.addAll(model.getChannelGenerators()); - for (ChannelGenerator generator: channels) { - for (ChannelMember member: ((DataTransferChannelGenerator) generator).getOutputChannelMembers()) { - boolean flag = !member.getStateTransition().isRightUnary(); // The state does not need to be stored if the state transition function is right unary. - for (Node node : graph.getNodes()) { - if (((ResourceNode) node).getIdentifierTemplate().equals(member.getIdentifierTemplate())) { - setStoreAttribute(flag, (ResourceNode) node); + Collection channels = new HashSet<>(model.getIOChannels()); + channels.addAll(model.getChannels()); + for (Channel channel: channels) { + for (ChannelMember member: ((DataTransferChannel) channel).getOutputChannelMembers()) { + boolean toBeStored = !member.getStateTransition().isRightUnary(); // The state does not need to be stored if the state transition function is right unary. + for (Node node: graph.getNodes()) { + if (((ResourceNode) node).getResource().equals(member.getResource())) { + setStoreAttribute((ResourceNode) node, toBeStored); } } } } - for (Node node : graph.getNodes()) { - HashSet inChannels = new HashSet<>(); - for(Edge pre : ((ResourceNode) node).getInEdges()) { - inChannels.add(((DataFlowEdge) pre).getChannelGenerator()); + for (Node node: graph.getNodes()) { + HashSet inChannels = new HashSet<>(); + for(Edge inEdge: ((ResourceNode) node).getInEdges()) { + inChannels.add(((DataFlowEdge) inEdge).getChannel()); } if ((inChannels.size() > 1)) { - setStoreAttribute(true, (ResourceNode) node); + // If the resource has multiple input channels, then the state of the resource needs to be stored. + setStoreAttribute((ResourceNode) node, true); } else if (((ResourceNode) node).getAttribute() == null) { - setStoreAttribute(false, (ResourceNode) node); + setStoreAttribute((ResourceNode) node, false); } } return graph; } - static private void setStoreAttribute(boolean flag, ResourceNode node) { + static private void setStoreAttribute(ResourceNode node, boolean toBeStored) { NodeAttribute attr = node.getAttribute(); StoreAttribute store; if (attr != null && attr instanceof NodeAttribute) { store = (StoreAttribute) attr; - store.setNeeded(store.isNeeded() || flag); + store.setNeeded(store.isNeeded() || toBeStored); } else { store = new StoreAttribute(); - store.setNeeded(flag); + store.setNeeded(toBeStored); node.setAttribute(store); } } diff --git a/AlgebraicDataflowArchitectureModel/src/algorithms/TypeInference.java b/AlgebraicDataflowArchitectureModel/src/algorithms/TypeInference.java index fb48b10..9b3ca65 100644 --- a/AlgebraicDataflowArchitectureModel/src/algorithms/TypeInference.java +++ b/AlgebraicDataflowArchitectureModel/src/algorithms/TypeInference.java @@ -13,16 +13,18 @@ import javax.xml.crypto.Data; import models.Node; +import models.algebra.Constant; import models.algebra.Expression; import models.algebra.Position; import models.algebra.Symbol; import models.algebra.Term; import models.algebra.Type; import models.algebra.Variable; -import models.dataConstraintModel.ChannelGenerator; +import models.dataConstraintModel.Channel; import models.dataConstraintModel.ChannelMember; import models.dataConstraintModel.DataConstraintModel; -import models.dataConstraintModel.IdentifierTemplate; +import models.dataConstraintModel.JsonType; +import models.dataConstraintModel.ResourcePath; import models.dataConstraintModel.StateTransition; import models.dataFlowModel.DataTransferModel; import models.dataFlowModel.ResourceNode; @@ -42,6 +44,8 @@ static private Map pairComponentTypes = new HashMap<>(); static private Map, Type> mapTypes = new HashMap<>(); static private Map> mapComponentTypes = new HashMap<>(); + static private Map, Type> jsonTypes = new HashMap<>(); + static private Map> jsonMemberTypes = new HashMap<>(); public static Type getListType(Type compType) { return listTypes.get(compType); @@ -83,14 +87,25 @@ return mapComponentTypes.get(mapType); } + public static Type getJsonType(Map memberTypes) { + return jsonTypes.get(memberTypes); + } + + public static Map getJsonMemberTypes(Type jsonType) { + return jsonMemberTypes.get(jsonType); + } + static public void infer(DataTransferModel model) { - Map> resources = new HashMap<>(); + Map> resources = new HashMap<>(); Map variables = new HashMap<>(); - Map, Type>>> messages = new HashMap<>(); + Map, Type>>> messages = new HashMap<>(); Map consOrSet = new HashMap<>(); Map tuple = new HashMap<>(); Map pair = new HashMap<>(); Map map = new HashMap<>(); + Map json = new HashMap<>(); + + // Maps from the objectId of each expression to its belonging group that has the same type as the expression Map> expToResource = new HashMap<>(); Map> expToVariable = new HashMap<>(); Map> expToMessage = new HashMap<>(); @@ -98,7 +113,9 @@ Map>> expToTuple = new HashMap<>(); Map>> expToPair = new HashMap<>(); Map>> expToMap = new HashMap<>(); + Map>> expToJson = new HashMap<>(); + // Maps from the objectId of each group to the set of updated expressions. Map> updateFromResource = new HashMap<>(); Map> updateFromVariable = new HashMap<>(); Map> updateFromMessage = new HashMap<>(); @@ -106,6 +123,7 @@ Map> updateFromTuple = new HashMap<>(); Map> updateFromPair = new HashMap<>(); Map> updateFromMap = new HashMap<>(); + Map> updateFromJson = new HashMap<>(); listComponentTypes.put(DataConstraintModel.typeList, null); listComponentTypes.put(DataConstraintModel.typeListInt, DataConstraintModel.typeInt); @@ -123,29 +141,29 @@ mapComponentTypes.put(DataConstraintModel.typeMap, Arrays.asList(new Type[] { null, null })); // 1. Collect type information from the architecture model. - Collection channels = new HashSet<>(model.getIOChannelGenerators()); - channels.addAll(model.getChannelGenerators()); - for (ChannelGenerator c : channels) { + Collection channels = new HashSet<>(model.getIOChannels()); + channels.addAll(model.getChannels()); + for (Channel c : channels) { for (ChannelMember cm : c.getChannelMembers()) { StateTransition st = cm.getStateTransition(); - IdentifierTemplate id = cm.getIdentifierTemplate(); + ResourcePath res = cm.getResource(); // 1.1 Group expressions by resources. - List sameResource = resources.get(id); + List sameResource = resources.get(res); if (sameResource == null) { sameResource = new ArrayList<>(); - resources.put(id, sameResource); + resources.put(res, sameResource); } sameResource.add(st.getCurStateExpression()); if (st.getNextStateExpression() != null) sameResource.add(st.getNextStateExpression()); expToResource.put(System.identityHashCode(st.getCurStateExpression()), sameResource); if (st.getNextStateExpression() != null) expToResource.put(System.identityHashCode(st.getNextStateExpression()), sameResource); Map updatedExps = getUpdateSet(updateFromResource, sameResource); - Type resType = id.getResourceStateType(); + Type resType = res.getResourceStateType(); Expression exp = st.getCurStateExpression(); Type expType = getExpTypeIfUpdatable(resType, exp); if (expType != null) { - id.setResourceStateType(expType); + res.setResourceStateType(expType); for (Expression resExp : sameResource) { if (resExp != exp) { if (resExp instanceof Variable && compareTypes(((Variable) resExp).getType(), expType)) { @@ -168,12 +186,12 @@ updatedExps.put(System.identityHashCode(exp), exp); } } - resType = id.getResourceStateType(); + resType = res.getResourceStateType(); exp = st.getNextStateExpression(); if (exp != null) { expType = getExpTypeIfUpdatable(resType, exp); if (expType != null) { - id.setResourceStateType(expType); + res.setResourceStateType(expType); for (Expression resExp : sameResource) { if (resExp != exp) { if (resExp instanceof Variable && compareTypes(((Variable) resExp).getType(), expType)) { @@ -343,7 +361,7 @@ if (symbol.equals(DataConstraintModel.cons) || symbol.equals(DataConstraintModel.set)) { // If the root symbol of the term is cons or set. List consExps = new ArrayList<>(); - consExps.add(t); + consExps.add(t); // list term updateExpressionBelonging(expToConsOrSet, t, consExps); if (symbol.equals(DataConstraintModel.cons)) { // If the root symbol of the term is cons. @@ -354,10 +372,10 @@ } else { // If the root symbol of the term is set. Expression e = t.getChildren().get(2); - consExps.add(e); + consExps.add(e); // list component updateExpressionBelonging(expToConsOrSet, e, consExps); e = t.getChildren().get(0); - consExps.add(e); + consExps.add(e); // list argument updateExpressionBelonging(expToConsOrSet, e, consExps); } Type newType = getExpTypeIfUpdatable(t.getType(), consExps.get(2)); @@ -410,9 +428,9 @@ // If the root symbol of the term is head or get. List consExps = new ArrayList<>(); Expression e = t.getChildren().get(0); - consExps.add(e); + consExps.add(e); // list argument updateExpressionBelonging(expToConsOrSet, e, consExps); - consExps.add(t); + consExps.add(t); // list's component updateExpressionBelonging(expToConsOrSet, t, consExps); consExps.add(null); Type listType = listTypes.get(t.getType()); @@ -446,11 +464,11 @@ } else if (symbol.equals(DataConstraintModel.tail)) { // If the root symbol of the term is tail. List consExps = new ArrayList<>(); - consExps.add(t); + consExps.add(t); // list term updateExpressionBelonging(expToConsOrSet, t, consExps); - consExps.add(null); + consExps.add(null); // list's component Expression e = t.getChildren().get(0); - consExps.add(e); + consExps.add(e); // list argument updateExpressionBelonging(expToConsOrSet, e, consExps); Type newType = getExpTypeIfUpdatable(t.getType(), consExps.get(2)); if (newType != null) { @@ -482,26 +500,27 @@ } else if (symbol.equals(DataConstraintModel.tuple)) { // If the root symbol of the term is tuple. List tupleExps = new ArrayList<>(); - List argsTypeList = new ArrayList<>(); - tupleExps.add(t); + List newArgTypesList = new ArrayList<>(); + tupleExps.add(t); // tuple term updateExpressionBelonging(expToTuple, t, tupleExps); for (Expression e : t.getChildren()) { - tupleExps.add(e); + tupleExps.add(e); // tuple's component updateExpressionBelonging(expToTuple, e, tupleExps); if (e instanceof Variable) { - argsTypeList.add(((Variable) e).getType()); + newArgTypesList.add(((Variable) e).getType()); } else if (e instanceof Term) { - argsTypeList.add(((Term) e).getType()); + newArgTypesList.add(((Term) e).getType()); } else { - argsTypeList.add(null); + newArgTypesList.add(null); } } if (t.getType() == DataConstraintModel.typeTuple) { - Type newTupleType = tupleTypes.get(argsTypeList); + Type newTupleType = tupleTypes.get(newArgTypesList); if (newTupleType == null) { // Create new tuple type; - newTupleType = createNewTupleType(argsTypeList, DataConstraintModel.typeTuple); + newTupleType = createNewTupleType(newArgTypesList, DataConstraintModel.typeTuple); } + // Update the type of the tuple term and record the updated expression. t.setType(newTupleType); Map updateExps = getUpdateSet(updateFromTuple, tupleExps); updateExps.put(System.identityHashCode(t), t); @@ -510,22 +529,22 @@ } else if (symbol.equals(DataConstraintModel.pair)) { // If the root symbol of the term is pair. List pairExps = new ArrayList<>(); - pairExps.add(t); + pairExps.add(t); // pair updateExpressionBelonging(expToPair, t, pairExps); if (t.getType() == DataConstraintModel.typePair) { for (Expression e : t.getChildren()) { - pairExps.add(e); + pairExps.add(e); // left/right updateExpressionBelonging(expToPair, e, pairExps); - Type argType = null; + Type newArgType = null; if (e instanceof Variable) { - argType = (((Variable) e).getType()); + newArgType = (((Variable) e).getType()); } else if (e instanceof Term) { - argType = (((Term) e).getType()); + newArgType = (((Term) e).getType()); } - if (argType != null) { - Type newPairType = pairTypes.get(argType); + if (newArgType != null) { + Type newPairType = pairTypes.get(newArgType); if (newPairType != null) { t.setType(newPairType); Map updateExps = getUpdateSet(updateFromPair, pairExps); @@ -540,11 +559,11 @@ // If the root symbol of the term is fst. List tupleExps = new ArrayList<>(); Expression arg = t.getChildren().get(0); - tupleExps.add(arg); + tupleExps.add(arg); // tuple argument updateExpressionBelonging(expToTuple, arg, tupleExps); - tupleExps.add(t); + tupleExps.add(t); // first component updateExpressionBelonging(expToTuple, t, tupleExps); - tupleExps.add(null); + tupleExps.add(null); // second component Type argType = null; if (arg instanceof Variable) { argType = ((Variable) arg).getType(); @@ -553,16 +572,17 @@ } Type newTupleType = DataConstraintModel.typeTuple; if (argType == DataConstraintModel.typeTuple && t.getType() != null) { - List compTypeList = new ArrayList<>(); - compTypeList.add(t.getType()); - compTypeList.add(null); - newTupleType = tupleTypes.get(compTypeList); + List newCompTypeList = new ArrayList<>(); + newCompTypeList.add(t.getType()); + newCompTypeList.add(null); + newTupleType = tupleTypes.get(newCompTypeList); if (newTupleType == null) { // Create new tuple type; - newTupleType = createNewTupleType(compTypeList, DataConstraintModel.typeTuple); + newTupleType = createNewTupleType(newCompTypeList, DataConstraintModel.typeTuple); } } if (argType != newTupleType && newTupleType != null) { + // Update the type of the tuple argument and record the updated expression. if (arg instanceof Variable) { ((Variable) arg).setType(newTupleType); argType = newTupleType; @@ -578,10 +598,10 @@ // If the root symbol of the term is snd. List tupleExps = new ArrayList<>(); Expression arg = t.getChildren().get(0); - tupleExps.add(arg); + tupleExps.add(arg); // tuple argument updateExpressionBelonging(expToTuple, arg, tupleExps); - tupleExps.add(null); - tupleExps.add(t); + tupleExps.add(null); // first component + tupleExps.add(t); // second component updateExpressionBelonging(expToTuple, t, tupleExps); Type argType = null; if (arg instanceof Variable) { @@ -591,27 +611,28 @@ } Type newTupleType = DataConstraintModel.typeTuple; if (argType == DataConstraintModel.typeTuple && t.getType() != null) { - List compTypeList = new ArrayList<>(); - compTypeList.add(null); + List newCompTypeList = new ArrayList<>(); + newCompTypeList.add(null); if (DataConstraintModel.typeTuple.isAncestorOf(t.getType())) { List sndTypes = tupleComponentTypes.get(t.getType()); if (sndTypes != null) { for (Type t2: sndTypes) { - compTypeList.add(t2); + newCompTypeList.add(t2); } } else { - compTypeList.add(t.getType()); + newCompTypeList.add(t.getType()); } } else { - compTypeList.add(t.getType()); + newCompTypeList.add(t.getType()); } - newTupleType = tupleTypes.get(compTypeList); + newTupleType = tupleTypes.get(newCompTypeList); if (newTupleType == null) { // Create new tuple type; - newTupleType = createNewTupleType(compTypeList, DataConstraintModel.typeTuple); + newTupleType = createNewTupleType(newCompTypeList, DataConstraintModel.typeTuple); } } if (argType != newTupleType && newTupleType != null) { + // Update the type of the tuple argument and record the updated expression. if (arg instanceof Variable) { ((Variable) arg).setType(newTupleType); argType = newTupleType; @@ -627,11 +648,11 @@ // If the root symbol of the term is left. List pairExps = new ArrayList<>(); Expression arg = t.getChildren().get(0); - pairExps.add(arg); + pairExps.add(arg); // pair updateExpressionBelonging(expToPair, arg, pairExps); - pairExps.add(t); + pairExps.add(t); // left updateExpressionBelonging(expToPair, t, pairExps); - pairExps.add(null); + pairExps.add(null); // right Type argType = null; if (arg instanceof Variable) { argType = ((Variable) arg).getType(); @@ -640,13 +661,13 @@ } Type newPairType = DataConstraintModel.typePair; if (argType == DataConstraintModel.typePair && t.getType() != null) { - List compTypeList = new ArrayList<>(); - compTypeList.add(t.getType()); - compTypeList.add(null); - newPairType = pairTypes.get(compTypeList); + List newCompTypeList = new ArrayList<>(); + newCompTypeList.add(t.getType()); + newCompTypeList.add(null); + newPairType = pairTypes.get(newCompTypeList); if (newPairType == null) { // Create new tuple type; - newPairType = createNewTupleType(compTypeList, DataConstraintModel.typePair); + newPairType = createNewTupleType(newCompTypeList, DataConstraintModel.typePair); } } if (argType != newPairType && newPairType != null) { @@ -665,10 +686,10 @@ // If the root symbol of the term is right. List pairExps = new ArrayList<>(); Expression arg = t.getChildren().get(0); - pairExps.add(arg); + pairExps.add(arg); // pair updateExpressionBelonging(expToPair, arg, pairExps); - pairExps.add(null); - pairExps.add(t); + pairExps.add(null); // left + pairExps.add(t); // right updateExpressionBelonging(expToPair, t, pairExps); Type argType = null; if (arg instanceof Variable) { @@ -678,13 +699,13 @@ } Type newPairType = DataConstraintModel.typePair; if (argType == DataConstraintModel.typePair && t.getType() != null) { - List compTypeList = new ArrayList<>(); - compTypeList.add(null); - compTypeList.add(t.getType()); - newPairType = pairTypes.get(compTypeList); + List newCompTypeList = new ArrayList<>(); + newCompTypeList.add(null); + newCompTypeList.add(t.getType()); + newPairType = pairTypes.get(newCompTypeList); if (newPairType == null) { // Create new tuple type; - newPairType = createNewTupleType(compTypeList, DataConstraintModel.typePair); + newPairType = createNewTupleType(newCompTypeList, DataConstraintModel.typePair); } } if (argType != newPairType && newPairType != null) { @@ -716,21 +737,22 @@ } else if (arg1 instanceof Term) { arg1Type = ((Term) arg1).getType(); } - List compTypeList = new ArrayList<>(); + List newCompTypeList = new ArrayList<>(); if (arg2 instanceof Variable) { - compTypeList.add(((Variable) arg2).getType()); + newCompTypeList.add(((Variable) arg2).getType()); } else if (arg2 instanceof Term) { - compTypeList.add(((Term) arg2).getType()); + newCompTypeList.add(((Term) arg2).getType()); } else { - compTypeList.add(null); + newCompTypeList.add(null); } - compTypeList.add(t.getType()); + newCompTypeList.add(t.getType()); if (arg1Type == DataConstraintModel.typeMap || arg1Type == null) { - Type newMapType = mapTypes.get(compTypeList); + Type newMapType = mapTypes.get(newCompTypeList); if (newMapType == null) { // Create new tuple type; - newMapType = createNewMapType(compTypeList, DataConstraintModel.typeMap); + newMapType = createNewMapType(newCompTypeList, DataConstraintModel.typeMap); } + // Update the type of the map argument and record the updated expression. if (arg1 instanceof Variable) { ((Variable) arg1).setType(newMapType); arg1Type = newMapType; @@ -757,33 +779,186 @@ mapExps.add(arg0); updateExpressionBelonging(expToMap, arg0, mapExps); Type termType = t.getType(); - List compTypeList = new ArrayList<>(); + List newCompTypeList = new ArrayList<>(); if (arg1 instanceof Variable) { - compTypeList.add(((Variable) arg1).getType()); + newCompTypeList.add(((Variable) arg1).getType()); } else if (arg1 instanceof Term) { - compTypeList.add(((Term) arg1).getType()); + newCompTypeList.add(((Term) arg1).getType()); } else { - compTypeList.add(null); + newCompTypeList.add(null); } if (arg2 instanceof Variable) { - compTypeList.add(((Variable) arg2).getType()); + newCompTypeList.add(((Variable) arg2).getType()); } else if (arg2 instanceof Term) { - compTypeList.add(((Term) arg2).getType()); + newCompTypeList.add(((Term) arg2).getType()); } else { - compTypeList.add(null); + newCompTypeList.add(null); } if (termType == DataConstraintModel.typeMap || termType == null) { - Type newMapType = mapTypes.get(compTypeList); + Type newMapType = mapTypes.get(newCompTypeList); if (newMapType == null) { // Create new tuple type; - newMapType = createNewMapType(compTypeList, DataConstraintModel.typeMap); + newMapType = createNewMapType(newCompTypeList, DataConstraintModel.typeMap); } + // Update the type of the map term and record the updated expression. t.setType(newMapType); termType = newMapType; Map updateExps = getUpdateSet(updateFromMap, mapExps); updateExps.put(System.identityHashCode(t), t); } map.put(System.identityHashCode(mapExps), termType); + } else if (symbol.equals(DataConstraintModel.addMember)) { + // If the root symbol of the term is addMember (addMember(json, key, value)). + List dotExps = new ArrayList<>(); + Expression jsonArg = t.getChildren().get(0); + Expression keyArg = t.getChildren().get(1); + Expression valueArg = t.getChildren().get(2); + dotExps.add(t); // json + updateExpressionBelonging(expToJson, t, dotExps); + dotExps.add(keyArg); // key + updateExpressionBelonging(expToJson, keyArg, dotExps); + dotExps.add(valueArg); // value + updateExpressionBelonging(expToJson, valueArg, dotExps); + dotExps.add(jsonArg); // json + updateExpressionBelonging(expToJson, jsonArg, dotExps); + Type jsonType = t.getType(); + Type valueType = null; + if (valueArg instanceof Variable) { + valueType = ((Variable) valueArg).getType(); + } else if (valueArg instanceof Term) { + valueType = ((Term) valueArg).getType(); + } + String keyName = null; + if (keyArg instanceof Constant) { + keyName = ((Constant) keyArg).getSymbol().getName(); + } + Type jsonArgType = null; + if (jsonArg instanceof Variable) { + jsonArgType = ((Variable) jsonArg).getType(); + } else if (jsonArg instanceof Term) { + jsonArgType = ((Term) jsonArg).getType(); + } + Type newJsonType = DataConstraintModel.typeJson; + if (jsonType == DataConstraintModel.typeJson && jsonArgType != null && keyName != null) { + Map newMemberTypes = new HashMap<>(((JsonType) jsonArgType).getMemberTypes()); + newMemberTypes.put(keyName, valueType); + newJsonType = jsonTypes.get(newMemberTypes); + if (newJsonType == null) { + // Create new json type; + newJsonType = createNewJsonType(newMemberTypes, DataConstraintModel.typeJson); + } + } + if (jsonType != newJsonType && newJsonType != null && !newJsonType.isAncestorOf(jsonType)) { + // Update the type of the json term and record the updated expression. + t.setType(newJsonType); + jsonType = newJsonType; + Map updateExps = getUpdateSet(updateFromJson, dotExps); + updateExps.put(System.identityHashCode(t), t); + } + json.put(System.identityHashCode(dotExps), jsonType); + } else if (symbol.equals(DataConstraintModel.dot)) { + // If the root symbol of the term is dot (json.property). + List dotExps = new ArrayList<>(); + Expression jsonArg = t.getChildren().get(0); + Expression keyArg = t.getChildren().get(1); + dotExps.add(jsonArg); // json + updateExpressionBelonging(expToJson, jsonArg, dotExps); + dotExps.add(keyArg); // key + updateExpressionBelonging(expToJson, keyArg, dotExps); + dotExps.add(t); // value + updateExpressionBelonging(expToJson, t, dotExps); + dotExps.add(null); // json + Type jsonType = null; + if (jsonArg instanceof Variable) { + jsonType = ((Variable) jsonArg).getType(); + } else if (jsonArg instanceof Term) { + jsonType = ((Term) jsonArg).getType(); + } + String keyName = null; + if (keyArg instanceof Constant) { + keyName = ((Constant) keyArg).getSymbol().getName(); + } + Type newJsonType = DataConstraintModel.typeJson; + if (jsonType == DataConstraintModel.typeJson && t.getType() != null && keyName != null) { + Map newMemberTypes = new HashMap<>(); + newMemberTypes.put(keyName, t.getType()); + newJsonType = jsonTypes.get(newMemberTypes); + if (newJsonType == null) { + // Create new json type; + newJsonType = createNewJsonType(newMemberTypes, DataConstraintModel.typeJson); + } + } + if (jsonType != newJsonType && newJsonType != null && !newJsonType.isAncestorOf(jsonType)) { + // Update the type of the json argument and record the updated expression. + if (jsonArg instanceof Variable) { + ((Variable) jsonArg).setType(newJsonType); + jsonType = newJsonType; + } else if (jsonArg instanceof Term) { + ((Term) jsonArg).setType(newJsonType); + jsonType = newJsonType; + } + Map updateExps = getUpdateSet(updateFromJson, dotExps); + updateExps.put(System.identityHashCode(jsonArg), jsonArg); + } + json.put(System.identityHashCode(dotExps), jsonType); + } else if (symbol.equals(DataConstraintModel.dotParam)) { + // If the root symbol of the term is dot (json.{param}). + List dotExps = new ArrayList<>(); + Expression jsonArg = t.getChildren().get(0); + Expression keyArg = t.getChildren().get(1); + dotExps.add(jsonArg); // json (list/map) + updateExpressionBelonging(expToJson, jsonArg, dotExps); + dotExps.add(null); // key + dotExps.add(t); // value + updateExpressionBelonging(expToJson, t, dotExps); + dotExps.add(null); // json + Type jsonType = null; + if (jsonArg instanceof Variable) { + jsonType = ((Variable) jsonArg).getType(); + } else if (jsonArg instanceof Term) { + jsonType = ((Term) jsonArg).getType(); + } + Type keyType = null; + if (keyArg instanceof Variable) { + keyType = ((Variable) keyArg).getType(); + } else if (keyArg instanceof Term) { + keyType = ((Term) keyArg).getType(); + } + Type newJsonType = null; + if (keyType == DataConstraintModel.typeInt) { + newJsonType = DataConstraintModel.typeList; + } else if (keyType == DataConstraintModel.typeString) { + newJsonType = DataConstraintModel.typeMap; + } + if (t.getType() != null) { + if ((jsonType == DataConstraintModel.typeList)) { + newJsonType = listTypes.get(t.getType()); + if (newJsonType == null) { + // Create new list type; + newJsonType = createNewListType(t.getType(), DataConstraintModel.typeList); + } + } else if (jsonType == DataConstraintModel.typeMap) { + List keyValueTypes = Arrays.asList(new Type[] {DataConstraintModel.typeString, t.getType()}); + newJsonType = mapTypes.get(keyValueTypes); + if (newJsonType == null) { + // Create new map type; + newJsonType = createNewMapType(keyValueTypes, DataConstraintModel.typeMap); + } + } + } + if (jsonType != newJsonType && newJsonType != null && !newJsonType.isAncestorOf(jsonType)) { + // Update the type of the json argument and record the updated expression. + if (jsonArg instanceof Variable) { + ((Variable) jsonArg).setType(newJsonType); + jsonType = newJsonType; + } else if (jsonArg instanceof Term) { + ((Term) jsonArg).setType(newJsonType); + jsonType = newJsonType; + } + Map updateExps = getUpdateSet(updateFromJson, dotExps); + updateExps.put(System.identityHashCode(jsonArg), jsonArg); + } + json.put(System.identityHashCode(dotExps), jsonType); } else if (symbol.equals(DataConstraintModel.cond)) { // If the root symbol of the term is if function. Expression c1 = t.getChild(1); @@ -929,7 +1104,8 @@ // 2. Propagate type information. while (updateFromResource.size() > 0 || updateFromVariable.size() > 0 || updateFromMessage.size() > 0 - || updateFromConsOrSet.size() > 0 || updateFromTuple.size() > 0 || updateFromPair.size() > 0 || updateFromMap.size() > 0) { + || updateFromConsOrSet.size() > 0 || updateFromTuple.size() > 0 || updateFromPair.size() > 0 + || updateFromMap.size() > 0 || updateFromJson.size() > 0) { if (updateFromResource.size() > 0) { Set resourceKeys = updateFromResource.keySet(); Integer resourceKey = resourceKeys.iterator().next(); @@ -943,6 +1119,7 @@ updateTupleTypes(resExp, tuple, expToTuple, updateFromTuple); updatePairTypes(resExp, pair, expToPair, updateFromPair); updateMapTypes(resExp, map, expToMap, updateFromMap); + updateJsonTypes(resExp, json, expToJson, updateFromJson); } } if (updateFromVariable.size() > 0) { @@ -959,6 +1136,7 @@ updateTupleTypes(var, tuple, expToTuple, updateFromTuple); updatePairTypes(var, pair, expToPair, updateFromPair); updateMapTypes(var, map, expToMap, updateFromMap); + updateJsonTypes(var, json, expToJson, updateFromJson); } } if (updateFromMessage.size() > 0) { @@ -974,6 +1152,7 @@ updateTupleTypes(mesExp, tuple, expToTuple, updateFromTuple); updatePairTypes(mesExp, pair, expToPair, updateFromPair); updateMapTypes(mesExp, map, expToMap, updateFromMap); + updateJsonTypes(mesExp, json, expToJson, updateFromJson); } } if (updateFromConsOrSet.size() > 0) { @@ -990,6 +1169,7 @@ updateTupleTypes(consExp, tuple, expToTuple, updateFromTuple); updatePairTypes(consExp, pair, expToPair, updateFromPair); updateMapTypes(consExp, map, expToMap, updateFromMap); + updateJsonTypes(consExp, json, expToJson, updateFromJson); } } if (updateFromTuple.size() > 0) { @@ -1006,6 +1186,7 @@ updateTupleTypes(tupleExp, tuple, expToTuple, updateFromTuple); updatePairTypes(tupleExp, pair, expToPair, updateFromPair); updateMapTypes(tupleExp, map, expToMap, updateFromMap); + updateJsonTypes(tupleExp, json, expToJson, updateFromJson); } } if (updateFromPair.size() > 0) { @@ -1022,6 +1203,7 @@ updateTupleTypes(pairExp, tuple, expToTuple, updateFromTuple); updatePairTypes(pairExp, pair, expToPair, updateFromPair); updateMapTypes(pairExp, map, expToMap, updateFromMap); + updateJsonTypes(pairExp, json, expToJson, updateFromJson); } } if (updateFromMap.size() > 0) { @@ -1038,6 +1220,24 @@ updateTupleTypes(mapExp, tuple, expToTuple, updateFromTuple); updatePairTypes(mapExp, pair, expToPair, updateFromPair); updateMapTypes(mapExp, map, expToMap, updateFromMap); + updateJsonTypes(mapExp, json, expToJson, updateFromJson); + } + } + if (updateFromJson.size() > 0) { + Set jsonKeys = updateFromJson.keySet(); + Integer jsonKey = jsonKeys.iterator().next(); + Map jsonValue = updateFromJson.get(jsonKey); + updateFromJson.remove(jsonKey); + for (int i : jsonValue.keySet()) { + Expression jsonExp = jsonValue.get(i); + updateResourceTypes(jsonExp, resources, expToResource, updateFromResource); + updateVaribleTypes(jsonExp, variables, expToVariable, updateFromVariable); + updateMessageTypes(jsonExp, messages, expToMessage, updateFromMessage); + updateConsOrSetTypes(jsonExp, consOrSet, expToConsOrSet, updateFromConsOrSet); + updateTupleTypes(jsonExp, tuple, expToTuple, updateFromTuple); + updatePairTypes(jsonExp, pair, expToPair, updateFromPair); + updateMapTypes(jsonExp, map, expToMap, updateFromMap); + updateJsonTypes(jsonExp, json, expToJson, updateFromJson); } } } @@ -1056,16 +1256,16 @@ } } - private static void updateResourceTypes(Expression exp, Map> resources, + private static void updateResourceTypes(Expression exp, Map> resources, Map> expToResource, Map> updateFromResource) { List sameResource = expToResource.get(System.identityHashCode(exp)); if (sameResource == null) return; - for (IdentifierTemplate id : resources.keySet()) { - if (resources.get(id) == sameResource) { - Type resType = id.getResourceStateType(); + for (ResourcePath res : resources.keySet()) { + if (resources.get(res) == sameResource) { + Type resType = res.getResourceStateType(); Type newResType = getExpTypeIfUpdatable(resType, exp); if (newResType != null) { - id.setResourceStateType(newResType); + res.setResourceStateType(newResType); Map updateExps = getUpdateSet(updateFromResource, sameResource); for (Expression resExp : sameResource) { if (resExp != exp) { @@ -1124,13 +1324,13 @@ } private static void updateMessageTypes(Expression exp, - Map, Type>>> messages, + Map, Type>>> messages, Map> expToMessage, Map> updateFromMessage) { List messageExps = expToMessage.get(System.identityHashCode(exp)); if (messageExps == null) return; Type msgType = null; Map.Entry, Type> expsAndType = null; - for (ChannelGenerator c : messages.keySet()) { + for (Channel c : messages.keySet()) { for (int i : messages.get(c).keySet()) { expsAndType = messages.get(c).get(i); if (expsAndType.getKey() == messageExps) { @@ -1167,6 +1367,7 @@ int idx = consOrSetComponentGroup.indexOf(exp); switch (idx) { case 0: + // exp is a list itself. if (!(exp instanceof Term)) break; Type listType = consOrSet.get(System.identityHashCode(consOrSetComponentGroup)); Type expType = getExpTypeIfUpdatable(listType, exp); @@ -1191,6 +1392,7 @@ } break; case 1: + // exp is a list's component. listType = consOrSet.get(System.identityHashCode(consOrSetComponentGroup)); Type compType = listComponentTypes.get(listType); Type newCompType = getExpTypeIfUpdatable(compType, exp); @@ -1216,6 +1418,7 @@ } break; case 2: + // exp is a list itself. listType = consOrSet.get(System.identityHashCode(consOrSetComponentGroup)); expType = getExpTypeIfUpdatable(listType, exp); if (expType != null) { @@ -1245,6 +1448,7 @@ for (List tupleComponentGroup: tupleComponentGroups) { int idx = tupleComponentGroup.indexOf(exp); if (idx == 0) { + // exp is a tuple itself. Type tupleType = tuple.get(System.identityHashCode(tupleComponentGroup)); Type newTupleType = getExpTypeIfUpdatable(tupleType, exp); if (newTupleType != null) { @@ -1312,6 +1516,7 @@ } } } else { + // exp is a tuple's component. Type tupleType = tuple.get(System.identityHashCode(tupleComponentGroup)); List componentTypes = tupleComponentTypes.get(tupleType); boolean updated = false; @@ -1382,6 +1587,7 @@ for (List pairComponentGroup: pairComponentGroups) { int idx = pairComponentGroup.indexOf(exp); if (idx == 0) { + // exp is a pair itself. Type pairType = pair.get(System.identityHashCode(pairComponentGroup)); Type newPairType = getExpTypeIfUpdatable(pairType, exp); if (newPairType != null) { @@ -1405,6 +1611,7 @@ } } } else { + // exp is a pair's component. Type pairType = pair.get(System.identityHashCode(pairComponentGroup)); Type compType = pairComponentTypes.get(pairType); Type newCompType = getExpTypeIfUpdatable(compType, exp); @@ -1435,6 +1642,7 @@ for (List mapComponentGroup: mapComponentGroups) { int idx = mapComponentGroup.indexOf(exp); if (idx == 0 || idx == 3) { + // exp is a map itself. Type mapType = map.get(System.identityHashCode(mapComponentGroup)); Type newMapType = getExpTypeIfUpdatable(mapType, exp); if (newMapType != null) { @@ -1478,6 +1686,7 @@ } } } else { + // exp is a map's key or value. Type mapType = map.get(System.identityHashCode(mapComponentGroup)); List componentTypes = mapComponentTypes.get(mapType); Type compType = componentTypes.get(idx - 1); @@ -1516,6 +1725,116 @@ } } + + private static void updateJsonTypes(Expression exp, Map json, + Map>> expToJson, Map> updateFromJson) { + Set> jsonMemberGroups = expToJson.get(System.identityHashCode(exp)); + if (jsonMemberGroups == null) return; + for (List jsonMemberGroup: jsonMemberGroups) { + int idx = jsonMemberGroup.indexOf(exp); + if (idx == 3) { + // exp is a json argument (0:t = addMember(3:json, 1:key, 2:value)). + Type jsonType = json.get(System.identityHashCode(jsonMemberGroup)); + Map memberTypes = new HashMap<>(jsonMemberTypes.get(jsonType)); + Map argMemberTypes = new HashMap<>(memberTypes); + String keyName = null; + Type valueType = null; + if (jsonMemberGroup.get(1) instanceof Constant) { + keyName = ((Constant) jsonMemberGroup.get(1)).getSymbol().getName(); + valueType = ((Constant) jsonMemberGroup.get(1)).getType(); + argMemberTypes.remove(keyName); + } + Type jsonArgType = jsonTypes.get(argMemberTypes); + Type newJsonArgType = getExpTypeIfUpdatable(jsonArgType, exp); + if (newJsonArgType != null && keyName != null) { + // Propagate an update of a json arg's type to its container's (json's) type. + argMemberTypes = ((JsonType) newJsonArgType).getMemberTypes(); + argMemberTypes.put(keyName, valueType); + memberTypes.putAll(argMemberTypes); + Type newJsonType = jsonTypes.get(memberTypes); + if (newJsonType == null) { + // Create new json type. + newJsonType = createNewJsonType(memberTypes, jsonType); + } + // Update the type of the json term and record the updated expression. + Map updateExps = getUpdateSet(updateFromJson, jsonMemberGroup); + Expression jsonExp = jsonMemberGroup.get(0); + if (jsonExp instanceof Variable) { + ((Variable) jsonExp).setType(newJsonType); + updateExps.put(System.identityHashCode(jsonExp), jsonExp); + } else if (jsonExp instanceof Term) { + ((Term) jsonExp).setType(newJsonType); + updateExps.put(System.identityHashCode(jsonExp), jsonExp); + } + json.put(System.identityHashCode(jsonMemberGroup), newJsonType); + } + } else if (idx == 2) { + // exp is a value (0:t = addMember(3:json, 1:key, 2:value) or 2:value = dot(0:list/map, 1:key)). + Type jsonType = json.get(System.identityHashCode(jsonMemberGroup)); + Type newJsonType = null; + if (exp instanceof Term && ((Term) exp).getSymbol().equals(DataConstraintModel.dotParam)) { + if (DataConstraintModel.typeList.isAncestorOf(jsonType)) { + Type elementType = listComponentTypes.get(jsonType); + Type newElementType = getExpTypeIfUpdatable(elementType, exp); + if (newElementType != null) { + // Propagate an update of a member's type to its container's (json's) type. + newJsonType = listTypes.get(newElementType); + if (newJsonType == null) { + // Create new json type. + newJsonType = createNewListType(newElementType, jsonType); + } + } + } else if (DataConstraintModel.typeMap.isAncestorOf(jsonType)) { + List keyValueTypes = mapComponentTypes.get(jsonType); + Type newValueType = getExpTypeIfUpdatable(keyValueTypes.get(1), exp); + if (newValueType != null) { + // Propagate an update of a member's type to its container's (json's) type. + List newKeyValueTypes = Arrays.asList(new Type[] {DataConstraintModel.typeString, newValueType}); + newJsonType = mapTypes.get(newKeyValueTypes); + if (newJsonType == null) { + // Create new json type. + newJsonType = createNewMapType(newKeyValueTypes, jsonType); + } + } + } + } else { + Map memberTypes = jsonMemberTypes.get(jsonType); + String keyName = null; + if (jsonMemberGroup.get(1) instanceof Constant) { + keyName = ((Constant) jsonMemberGroup.get(1)).getSymbol().getName(); + } + if (memberTypes != null) { + Type memberType = memberTypes.get(keyName); + Type newMemberType = getExpTypeIfUpdatable(memberType, exp); + if (newMemberType != null && keyName != null) { + // Propagate an update of a member's type to its container's (json's) type. + Map newMemberTypes = new HashMap<>(memberTypes); + newMemberTypes.put(keyName, newMemberType); + newJsonType = jsonTypes.get(newMemberTypes); + if (newJsonType == null) { + // Create new json type. + newJsonType = createNewJsonType(newMemberTypes, jsonType); + } + } + } + } + if (newJsonType != null) { + // Update the type of the json term and record the updated expression. + Map updateExps = getUpdateSet(updateFromJson, jsonMemberGroup); + Expression jsonExp = jsonMemberGroup.get(0); + if (jsonExp instanceof Variable) { + ((Variable) jsonExp).setType(newJsonType); + updateExps.put(System.identityHashCode(jsonExp), jsonExp); + } else if (jsonExp instanceof Term) { + ((Term) jsonExp).setType(newJsonType); + updateExps.put(System.identityHashCode(jsonExp), jsonExp); + } + json.put(System.identityHashCode(jsonMemberGroup), newJsonType); + } + } + } + } + private static Type createNewListType(Type compType, Type parentType) { String compTypeName = getInterfaceTypeName(compType); List childrenTypes = getChildrenTypes(parentType, listComponentTypes.keySet()); @@ -1598,9 +1917,39 @@ return newMapType; } - private static List getChildrenTypes(Type parentType, Set componentTypes) { + private static JsonType createNewJsonType(Map memberTypes, Type parentJsonType) { + String implTypeName = "HashMap<>"; + String interfaceTypeName = "Map"; + List childrenTypes = getChildrenTypes(parentJsonType, jsonMemberTypes.keySet()); + JsonType newJsonType = new JsonType("Json", implTypeName, interfaceTypeName, parentJsonType); + for (String key: memberTypes.keySet()) { + newJsonType.addMemberType(key, memberTypes.get(key)); + } + jsonTypes.put(memberTypes, newJsonType); + jsonMemberTypes.put(newJsonType, memberTypes); + for (Type childType : childrenTypes) { + if (compareTypes(childType, newJsonType)) { + if (newJsonType.getParentTypes().contains(parentJsonType)) { + newJsonType.replaceParentType(parentJsonType, childType); + } else { + newJsonType.addParentType(childType); + } + } else if (compareTypes(newJsonType, childType)) { + childType.replaceParentType(parentJsonType, newJsonType); + } + } + return newJsonType; + } + + /** + * Get children types of a given type from given set of types. + * @param parentType a type + * @param allTypes set of types + * @return list of the children types + */ + private static List getChildrenTypes(Type parentType, Set allTypes) { List childrenTypes = new ArrayList<>(); - for (Type childType : componentTypes) { + for (Type childType : allTypes) { if (childType.getParentTypes().contains(parentType)) { childrenTypes.add(childType); } @@ -1626,8 +1975,7 @@ return type.getInterfaceTypeName(); } - private static > Map getUpdateSet( - Map> updateSets, U keySet) { + private static > Map getUpdateSet(Map> updateSets, U keySet) { Map updatedExps = updateSets.get(System.identityHashCode(keySet)); if (updatedExps == null) { updatedExps = new HashMap<>(); @@ -1683,6 +2031,7 @@ for (int i = 0; i < originalCompTypes.size(); i++) { if (originalCompTypes.get(i) != null) { if (DataConstraintModel.typeTuple.isAncestorOf(originalCompTypes.get(i))) { + // Unfold the nested tuple's types. Type tupleType = originalCompTypes.remove(i); for (Type t: tupleComponentTypes.get(tupleType)) { originalCompTypes.add(t); @@ -1690,6 +2039,7 @@ } if (newCompTypes.size() - 1 < i) return false; if (newCompTypes.get(i) != null && DataConstraintModel.typeTuple.isAncestorOf(newCompTypes.get(i))) { + // Unfold the nested tuple's types. Type tupleType = newCompTypes.remove(i); for (Type t: tupleComponentTypes.get(tupleType)) { newCompTypes.add(t); @@ -1707,6 +2057,19 @@ if (originalCompType != null && (newCompType == null || !originalCompType.isAncestorOf(newCompType))) return false; return true; } + if (DataConstraintModel.typeJson.isAncestorOf(originalType) && DataConstraintModel.typeJson.isAncestorOf(newType)) { + Map originalMemberTypes = jsonMemberTypes.get(originalType); + Map newMemberTypes = jsonMemberTypes.get(newType); + if (originalMemberTypes == null) return true; + if (originalMemberTypes.keySet().size() < newMemberTypes.keySet().size() + && newMemberTypes.keySet().containsAll(originalMemberTypes.keySet())) return true; + if (originalMemberTypes.keySet().size() > newMemberTypes.keySet().size()) return false; + if (!newMemberTypes.keySet().containsAll(originalMemberTypes.keySet())) return false; + for (String key: originalMemberTypes.keySet()) { + if (!originalMemberTypes.get(key).isAncestorOf(newMemberTypes.get(key))) return false; + } + return true; + } } return false; } diff --git a/AlgebraicDataflowArchitectureModel/src/application/ApplicationLanguage.java b/AlgebraicDataflowArchitectureModel/src/application/ApplicationLanguage.java new file mode 100644 index 0000000..b99952d --- /dev/null +++ b/AlgebraicDataflowArchitectureModel/src/application/ApplicationLanguage.java @@ -0,0 +1,72 @@ +package application; + +import java.io.File; +import java.net.MalformedURLException; +import java.net.URL; +import java.net.URLClassLoader; +import java.nio.file.Paths; +import java.util.Locale; +import java.util.ResourceBundle; + +/*********************************************************************** + * + * + */ +public class ApplicationLanguage { + private Locale locale = null; + private ResourceBundle resBundle = null; + + private static ApplicationLanguage instance = null; + + private final static String RESOURCE_PATH = ".\\resources\\locales"; + + public final static String JP = "ja"; + public final static String EN = "en"; + + /*********************************************************************** + * [ *constructor ] + /*********************************************************************** + * + * @return + */ + private ApplicationLanguage() { + this.locale = Locale.getDefault(); + setLocaleLanguage(this.locale.getLanguage()); + } + + /*********************************************************************** + * [ *public static] + * /*********************************************************************** + * + * @return + */ + public static ApplicationLanguage getInstance() { + if (instance == null) + instance = new ApplicationLanguage(); + return instance; + } + + /*********************************************************************** + * + /*********************************************************************** + * + */ + public void setLocaleLanguage(final String language) { + File dicDirectory = Paths.get(RESOURCE_PATH).toFile(); + URLClassLoader urlLoader = null; + try { + urlLoader = new URLClassLoader(new URL[] { dicDirectory.toURI().toURL() }); + } catch (MalformedURLException e) { + return; + } + + this.resBundle = ResourceBundle.getBundle(language, this.locale, urlLoader); + } + + /*********************************************************************** + * + */ + public String getOptionByPropName(final String propName) { + return this.resBundle.getString(propName); + } +} diff --git a/AlgebraicDataflowArchitectureModel/src/application/ApplicationMenuBar.java b/AlgebraicDataflowArchitectureModel/src/application/ApplicationMenuBar.java new file mode 100644 index 0000000..b63e9f8 --- /dev/null +++ b/AlgebraicDataflowArchitectureModel/src/application/ApplicationMenuBar.java @@ -0,0 +1,100 @@ +package application; + +import javax.swing.JMenu; +import javax.swing.JMenuBar; + +import application.actions.CircleLayoutAction; +import application.actions.DAGLayoutAction; +import application.actions.DeleteAction; +import application.actions.ExitAction; +import application.actions.JavaPrototypeGenerateAction; +import application.actions.JerseyPrototypeGenerateAction; +import application.actions.NewChannelAction; +import application.actions.NewFormulaChannelAction; +import application.actions.NewIOChannelAction; +import application.actions.NewModelAction; +import application.actions.NewResourceAction; +import application.actions.OpenAction; +import application.actions.SaveAction; +import application.actions.SaveAsAction; +import application.actions.ShowNavigationAction; +import application.actions.ShowFlowLayerWindowAction; +import application.actions.TreeLayoutAction; +import application.actions.ZoomInAction; +import application.actions.ZoomOutAction; +import application.editor.Editor; + +public class ApplicationMenuBar extends JMenuBar { + private static final long serialVersionUID = 4811536194182272888L; + + private ApplicationWindow applicationWindow = null; + + private NewResourceAction newResourceAction = null; + private NewChannelAction newChannelAction = null; + private NewIOChannelAction newIOChannelAction = null; + private NewFormulaChannelAction newFormulaChannelAction = null; + private DeleteAction deleteAction = null; + private JavaPrototypeGenerateAction javaPrototypeGenerateAction = null; + private JerseyPrototypeGenerateAction jerseyPrototypeGenerateAction = null; + private DAGLayoutAction dagLayoutAction = null; + private TreeLayoutAction treeLayoutAction = null; + private CircleLayoutAction circleLayoutAction = null; + + public ApplicationMenuBar(ApplicationWindow applicationWindow) { + this.applicationWindow = applicationWindow; + JMenu newMenu = new JMenu(ApplicationLanguage.getInstance().getOptionByPropName("new")); + + newMenu.add(new NewModelAction(applicationWindow)); + + newMenu.add(newResourceAction = new NewResourceAction(applicationWindow.getEditor())); + newMenu.add(newChannelAction = new NewChannelAction(applicationWindow.getEditor())); + newMenu.add(newIOChannelAction = new NewIOChannelAction(applicationWindow.getEditor())); + newMenu.add(newFormulaChannelAction = new NewFormulaChannelAction(applicationWindow.getEditor())); + + JMenu menu = null; + menu = add(new JMenu(ApplicationLanguage.getInstance().getOptionByPropName("file"))); + menu.add(newMenu); + menu.add(new OpenAction(applicationWindow)); + menu.addSeparator(); + menu.add(new SaveAction(applicationWindow)); + menu.add(new SaveAsAction(applicationWindow)); + menu.addSeparator(); + menu.add(new ExitAction()); + + menu = add(new JMenu(ApplicationLanguage.getInstance().getOptionByPropName("edit"))); + menu.add(deleteAction = new DeleteAction(applicationWindow.getEditor())); + + + menu = add(new JMenu(ApplicationLanguage.getInstance().getOptionByPropName("layout"))); + menu.add(dagLayoutAction = new DAGLayoutAction(applicationWindow.getEditor())); + menu.add(treeLayoutAction = new TreeLayoutAction(applicationWindow.getEditor())); + menu.add(circleLayoutAction = new CircleLayoutAction(applicationWindow.getEditor())); + + menu = add(new JMenu(ApplicationLanguage.getInstance().getOptionByPropName("view"))); + menu.add(new ZoomInAction(applicationWindow.getGraphComponent())); + menu.add(new ZoomOutAction(applicationWindow.getGraphComponent())); + + menu = add(new JMenu(ApplicationLanguage.getInstance().getOptionByPropName("generate"))); + menu.add(javaPrototypeGenerateAction = new JavaPrototypeGenerateAction(applicationWindow.getEditor())); + menu.add(jerseyPrototypeGenerateAction = new JerseyPrototypeGenerateAction(applicationWindow.getEditor())); + + menu = add(new JMenu(ApplicationLanguage.getInstance().getOptionByPropName("window"))); + menu.add(new ShowNavigationAction(applicationWindow)); + menu.add(new ShowFlowLayerWindowAction(applicationWindow)); + } + + public Editor getEditor() { + return applicationWindow.getEditor(); + } + + public void setEditor(Editor editor) { + newResourceAction.setEditor(editor); + newChannelAction.setEditor(editor); + newIOChannelAction.setEditor(editor); + deleteAction.setEditor(editor); + javaPrototypeGenerateAction.setEditor(editor); + jerseyPrototypeGenerateAction.setEditor(editor); + treeLayoutAction.setEditor(editor); + circleLayoutAction.setEditor(editor); + } +} diff --git a/AlgebraicDataflowArchitectureModel/src/application/ApplicationWindow.java b/AlgebraicDataflowArchitectureModel/src/application/ApplicationWindow.java new file mode 100644 index 0000000..d4a58e1 --- /dev/null +++ b/AlgebraicDataflowArchitectureModel/src/application/ApplicationWindow.java @@ -0,0 +1,117 @@ +package application; + +import java.io.IOException; +import java.util.logging.FileHandler; +import java.util.logging.Handler; +import java.util.logging.Level; +import java.util.logging.Logger; +import java.util.logging.SimpleFormatter; + +import javax.swing.JFrame; + +import com.mxgraph.model.mxGeometry; +import com.mxgraph.swing.mxGraphComponent; +import com.mxgraph.swing.handler.mxRubberband; +import com.mxgraph.view.mxGraph; + +import application.editor.Editor; +import application.views.NavigationWindow; +import application.views.controlFlowDelegation.FlowLayerWindow; + +/** + * Application main window + * + * @author Nitta Lab. + * + */ +public class ApplicationWindow extends JFrame { + private static final long serialVersionUID = -8690140317781055614L; + public static final String title = "Visual Modeling Tool"; + public static final Logger logger = Logger.getLogger("dtram"); + + private Editor editor = null; + private mxGraph graph = null; + private mxGraphComponent graphComponent = null; + + private ApplicationMenuBar menuBar = null; + private NavigationWindow navigationWindow = null; + private FlowLayerWindow showFlowLayerWindow = null; + + public ApplicationWindow() { + setTitle(title); + setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); + + try { + Handler fh = new FileHandler("dtram.log", true); + fh.setFormatter(new SimpleFormatter()); + logger.addHandler(fh); + } catch (SecurityException | IOException e) { + e.printStackTrace(); + } + logger.setLevel(Level.INFO); + logger.log(Level.INFO, "launched"); + + // If you want to change the language, change here. + ApplicationLanguage.getInstance().setLocaleLanguage(ApplicationLanguage.JP); + + this.graph = new mxGraph() { + public boolean isPort(Object cell) { + mxGeometry geo = getCellGeometry(cell); + + return (geo != null) ? geo.isRelative() : false; + } + + public boolean isCellFoldable(Object cell, boolean collapse) { + return false; + } + }; + + this.graphComponent = new mxGraphComponent(graph); + + this.editor = new Editor(graphComponent); + + getContentPane().add(graphComponent); + new mxRubberband(graphComponent); + graph.setAllowDanglingEdges(false); + graph.setCellsDisconnectable(true); + graph.setDropEnabled(false); + + menuBar = new ApplicationMenuBar(this); + setJMenuBar(menuBar); + setSize(870, 640); + + navigationWindow = new NavigationWindow(this, editor); + navigationWindow.setVisible(true); + + showFlowLayerWindow = new FlowLayerWindow(this); + showFlowLayerWindow.setVisible(false); + + editor.addStageChangeListener(navigationWindow); + editor.addStageChangeListener(showFlowLayerWindow); + } + + public mxGraph getGraph() { + return graph; + } + + public mxGraphComponent getGraphComponent() { + return graphComponent; + } + + public Editor getEditor() { + return editor; + } + + public void setEditor(Editor editor) { + this.editor = editor; + } + + public void showNavigationWindow() { + navigationWindow.setVisible(true); + } + + public void showSwitchLayerWindow() { + showFlowLayerWindow.setVisible(true); + } + +} diff --git a/AlgebraicDataflowArchitectureModel/src/application/actions/AbstractEditorAction.java b/AlgebraicDataflowArchitectureModel/src/application/actions/AbstractEditorAction.java new file mode 100644 index 0000000..2db8692 --- /dev/null +++ b/AlgebraicDataflowArchitectureModel/src/application/actions/AbstractEditorAction.java @@ -0,0 +1,29 @@ +package application.actions; + +import java.awt.event.ActionEvent; +import java.util.logging.Level; + +import javax.swing.AbstractAction; +import javax.swing.Action; + +import application.ApplicationLanguage; +import application.ApplicationWindow; +import application.editor.Editor; + +public abstract class AbstractEditorAction extends AbstractAction { + protected Editor editor; + + public AbstractEditorAction(String propName, Editor editor) { + super(ApplicationLanguage.getInstance().getOptionByPropName(propName)); + this.editor = editor; + } + + public void setEditor(Editor editor) { + this.editor = editor; + } + + @Override + public void actionPerformed(ActionEvent e) { + ApplicationWindow.logger.log(Level.INFO, (String) getValue(Action.NAME)); + } +} \ No newline at end of file diff --git a/AlgebraicDataflowArchitectureModel/src/application/actions/AbstractPopupAction.java b/AlgebraicDataflowArchitectureModel/src/application/actions/AbstractPopupAction.java new file mode 100644 index 0000000..665fce0 --- /dev/null +++ b/AlgebraicDataflowArchitectureModel/src/application/actions/AbstractPopupAction.java @@ -0,0 +1,33 @@ +package application.actions; + +import java.awt.event.ActionEvent; +import java.util.logging.Level; + +import javax.swing.AbstractAction; +import javax.swing.Action; + +import com.mxgraph.model.mxCell; +import com.mxgraph.swing.mxGraphComponent; + +import application.ApplicationLanguage; +import application.ApplicationWindow; + +public abstract class AbstractPopupAction extends AbstractAction { + protected mxGraphComponent graphComponent = null; + protected mxCell targetCell = null; + + public AbstractPopupAction(final String propName, final mxCell targetCell, final mxGraphComponent graphComponent) { + super(ApplicationLanguage.getInstance().getOptionByPropName(propName)); + this.graphComponent = graphComponent; + this.targetCell = targetCell; + } + + public void updateTargetCell(final mxCell targetCell) { + this.targetCell = targetCell; + } + + @Override + public void actionPerformed(ActionEvent e) { + ApplicationWindow.logger.log(Level.INFO, (String) getValue(Action.NAME)); + } +} diff --git a/AlgebraicDataflowArchitectureModel/src/application/actions/AbstractSystemAction.java b/AlgebraicDataflowArchitectureModel/src/application/actions/AbstractSystemAction.java new file mode 100644 index 0000000..76b644b --- /dev/null +++ b/AlgebraicDataflowArchitectureModel/src/application/actions/AbstractSystemAction.java @@ -0,0 +1,30 @@ +package application.actions; + +import java.awt.event.ActionEvent; +import java.util.logging.Level; + +import javax.swing.AbstractAction; +import javax.swing.Action; + +import application.ApplicationLanguage; +import application.ApplicationWindow; +import application.editor.Editor; + +public abstract class AbstractSystemAction extends AbstractAction { + + protected ApplicationWindow frame; + + public AbstractSystemAction(String propName, ApplicationWindow frame) { + super(ApplicationLanguage.getInstance().getOptionByPropName(propName)); + this.frame = frame; + } + + public void setFrame(ApplicationWindow frame) { + this.frame = frame; + } + + @Override + public void actionPerformed(ActionEvent e) { + ApplicationWindow.logger.log(Level.INFO, (String) getValue(Action.NAME)); + } +} diff --git a/AlgebraicDataflowArchitectureModel/src/application/actions/AbstractViewerAction.java b/AlgebraicDataflowArchitectureModel/src/application/actions/AbstractViewerAction.java new file mode 100644 index 0000000..f7a283d --- /dev/null +++ b/AlgebraicDataflowArchitectureModel/src/application/actions/AbstractViewerAction.java @@ -0,0 +1,27 @@ +package application.actions; + +import java.awt.event.ActionEvent; +import java.util.logging.Level; + +import javax.swing.AbstractAction; +import javax.swing.Action; + +import com.mxgraph.swing.mxGraphComponent; + +import application.ApplicationLanguage; +import application.ApplicationWindow; + +public abstract class AbstractViewerAction extends AbstractAction { + + protected mxGraphComponent graphComponent = null; + + public AbstractViewerAction(String propName, mxGraphComponent graphComponent) { + super(ApplicationLanguage.getInstance().getOptionByPropName(propName)); + this.graphComponent = graphComponent; + } + + @Override + public void actionPerformed(ActionEvent e) { + ApplicationWindow.logger.log(Level.INFO, (String) getValue(Action.NAME)); + } +} diff --git a/AlgebraicDataflowArchitectureModel/src/application/actions/ChangeCallOrderAction.java b/AlgebraicDataflowArchitectureModel/src/application/actions/ChangeCallOrderAction.java new file mode 100644 index 0000000..f504228 --- /dev/null +++ b/AlgebraicDataflowArchitectureModel/src/application/actions/ChangeCallOrderAction.java @@ -0,0 +1,77 @@ +package application.actions; + +import java.awt.event.ActionEvent; + +import javax.swing.JOptionPane; + +import com.mxgraph.model.mxCell; +import com.mxgraph.swing.mxGraphComponent; + +import models.controlFlowModel.CallEdgeAttribute; + +/************************************************************* + * + */ +public class ChangeCallOrderAction extends AbstractPopupAction { + + /************************************************************* + * [ *constructor ] + /************************************************************* + */ + public ChangeCallOrderAction(final mxGraphComponent graphComponent ,final mxCell cell) { + super(/*propName*/"changeCallOrder", cell, graphComponent); + } + + /************************************************************* + * [ *public ] + /************************************************************* + * + */ + @Override + public void actionPerformed(ActionEvent e) { + super.actionPerformed(e); + if(targetCell == null) return; + changeCallOrderOfCallEdge(targetCell); + } + + /************************************************************* + * [ *private ] + /************************************************************* + */ + private void changeCallOrderOfCallEdge(Object cellObj) { + String input = ""; + int inputOrder = 0; + + CallEdgeAttribute callEdgeAttr = (CallEdgeAttribute)graphComponent.getGraph().getModel().getValue(cellObj); + if(callEdgeAttr == null) return; + + input = JOptionPane.showInputDialog("Call order"); + if( input == null) return; + + if( !isNumeric(input) ) { + JOptionPane.showMessageDialog(graphComponent, "Input value must type of number."); + return; + } + + inputOrder = Integer.parseInt(input); + + final int endOfOrderOfSrc = callEdgeAttr.getSourceObjectNode().getOutdegree(); + if(inputOrder <= 0 || endOfOrderOfSrc < inputOrder) { + JOptionPane.showMessageDialog(graphComponent, "Input order must be between 1 and " + endOfOrderOfSrc + "."); + return; + } + + int curOrder = callEdgeAttr.getSourceObjectNode().getOutEdgeCallOrder(callEdgeAttr.getCallEdge()); + callEdgeAttr.getSourceObjectNode().sortOutEdgesByCallOrder(curOrder, inputOrder); + + graphComponent.refresh(); + } + + /************************************************************* + * + */ + private boolean isNumeric(final String str) { + if(str == null) return false; + return str.matches("[0-9.]+"); + } +} \ No newline at end of file diff --git a/AlgebraicDataflowArchitectureModel/src/application/actions/CircleLayoutAction.java b/AlgebraicDataflowArchitectureModel/src/application/actions/CircleLayoutAction.java new file mode 100644 index 0000000..d19ff89 --- /dev/null +++ b/AlgebraicDataflowArchitectureModel/src/application/actions/CircleLayoutAction.java @@ -0,0 +1,19 @@ +package application.actions; + +import java.awt.event.ActionEvent; + +import application.editor.Editor; + +public class CircleLayoutAction extends AbstractEditorAction { + + public CircleLayoutAction(Editor editor) { + super(/*propName*/"circleLayout", editor); + } + + @Override + public void actionPerformed(ActionEvent e) { + super.actionPerformed(e); + editor.setCircleLayout(); + } + +} diff --git a/AlgebraicDataflowArchitectureModel/src/application/actions/DAGLayoutAction.java b/AlgebraicDataflowArchitectureModel/src/application/actions/DAGLayoutAction.java new file mode 100644 index 0000000..a06c8f5 --- /dev/null +++ b/AlgebraicDataflowArchitectureModel/src/application/actions/DAGLayoutAction.java @@ -0,0 +1,19 @@ +package application.actions; + +import java.awt.event.ActionEvent; + +import application.editor.Editor; + +public class DAGLayoutAction extends AbstractEditorAction { + + public DAGLayoutAction(Editor editor) { + super(/*propName*/"dagLayout", editor); + } + + @Override + public void actionPerformed(ActionEvent e) { + super.actionPerformed(e); + editor.setDAGLayout(); + } + +} diff --git a/AlgebraicDataflowArchitectureModel/src/application/actions/DeleteAction.java b/AlgebraicDataflowArchitectureModel/src/application/actions/DeleteAction.java new file mode 100644 index 0000000..7c949f0 --- /dev/null +++ b/AlgebraicDataflowArchitectureModel/src/application/actions/DeleteAction.java @@ -0,0 +1,25 @@ +package application.actions; + +import java.awt.event.ActionEvent; + +import application.ApplicationLanguage; +import application.editor.Editor; + +public class DeleteAction extends AbstractEditorAction { + + /** + * + */ + private static final long serialVersionUID = -4410145389391154784L; + + public DeleteAction(Editor editor) { + super(/*propName*/ "delete", editor); + } + + @Override + public void actionPerformed(ActionEvent e) { + super.actionPerformed(e); + editor.delete(); + } + +} diff --git a/AlgebraicDataflowArchitectureModel/src/application/actions/ExitAction.java b/AlgebraicDataflowArchitectureModel/src/application/actions/ExitAction.java new file mode 100644 index 0000000..dcf6245 --- /dev/null +++ b/AlgebraicDataflowArchitectureModel/src/application/actions/ExitAction.java @@ -0,0 +1,28 @@ +package application.actions; + +import java.awt.event.ActionEvent; +import java.util.logging.Level; + +import javax.swing.AbstractAction; +import javax.swing.Action; + +import application.ApplicationLanguage; +import application.ApplicationWindow; + +public class ExitAction extends AbstractAction { + /** + * + */ + private static final long serialVersionUID = -8733766417378036850L; + + public ExitAction() { + super(ApplicationLanguage.getInstance().getOptionByPropName("exit")); + } + + @Override + public void actionPerformed(ActionEvent e) { + ApplicationWindow.logger.log(Level.INFO, "exit"); + System.exit(0); + } + +} diff --git a/AlgebraicDataflowArchitectureModel/src/application/actions/InsertStatelessObjectAction.java b/AlgebraicDataflowArchitectureModel/src/application/actions/InsertStatelessObjectAction.java new file mode 100644 index 0000000..4f616c0 --- /dev/null +++ b/AlgebraicDataflowArchitectureModel/src/application/actions/InsertStatelessObjectAction.java @@ -0,0 +1,93 @@ +package application.actions; + +import java.awt.event.ActionEvent; + +import javax.swing.JOptionPane; + +import com.mxgraph.model.mxCell; +import com.mxgraph.swing.mxGraphComponent; + +import application.editor.stages.ControlFlowDelegationStage; +import application.editor.stages.ControlFlowDelegationStageStatus; +import models.controlFlowModel.ObjectNodeAttribute; + +/************************************************************* + * + */ +public class InsertStatelessObjectAction extends AbstractPopupAction{ + + private ControlFlowDelegationStage stage = null; + + /************************************************************* + * [ *constructor ] + /************************************************************* + */ + public InsertStatelessObjectAction(final ControlFlowDelegationStage stage, final mxGraphComponent graphComponent ,final mxCell cell) { + super(/*propName*/"insertMediator", cell, graphComponent); + this.stage = stage; + } + + /************************************************************* + * [ *public ] + /************************************************************* + * + */ + @Override + public void actionPerformed(ActionEvent e) { + super.actionPerformed(e); + insertObjectNode(targetCell); + this.stage.setState( ControlFlowDelegationStageStatus.SELECTING_AN_EDGE); + } + + /************************************************************ + * + */ + private void insertObjectNode(final Object cellObj) { + if(cellObj == null) return; + + mxCell edgeCell = null; + if(cellObj instanceof mxCell) edgeCell = (mxCell)cellObj; + else return; + + // Inputing name to the dialog. + String objName = JOptionPane.showInputDialog("Object Name:"); + if(objName == null) return; + + if( objName.isEmpty()) { + JOptionPane.showMessageDialog(graphComponent, "You must input a name. \nIt mustn't be empty."); + return; + } + + if( isDuplicatedName(objName) ) { + JOptionPane.showMessageDialog(graphComponent, "The named object has already existed."); + return; + } + + stage.insertObjectNodeCellInControlFlowLayer(graphComponent.getGraph(), edgeCell, objName); + } + + /************************************************************* + * + */ + private boolean isDuplicatedName(final String name) { + mxCell root = (mxCell)graphComponent.getGraph().getDefaultParent(); + + for(int i = 0; i < root.getChildCount(); i++) { + mxCell layerCell = (mxCell)root.getChildAt(i); + for(int j = 0; j < layerCell.getChildCount(); j++) { + mxCell cell = (mxCell)layerCell.getChildAt(j); + + ObjectNodeAttribute attr = null; + if(cell.getValue() instanceof ObjectNodeAttribute) + attr = (ObjectNodeAttribute)cell.getValue(); + else continue; + + if( !(attr.getObjectNode().getName().equals(name))) continue; + return true; + } + } + return false; + } + + +} diff --git a/AlgebraicDataflowArchitectureModel/src/application/actions/JavaPrototypeGenerateAction.java b/AlgebraicDataflowArchitectureModel/src/application/actions/JavaPrototypeGenerateAction.java new file mode 100644 index 0000000..5cf13f9 --- /dev/null +++ b/AlgebraicDataflowArchitectureModel/src/application/actions/JavaPrototypeGenerateAction.java @@ -0,0 +1,104 @@ +package application.actions; + +import java.awt.event.ActionEvent; +import java.io.BufferedReader; +import java.io.BufferedWriter; +import java.io.File; +import java.io.FileReader; +import java.io.FileWriter; +import java.io.IOException; + +import javax.swing.JFileChooser; + +import algorithms.*; +import application.editor.Editor; +import code.ast.*; +import generators.CodeGenerator; +import generators.CodeGeneratorFromControlFlowGraph; +import generators.CodeGeneratorFromDataFlowGraph; +import generators.DataTransferMethodAnalyzer; +import generators.JavaCodeGenerator; +import generators.JavaMethodBodyGenerator; +import generators.JavaSpecific; +import models.controlFlowModel.ControlFlowGraph; +import models.dataConstraintModel.ResourcePath; +import models.dataFlowModel.DataTransferModel; +import models.dataFlowModel.ModelExtension; +import models.dataFlowModel.DataFlowGraph; + +public class JavaPrototypeGenerateAction extends AbstractEditorAction { + /** + * + */ + private static final long serialVersionUID = -3694103632055735068L; + + private String lastDir = null; + + public JavaPrototypeGenerateAction(Editor editor) { + super(/*propName*/"generateJava", editor); + } + + @Override + public void actionPerformed(ActionEvent e) { + super.actionPerformed(e); + DataFlowGraph dataFlowgraph = editor.getDataFlowGraph(); + if (dataFlowgraph == null) { + editor.changeStage(Editor.STAGE_PUSH_PULL_SELECTION); + dataFlowgraph = editor.getDataFlowGraph(); + } + if (dataFlowgraph != null) { + DataTransferModel model = editor.getModel(); + ModelExtension.extendModel(model); + TypeInference.infer(model); + DataTransferMethodAnalyzer.decideToStoreResourceStates(dataFlowgraph); + String fileName = editor.getCurFileName(); + if (fileName == null) fileName = "Main"; + String mainTypeName = fileName.split("\\.")[0]; + boolean exist = false; + for (ResourcePath id: model.getResourcePaths()) { + String resourceName = id.getResourceName().substring(0, 1).toUpperCase() + id.getResourceName().substring(1); + if (mainTypeName.equals(resourceName)) { + exist = true; + } + } + if (!exist) { + CodeGenerator.setMainTypeName(mainTypeName); // use model's file name as the main type's name. + } else { + CodeGenerator.resetMainTypeName(); // use the default main type's name. + } + ControlFlowGraph controlFlowGraph = editor.getControlFlowGraph(); + if (controlFlowGraph != null) { + editor.setCodes(new CodeGeneratorFromControlFlowGraph().generateCode(model, controlFlowGraph, new JavaSpecific())); + } else { + editor.setCodes(new CodeGeneratorFromDataFlowGraph().generateCode(model, dataFlowgraph, new JavaSpecific())); + } + ModelExtension.recoverModel(model); + for (CompilationUnit file : editor.getCodes()) { + System.out.println(file); + } + + String wd = (lastDir != null) ? lastDir : System.getProperty("user.dir"); + JFileChooser fc = new JFileChooser(wd); + fc.setFileSelectionMode(JFileChooser.FILES_AND_DIRECTORIES); + int rc = fc.showSaveDialog(null); + if (rc == JFileChooser.APPROVE_OPTION) { + lastDir = fc.getSelectedFile().getPath(); + for (CompilationUnit cu : editor.getCodes()) { + save(fc.getSelectedFile(), cu); + } + } + } + } + + private void save(File dir, CompilationUnit cu) { + File javaFile = new File(dir.getPath(), cu.getFileName()); + try { + BufferedWriter writer = new BufferedWriter(new FileWriter(javaFile)); + writer.write(cu.toString()); + writer.close(); + } catch (IOException e) { + e.printStackTrace(); + } + } + +} diff --git a/AlgebraicDataflowArchitectureModel/src/application/actions/JerseyPrototypeGenerateAction.java b/AlgebraicDataflowArchitectureModel/src/application/actions/JerseyPrototypeGenerateAction.java new file mode 100644 index 0000000..6ad55d2 --- /dev/null +++ b/AlgebraicDataflowArchitectureModel/src/application/actions/JerseyPrototypeGenerateAction.java @@ -0,0 +1,95 @@ +package application.actions; + +import java.awt.event.ActionEvent; +import java.io.BufferedReader; +import java.io.BufferedWriter; +import java.io.File; +import java.io.FileReader; +import java.io.FileWriter; +import java.io.IOException; + +import javax.swing.JFileChooser; + +import algorithms.*; +import application.editor.Editor; +import code.ast.*; +import generators.DataTransferMethodAnalyzer; +import generators.JerseyCodeGenerator; +import generators.JerseyMethodBodyGenerator; +import models.algebra.Type; +import models.dataConstraintModel.ResourcePath; +import models.dataFlowModel.DataTransferModel; +import models.dataFlowModel.ModelExtension; +import models.dataFlowModel.DataFlowGraph; + +public class JerseyPrototypeGenerateAction extends AbstractEditorAction { + /** + * + */ + private static final long serialVersionUID = 1117065654665887436L; + + private String lastDir = null; + + public JerseyPrototypeGenerateAction(Editor editor) { + super(/*propName*/"generateJAX_RS", editor); + } + + @Override + public void actionPerformed(ActionEvent e) { + super.actionPerformed(e); + DataFlowGraph graph = editor.getDataFlowGraph(); + if (graph == null) { + editor.changeStage(Editor.STAGE_PUSH_PULL_SELECTION); + graph = editor.getDataFlowGraph(); + } + if (graph != null) { + DataTransferModel model = editor.getModel(); + ModelExtension.extendModel(model); + TypeInference.infer(model); + DataTransferMethodAnalyzer.decideToStoreResourceStates(graph); + String fileName = editor.getCurFileName(); + if (fileName == null) fileName = "Main"; + String mainTypeName = fileName.split("\\.")[0]; + boolean exist = false; + for (ResourcePath id: model.getResourcePaths()) { + String resourceName = id.getResourceName().substring(0, 1).toUpperCase() + id.getResourceName().substring(1); + if (mainTypeName.equals(resourceName)) { + exist = true; + } + } + if (!exist) { + JerseyCodeGenerator.setMainTypeName(mainTypeName); // use model's file name as the main type's name. + } else { + JerseyCodeGenerator.resetMainTypeName(); // use the default main type's name. + } + editor.setCodes(JerseyMethodBodyGenerator.doGenerate(graph, model, JerseyCodeGenerator.doGenerate(graph, model))); + ModelExtension.recoverModel(model); + for (CompilationUnit file : editor.getCodes()) { + System.out.println(file); + } + + String wd = (lastDir != null) ? lastDir : System.getProperty("user.dir"); + JFileChooser fc = new JFileChooser(wd); + fc.setFileSelectionMode(JFileChooser.FILES_AND_DIRECTORIES); + int rc = fc.showSaveDialog(null); + if (rc == JFileChooser.APPROVE_OPTION) { + lastDir = fc.getSelectedFile().getPath(); + for (CompilationUnit cu : editor.getCodes()) { + save(fc.getSelectedFile(), cu); + } + } + } + } + + private void save(File dir, CompilationUnit cu) { + File javaFile = new File(dir.getPath(), cu.getFileName()); + try { + BufferedWriter writer = new BufferedWriter(new FileWriter(javaFile)); + writer.write(cu.toString()); + writer.close(); + } catch (IOException e) { + e.printStackTrace(); + } + } + +} diff --git a/AlgebraicDataflowArchitectureModel/src/application/actions/NewChannelAction.java b/AlgebraicDataflowArchitectureModel/src/application/actions/NewChannelAction.java new file mode 100644 index 0000000..2810dbc --- /dev/null +++ b/AlgebraicDataflowArchitectureModel/src/application/actions/NewChannelAction.java @@ -0,0 +1,29 @@ +package application.actions; + +import java.awt.event.ActionEvent; + +import javax.swing.JOptionPane; + +import application.editor.Editor; +import models.dataFlowModel.DataTransferChannel; + +public class NewChannelAction extends AbstractEditorAction { + + /** + * + */ + private static final long serialVersionUID = 5979007029473101802L; + + public NewChannelAction(Editor editor) { + super(/*propName*/"newChannel", editor); + } + + @Override + public void actionPerformed(ActionEvent e) { + super.actionPerformed(e); + String channelName = JOptionPane.showInputDialog("Channel Name:"); + if (channelName == null) return; + editor.addChannel(new DataTransferChannel(channelName)); + } + +} diff --git a/AlgebraicDataflowArchitectureModel/src/application/actions/NewFormulaChannelAction.java b/AlgebraicDataflowArchitectureModel/src/application/actions/NewFormulaChannelAction.java new file mode 100644 index 0000000..e524a8e --- /dev/null +++ b/AlgebraicDataflowArchitectureModel/src/application/actions/NewFormulaChannelAction.java @@ -0,0 +1,63 @@ +package application.actions; + +import java.awt.BorderLayout; +import java.awt.Container; +import java.awt.FlowLayout; +import java.awt.Frame; +import java.awt.GridLayout; +import java.awt.event.ActionEvent; +import java.awt.event.ActionListener; + +import javax.swing.BoxLayout; +import javax.swing.JButton; +import javax.swing.JDialog; +import javax.swing.JFrame; +import javax.swing.JLabel; +import javax.swing.JOptionPane; +import javax.swing.JPanel; +import javax.swing.JTextField; + +import application.ApplicationWindow; +import application.editor.Editor; +import models.visualModel.FormulaChannel; + +public class NewFormulaChannelAction extends AbstractEditorAction implements ActionListener { + + /** + * + */ + private static final long serialVersionUID = 5345875219049178252L; + + public NewFormulaChannelAction(Editor editor) { + super(/*propName*/"newFormulaChannel", editor); + } + + @Override + public void actionPerformed(ActionEvent e) { + super.actionPerformed(e); + JPanel panel = new JPanel(); + GridLayout layout = new GridLayout(2,2); + panel.setLayout(layout); + layout.setVgap(5); + layout.setHgap(20); + panel.add(new JLabel("Channel Name:")); + JTextField channelText = new JTextField(); + panel.add(channelText); + panel.add(new JLabel("Symbol:")); + JTextField symbolText = new JTextField(); + panel.add(symbolText); + + int r = JOptionPane.showConfirmDialog( + null, + panel, + "New Formula Channel", + JOptionPane.OK_CANCEL_OPTION, + JOptionPane.QUESTION_MESSAGE); + + String channelName = channelText.getText(); + String symbol = symbolText.getText(); + if(r == JOptionPane.OK_OPTION) { + editor.addFormulaChannel(new FormulaChannel(channelName, editor.getModel().getSymbol(symbol))); + } + } +} diff --git a/AlgebraicDataflowArchitectureModel/src/application/actions/NewIOChannelAction.java b/AlgebraicDataflowArchitectureModel/src/application/actions/NewIOChannelAction.java new file mode 100644 index 0000000..3d37ba4 --- /dev/null +++ b/AlgebraicDataflowArchitectureModel/src/application/actions/NewIOChannelAction.java @@ -0,0 +1,29 @@ +package application.actions; + +import java.awt.event.ActionEvent; + +import javax.swing.JOptionPane; + +import application.editor.Editor; +import models.dataFlowModel.DataTransferChannel; + +public class NewIOChannelAction extends AbstractEditorAction { + + /** + * + */ + private static final long serialVersionUID = -1657072017390171313L; + + public NewIOChannelAction(Editor editor) { + super(/*propName*/"newEventChannel", editor); + } + + @Override + public void actionPerformed(ActionEvent e) { + super.actionPerformed(e); + String channelName = JOptionPane.showInputDialog("I/O Channel Name:"); + if (channelName == null) return; + editor.addIOChannel(new DataTransferChannel(channelName)); + } + +} diff --git a/AlgebraicDataflowArchitectureModel/src/application/actions/NewModelAction.java b/AlgebraicDataflowArchitectureModel/src/application/actions/NewModelAction.java new file mode 100644 index 0000000..77104a8 --- /dev/null +++ b/AlgebraicDataflowArchitectureModel/src/application/actions/NewModelAction.java @@ -0,0 +1,25 @@ +package application.actions; + +import java.awt.event.ActionEvent; + +import application.ApplicationWindow; +import application.editor.Editor; + +public class NewModelAction extends AbstractSystemAction { + /** + * + */ + private static final long serialVersionUID = 8484493203589724589L; + + public NewModelAction(ApplicationWindow frame) { + super(/*propName*/"newModel", frame); + } + + @Override + public void actionPerformed(ActionEvent e) { + super.actionPerformed(e); + frame.getEditor().clear(); + frame.setTitle(frame.title); + } + +} diff --git a/AlgebraicDataflowArchitectureModel/src/application/actions/NewResourceAction.java b/AlgebraicDataflowArchitectureModel/src/application/actions/NewResourceAction.java new file mode 100644 index 0000000..623e0b7 --- /dev/null +++ b/AlgebraicDataflowArchitectureModel/src/application/actions/NewResourceAction.java @@ -0,0 +1,29 @@ +package application.actions; + +import java.awt.event.ActionEvent; + +import javax.swing.JOptionPane; + +import application.editor.Editor; +import models.dataConstraintModel.ResourcePath; + +public class NewResourceAction extends AbstractEditorAction { + + /** + * + */ + private static final long serialVersionUID = -4439207504700741286L; + + public NewResourceAction(Editor editor) { + super(/*propName*/"newResources", editor); + } + + @Override + public void actionPerformed(ActionEvent e) { + super.actionPerformed(e); + String resName = JOptionPane.showInputDialog("Resourece Name:"); + if (resName == null) return; + editor.addResourcePath(new ResourcePath(resName, 0)); + } + +} diff --git a/AlgebraicDataflowArchitectureModel/src/application/actions/OpenAction.java b/AlgebraicDataflowArchitectureModel/src/application/actions/OpenAction.java new file mode 100644 index 0000000..0502933 --- /dev/null +++ b/AlgebraicDataflowArchitectureModel/src/application/actions/OpenAction.java @@ -0,0 +1,63 @@ +package application.actions; + +import java.awt.event.ActionEvent; +import java.io.File; + +import javax.swing.JFileChooser; +import javax.swing.filechooser.FileFilter; +import javax.swing.filechooser.FileNameExtensionFilter; + +import application.ApplicationWindow; +import application.editor.Editor; + +public class OpenAction extends AbstractSystemAction { + /** + * + */ + private static final long serialVersionUID = -8290761032629599683L; + + private String lastDir = null; + + public OpenAction(ApplicationWindow frame) { + super(/*propName*/"open", frame); + } + + @Override + public void actionPerformed(ActionEvent e) { + super.actionPerformed(e); + Editor editor = frame.getEditor(); + if (editor != null) { + String wd = (lastDir != null) ? lastDir : System.getProperty("user.dir"); + + JFileChooser fc = new JFileChooser(wd); + + FileFilter model = new FileNameExtensionFilter("model","model"); + FileFilter dtram = new FileNameExtensionFilter("dtram", "dtram"); + + // Adds file filter for supported file format + FileFilter defaultFilter = new FileFilter() { + + public boolean accept(File file) { + String lcase = file.getName().toLowerCase(); + return lcase.endsWith(".model"); + } + + @Override + public String getDescription() { + return null; + } + }; + + fc.addChoosableFileFilter(defaultFilter); + fc.addChoosableFileFilter(model); + fc.addChoosableFileFilter(dtram); + int rc = fc.showDialog(null, "Open Model File"); + if (rc == JFileChooser.APPROVE_OPTION) { + lastDir = fc.getSelectedFile().getParent(); + editor.open(fc.getSelectedFile()); + frame.setTitle(frame.title + " - " + fc.getSelectedFile().getAbsolutePath()); + } + } + } + +} diff --git a/AlgebraicDataflowArchitectureModel/src/application/actions/SaveAction.java b/AlgebraicDataflowArchitectureModel/src/application/actions/SaveAction.java new file mode 100644 index 0000000..c19d3bb --- /dev/null +++ b/AlgebraicDataflowArchitectureModel/src/application/actions/SaveAction.java @@ -0,0 +1,27 @@ +package application.actions; + +import java.awt.event.ActionEvent; + +import application.ApplicationWindow; +import application.editor.Editor; + +public class SaveAction extends AbstractSystemAction { + /** + * + */ + private static final long serialVersionUID = 5660460585305281982L; + + public SaveAction(ApplicationWindow frame) { + super(/*propName*/"save", frame); + } + + @Override + public void actionPerformed(ActionEvent e) { + super.actionPerformed(e); + Editor editor = frame.getEditor(); + if (editor != null && editor.getCurFileName() != null) { + editor.save(); + } + } + +} diff --git a/AlgebraicDataflowArchitectureModel/src/application/actions/SaveAsAction.java b/AlgebraicDataflowArchitectureModel/src/application/actions/SaveAsAction.java new file mode 100644 index 0000000..b527004 --- /dev/null +++ b/AlgebraicDataflowArchitectureModel/src/application/actions/SaveAsAction.java @@ -0,0 +1,78 @@ +package application.actions; + +import java.awt.event.ActionEvent; +import java.io.File; + +import javax.swing.AbstractAction; +import javax.swing.JFileChooser; +import javax.swing.filechooser.FileFilter; +import javax.swing.filechooser.FileNameExtensionFilter; + +import application.ApplicationWindow; +import application.editor.Editor; + +public class SaveAsAction extends AbstractSystemAction { + /** + * + */ + private static final long serialVersionUID = -2599502783032684084L; + + private String lastDir = null; + + public SaveAsAction(ApplicationWindow frame) { + super(/*propName*/"saveAs", frame); + } + + @Override + public void actionPerformed(ActionEvent e) { + super.actionPerformed(e); + Editor editor = frame.getEditor(); + if (editor != null) { + String wd = (lastDir != null) ? lastDir : System.getProperty("user.dir"); + + JFileChooser fc = new JFileChooser(wd); + FileFilter model = new FileNameExtensionFilter("model","model"); + FileFilter dtram = new FileNameExtensionFilter("dtram", "dtram"); + + // Adds file filter for supported file format + FileFilter defaultFilter = new FileFilter() { + public boolean accept(File file) { + String lcase = file.getName().toLowerCase(); + return lcase.endsWith(".model"); + } + + @Override + public String getDescription() { + return null; + } + }; + + fc.addChoosableFileFilter(defaultFilter); + fc.addChoosableFileFilter(model); + fc.addChoosableFileFilter(dtram); + int rc = fc.showDialog(null, "Save Model File"); + + // choose a file extension from a dialog. + if (rc == JFileChooser.APPROVE_OPTION) { + + // if extension filter is filled, then attaching extension by choosing filter. + // but if it's not filled, then using default extension name. + String extension = ""; + if(fc.getFileFilter() instanceof FileNameExtensionFilter) { + FileNameExtensionFilter selectedFilter = (FileNameExtensionFilter)fc.getFileFilter(); + extension = "." + selectedFilter.getExtensions()[0].toString(); + } + + lastDir = fc.getSelectedFile().getParent(); + + String fileName = fc.getSelectedFile().getAbsolutePath() + extension; + editor.setCurFilePath(fileName); + + // overwriting file + editor.save(); + frame.setTitle(ApplicationWindow.title + " - " + fc.getSelectedFile().getAbsolutePath()); + } + } + } + +} diff --git a/AlgebraicDataflowArchitectureModel/src/application/actions/ShowDependentableMediatorAction.java b/AlgebraicDataflowArchitectureModel/src/application/actions/ShowDependentableMediatorAction.java new file mode 100644 index 0000000..82ed4b5 --- /dev/null +++ b/AlgebraicDataflowArchitectureModel/src/application/actions/ShowDependentableMediatorAction.java @@ -0,0 +1,49 @@ +package application.actions; + +import java.awt.event.ActionEvent; + +import com.mxgraph.model.mxCell; +import com.mxgraph.swing.mxGraphComponent; + +import application.editor.stages.ControlFlowDelegationStage; +import application.editor.stages.ControlFlowDelegationStageStatus; +import models.controlFlowModel.CallEdgeAttribute; + +public class ShowDependentableMediatorAction extends AbstractPopupAction { + private ControlFlowDelegationStage stage = null; + + /************************************************************* + * [ *constructor ] + /************************************************************* + */ + public ShowDependentableMediatorAction(final ControlFlowDelegationStage stage, final mxGraphComponent graphComponent, final mxCell targetCell) { + super(/*propName*/"dependsOnMediator", targetCell, graphComponent); + this.stage = stage; + } + + /************************************************************ + * [ *public ] + /************************************************************* + * + */ + @Override + public void actionPerformed(ActionEvent e) { + super.actionPerformed(e); + showDependentableNodesBySelectedEdge(targetCell); + stage.setState(ControlFlowDelegationStageStatus.SHOWING_DEPENDENTABLE_NODES); + // -> dependent manipulation is ControlFlowStageEditor + } + + /************************************************************* + * [ *private ] + /************************************************************* + * + */ + private void showDependentableNodesBySelectedEdge(Object cellObj) { + CallEdgeAttribute callEdgeAttr = (CallEdgeAttribute)graphComponent.getGraph().getModel().getValue(cellObj); + if(callEdgeAttr == null) return; + + ControlFlowDelegationStage cfdStage = (ControlFlowDelegationStage)stage; + cfdStage.showDependentableNodes(this.graphComponent.getGraph(), callEdgeAttr);; + } +} diff --git a/AlgebraicDataflowArchitectureModel/src/application/actions/ShowFlowLayerWindowAction.java b/AlgebraicDataflowArchitectureModel/src/application/actions/ShowFlowLayerWindowAction.java new file mode 100644 index 0000000..1a9e790 --- /dev/null +++ b/AlgebraicDataflowArchitectureModel/src/application/actions/ShowFlowLayerWindowAction.java @@ -0,0 +1,17 @@ +package application.actions; + +import java.awt.event.ActionEvent; + +import application.ApplicationWindow; + +public class ShowFlowLayerWindowAction extends AbstractSystemAction { + public ShowFlowLayerWindowAction(ApplicationWindow frame) { + super(/*propName*/"showFlowLayer", frame); + } + + @Override + public void actionPerformed(ActionEvent e) { + super.actionPerformed(e); + frame.showSwitchLayerWindow(); + } +} diff --git a/AlgebraicDataflowArchitectureModel/src/application/actions/ShowNavigationAction.java b/AlgebraicDataflowArchitectureModel/src/application/actions/ShowNavigationAction.java new file mode 100644 index 0000000..8d7aacb --- /dev/null +++ b/AlgebraicDataflowArchitectureModel/src/application/actions/ShowNavigationAction.java @@ -0,0 +1,19 @@ +package application.actions; + +import java.awt.event.ActionEvent; + +import application.ApplicationWindow; + +public class ShowNavigationAction extends AbstractSystemAction { + + public ShowNavigationAction(ApplicationWindow frame) { + super(/*propName*/"showNavigation", frame); + } + + @Override + public void actionPerformed(ActionEvent e) { + super.actionPerformed(e); + frame.showNavigationWindow(); + } + +} diff --git a/AlgebraicDataflowArchitectureModel/src/application/actions/TreeLayoutAction.java b/AlgebraicDataflowArchitectureModel/src/application/actions/TreeLayoutAction.java new file mode 100644 index 0000000..a8056eb --- /dev/null +++ b/AlgebraicDataflowArchitectureModel/src/application/actions/TreeLayoutAction.java @@ -0,0 +1,19 @@ +package application.actions; + +import java.awt.event.ActionEvent; + +import application.editor.Editor; + +public class TreeLayoutAction extends AbstractEditorAction { + + public TreeLayoutAction(Editor editor) { + super(/*propName*/"treeLayout", editor); + } + + @Override + public void actionPerformed(ActionEvent e) { + super.actionPerformed(e); + editor.setTreeLayout(); + } + +} diff --git a/AlgebraicDataflowArchitectureModel/src/application/actions/ZoomInAction.java b/AlgebraicDataflowArchitectureModel/src/application/actions/ZoomInAction.java new file mode 100644 index 0000000..e18fb4f --- /dev/null +++ b/AlgebraicDataflowArchitectureModel/src/application/actions/ZoomInAction.java @@ -0,0 +1,29 @@ +package application.actions; + +import java.awt.event.ActionEvent; + +import javax.swing.AbstractAction; +import javax.swing.JOptionPane; + +import com.mxgraph.swing.mxGraphComponent; +import com.mxgraph.util.mxResources; + +import application.editor.Editor; + +public class ZoomInAction extends AbstractViewerAction { + /** + * + */ + private static final long serialVersionUID = 6758532166946195926L; + + public ZoomInAction(mxGraphComponent graphComponent) { + super(/*propName*/"zoomIn", graphComponent); + } + + @Override + public void actionPerformed(ActionEvent e) { + super.actionPerformed(e); + graphComponent.zoomIn(); + } + +} diff --git a/AlgebraicDataflowArchitectureModel/src/application/actions/ZoomOutAction.java b/AlgebraicDataflowArchitectureModel/src/application/actions/ZoomOutAction.java new file mode 100644 index 0000000..0e306da --- /dev/null +++ b/AlgebraicDataflowArchitectureModel/src/application/actions/ZoomOutAction.java @@ -0,0 +1,27 @@ +package application.actions; + +import java.awt.event.ActionEvent; + +import javax.swing.AbstractAction; + +import com.mxgraph.swing.mxGraphComponent; + +import application.editor.Editor; + +public class ZoomOutAction extends AbstractViewerAction { + /** + * + */ + private static final long serialVersionUID = 8657530769383486605L; + + public ZoomOutAction(mxGraphComponent graphComponent) { + super(/*propName*/"zoomOut", graphComponent); + } + + @Override + public void actionPerformed(ActionEvent e) { + super.actionPerformed(e); + graphComponent.zoomOut(); + } + +} diff --git a/AlgebraicDataflowArchitectureModel/src/application/editor/Editor.java b/AlgebraicDataflowArchitectureModel/src/application/editor/Editor.java new file mode 100644 index 0000000..82cb881 --- /dev/null +++ b/AlgebraicDataflowArchitectureModel/src/application/editor/Editor.java @@ -0,0 +1,529 @@ +package application.editor; + +import java.awt.event.MouseListener; +import java.io.BufferedReader; +import java.io.File; +import java.io.FileNotFoundException; +import java.io.FileReader; +import java.io.FileWriter; +import java.io.IOException; +import java.util.ArrayList; +import java.util.List; + +import com.mxgraph.layout.mxCircleLayout; +import com.mxgraph.layout.mxCompactTreeLayout; +import com.mxgraph.model.mxCell; +import com.mxgraph.swing.mxGraphComponent; +import com.mxgraph.util.mxEvent; +import com.mxgraph.util.mxEventSource.mxIEventListener; +import com.mxgraph.view.mxCellState; +import com.mxgraph.view.mxGraph; +import com.mxgraph.view.mxGraphView; + +import application.editor.stages.ControlFlowDelegationStage; +import application.editor.stages.DataFlowModelingStage; +import application.editor.stages.PushPullSelectionStage; +import application.layouts.*; +import code.ast.CompilationUnit; +import models.EdgeAttribute; +import models.controlFlowModel.ControlFlowGraph; +import models.dataConstraintModel.Channel; +import models.dataConstraintModel.ResourcePath; +import models.dataFlowModel.DataTransferModel; +import models.dataFlowModel.DataTransferChannel; +import models.dataFlowModel.DataFlowGraph; +import models.visualModel.FormulaChannel; +import parser.Parser; +import parser.exceptions.ExpectedAssignment; +import parser.exceptions.ExpectedChannel; +import parser.exceptions.ExpectedChannelName; +import parser.exceptions.ExpectedColon; +import parser.exceptions.ExpectedEquals; +import parser.exceptions.ExpectedFormulaChannel; +import parser.exceptions.ExpectedGeometry; +import parser.exceptions.ExpectedInOrOutOrRefKeyword; +import parser.exceptions.ExpectedIoChannel; +import parser.exceptions.ExpectedLeftCurlyBracket; +import parser.exceptions.ExpectedModel; +import parser.exceptions.ExpectedNode; +import parser.exceptions.ExpectedRHSExpression; +import parser.exceptions.ExpectedResource; +import parser.exceptions.ExpectedRightBracket; +import parser.exceptions.ExpectedStateTransition; +import parser.exceptions.WrongJsonExpression; +import parser.exceptions.WrongLHSExpression; +import parser.exceptions.WrongRHSExpression; +import parser.ParserDTRAM; + +/** + * Main editor for all stages + * + * @author Nitta + * + */ +public class Editor { + public DataTransferModel model = null; + public mxGraph graph = null; + private mxGraphComponent graphComponent = null; + private mxIEventListener curChangeEventListener = null; + private MouseListener curMouseEventListener = null; + + protected Stage curStage = null; + protected List stageQueue = null; + private List stageChangeListeners = null; + + protected String curFileName = null; + protected String curFilePath = null; + protected ArrayList codes = null; + + public static DataFlowModelingStage STAGE_DATA_FLOW_MODELING = null; + public static PushPullSelectionStage STAGE_PUSH_PULL_SELECTION = null; + public static ControlFlowDelegationStage STAGE_CONTROL_FLOW_DELEGATION = null; + + public Editor(mxGraphComponent graphComponent) { + this.graphComponent = graphComponent; + this.graph = graphComponent.getGraph(); + + STAGE_DATA_FLOW_MODELING = new DataFlowModelingStage(graphComponent); + STAGE_PUSH_PULL_SELECTION = new PushPullSelectionStage(graphComponent); + STAGE_CONTROL_FLOW_DELEGATION = new ControlFlowDelegationStage(graphComponent); + + graphComponent.setCellEditor(STAGE_DATA_FLOW_MODELING.createCellEditor(graphComponent)); + + stageQueue = new ArrayList<>(); + stageQueue.add(STAGE_DATA_FLOW_MODELING); + stageQueue.add(STAGE_PUSH_PULL_SELECTION); + stageQueue.add(STAGE_CONTROL_FLOW_DELEGATION); + curStage = STAGE_DATA_FLOW_MODELING; + + stageChangeListeners = new ArrayList<>(); + } + + public mxGraph getGraph() { + return graph; + } + + public mxGraphComponent getGraphComponent() { + return this.graphComponent; + } + + public DataTransferModel getModel() { + model = curStage.getModel(); + return model; + } + + public Stage getCurStage() { + return curStage; + } + + public boolean canChange(Stage nextStage) { + return nextStage.canChangeFrom(curStage); + } + + public boolean nextStage() { + int curStageNo = stageQueue.indexOf(curStage); + if (curStageNo + 1 >= stageQueue.size()) return false; + return changeStage(stageQueue.get(curStageNo + 1)); + } + + public boolean changeStage(Stage nextStage) { + if (!nextStage.canChangeFrom(curStage)) return false; + nextStage.init(curStage); + graphComponent.setCellEditor(nextStage.createCellEditor(graphComponent)); + + // add listeners + // "curChangeEventListener" will be called when updating the mxGraph. + if (curChangeEventListener != null) { + graph.getModel().removeListener(curChangeEventListener); + } + curChangeEventListener = nextStage.createChangeEventListener(this); + if (curChangeEventListener != null) { + graph.getModel().addListener(mxEvent.CHANGE, curChangeEventListener); + } + + // A handler of a mouse event. + if(curMouseEventListener != null) { + graphComponent.getGraphControl().removeMouseListener(curMouseEventListener); + } + curMouseEventListener = nextStage.createMouseEventListener(this); + if(curMouseEventListener != null) { + graphComponent.getGraphControl().addMouseListener(curMouseEventListener); + } + curStage = nextStage; + notifyStageChangeListeners(); + return true; + } + + public void addStageChangeListener(IStageChangeListener stageChangeListener) { + stageChangeListeners.add(stageChangeListener); + } + + private void notifyStageChangeListeners() { + for (IStageChangeListener l: stageChangeListeners) { + l.stageChanged(curStage); + } + } + + public DataFlowGraph getDataFlowGraph() { + if (curStage instanceof PushPullSelectionStage) { + return ((PushPullSelectionStage) curStage).getDataFlowGraph(); + } else if (curStage instanceof ControlFlowDelegationStage) { + return ((ControlFlowDelegationStage) curStage).getControlFlowGraph().getDataFlowGraph(); + } + return null; + } + + public ControlFlowGraph getControlFlowGraph() { + if (curStage instanceof ControlFlowDelegationStage) { + return ((ControlFlowDelegationStage) curStage).getControlFlowGraph(); + } + return null; + } + + public ArrayList getCodes() { + return codes; + } + + public void setCodes(ArrayList codes) { + this.codes = codes; + } + + public String getCurFileName() { + return curFileName; + } + + public String getCurFilePath() { + return curFilePath; + } + + public void setCurFilePath(String curFilePath) { + this.curFilePath = curFilePath; + this.curFileName = new File(curFilePath).getName(); + } + + public void clear() { + // Force to change to the data-flow modeling stage. + boolean stageChanged = changeStage(STAGE_DATA_FLOW_MODELING); + if (!stageChanged) return; + + model = null; + ((DataFlowModelingStage) curStage).clear(); + + curFilePath = null; + curFileName = null; + codes = null; + } + + /** + * Open a given file, parse the file, construct a DataFlowModel and a mxGraph + * @param file given file + * @return a constructed DataFlowModel + */ + public DataTransferModel open(File file) { + // Force to change to the data-flow modeling stage. + boolean stageChanged = changeStage(STAGE_DATA_FLOW_MODELING); + if (!stageChanged) return null; + + try { + String extension =""; + if(file != null && file.exists()) { + // get file's name + String name = file.getName(); + + // get file's extension + extension = name.substring(name.lastIndexOf(".")); + } + if(extension.contains(".model")) { + openModel(file); + } else { + // Parse the .dtram file. + ParserDTRAM parserDTRAM = new ParserDTRAM(new BufferedReader(new FileReader(file))); + try { + model = parserDTRAM.doParseModel(); + if (curStage instanceof DataFlowModelingStage) { + // Update the mxGraph. + ((DataFlowModelingStage) curStage).setModel(model); + } + // Restore the geometry. + parserDTRAM.doParseGeometry(graph); + + // Change to the push/pull selection stage, analyze the data transfer model and construct a data-flow graph. + changeStage(STAGE_PUSH_PULL_SELECTION); + + curFilePath = file.getAbsolutePath(); + curFileName = file.getName(); + return model; + } catch (ExpectedChannel | ExpectedChannelName | ExpectedLeftCurlyBracket | ExpectedInOrOutOrRefKeyword + | ExpectedStateTransition | ExpectedEquals | ExpectedRHSExpression | WrongLHSExpression + | WrongRHSExpression | ExpectedRightBracket | ExpectedAssignment | ExpectedModel | ExpectedGeometry | ExpectedNode | ExpectedResource | ExpectedFormulaChannel | ExpectedIoChannel | WrongJsonExpression | ExpectedColon e) { + e.printStackTrace(); + } + } + } catch (FileNotFoundException e) { + e.printStackTrace(); + } + + return null; + } + + public DataTransferModel openModel(File file) { + // Force to change to data-flow modeling stage. + boolean stageChanged = changeStage(STAGE_DATA_FLOW_MODELING); + + if (!stageChanged) return null; + + try { + // Parse the .model file. + Parser parser = new Parser(new BufferedReader(new FileReader(file))); + try { + model = parser.doParse(); + if (curStage instanceof DataFlowModelingStage) { + // Update the mxGraph. + ((DataFlowModelingStage) curStage).setModel(model); + } + // Set DAG layout. + setDAGLayout(); + + // Change to the push/pull selection stage, analyze the data transfer model and construct a data-flow graph. + changeStage(STAGE_PUSH_PULL_SELECTION); + + curFilePath = file.getAbsolutePath(); + curFileName = file.getName(); + return model; + } catch (ExpectedChannel | ExpectedChannelName | ExpectedLeftCurlyBracket | ExpectedInOrOutOrRefKeyword + | ExpectedStateTransition | ExpectedEquals | ExpectedRHSExpression | WrongLHSExpression + | WrongRHSExpression | ExpectedRightBracket | ExpectedAssignment | WrongJsonExpression | ExpectedColon e) { + e.printStackTrace(); + } + } catch (FileNotFoundException e) { + e.printStackTrace(); + } + return null; + } + + /************************************************************* + * [save] + /************************************************************* + * + */ + public void save() { + if (curFilePath != null) { + try { + File file = new File(curFilePath); + String extension = ""; + if(file != null && file.exists()) { + // get a file's name + String name = file.getName(); + + // get a file's extension + extension = name.substring(name.lastIndexOf(".")); + } + if(extension.contains(".model")) { + saveModel(file); + } else { + FileWriter filewriter = new FileWriter(file); + filewriter.write(toOutputString()); + filewriter.close(); + } + } catch (IOException e) { + e.printStackTrace(); + } + } + } + + public void saveModel(File file) { + if (curFilePath != null) { + try { + FileWriter filewriter = new FileWriter(file); + filewriter.write(model.getSourceText()); + filewriter.close(); + } catch (IOException e) { + e.printStackTrace(); + } + } + } + + /**-------------------------------------------------------------------------------- + * get writing texts "dtram" file information is written. + * + * @return formatted "dtram" info texts. + */ + protected String toOutputString() { + String fileString = ""; + + fileString += "model {\n"; + fileString += this.model.getSourceText(); + fileString += "}\n"; + + fileString += "geometry {\n"; + + mxCell root = (mxCell) graph.getDefaultParent(); + mxCell nodeLayer = (mxCell) root.getChildAt(Stage.NODE_LAYER); + mxCell dataFlowLayer = (mxCell) root.getChildAt(Stage.DATA_FLOW_LAYER); + for (int i = 0; i < graph.getModel().getChildCount(nodeLayer); i++) { + Object cell = graph.getModel().getChildAt(nodeLayer, i); + if (graph.getModel().isVertex(cell)) { + mxGraphView view = graph.getView(); + mxCellState state = view.getState(cell); + int x = (int) state.getX(); + int y = (int) state.getY(); + int w = (int) state.getWidth(); + int h = (int) state.getHeight(); + + for (ResourcePath res: model.getResourcePaths()){ + if(res instanceof ResourcePath && state.getLabel().equals(res.getResourceName())) + fileString += "\tnode r " + state.getLabel() + ":" + x + "," + y + "," + w + "," + h + "\n"; + } + + for (Channel ioC: model.getIOChannels()) { + if(ioC instanceof Channel && state.getLabel().equals(ioC.getChannelName())) { + fileString += "\tnode ioc " + state.getLabel() + ":" + x + "," + y + "," + w + "," + h + "\n"; + } + } + } + } + for (int i = 0; i < graph.getModel().getChildCount(dataFlowLayer); i++) { + Object cell = graph.getModel().getChildAt(dataFlowLayer, i); + if (graph.getModel().isVertex(cell)) { + mxGraphView view = graph.getView(); + mxCellState state = view.getState(cell); + int x = (int) state.getX(); + int y = (int) state.getY(); + int w = (int) state.getWidth(); + int h = (int) state.getHeight(); + + for(Channel ch: model.getChannels()) { + if(ch instanceof FormulaChannel && state.getLabel().equals(ch.getChannelName())) { + fileString += "\tnode fc " + state.getLabel() + ":" + x + "," + y + "," + w + "," + h+"\n"; + } else if(ch instanceof Channel && state.getLabel().equals(ch.getChannelName())) { + fileString +="\tnode c " + state.getLabel() + ":" + x + "," + y + "," + w + "," + h+"\n"; + } + } + } + } + fileString += "}\n"; + + return fileString; + } + + public void setDAGLayout() { + mxCell root = (mxCell) graph.getDefaultParent(); + mxCell dataFlowLayer = (mxCell) root.getChildAt(Stage.DATA_FLOW_LAYER); + graph.getModel().beginUpdate(); + try { + DAGLayout ctl = new DAGLayout(graph); + ctl.execute(dataFlowLayer); +// for(int i = 0; i < root.getChildCount(); i++) { +// ctl.execute(root.getChildAt(i)); +// } + } finally { + graph.getModel().endUpdate(); + } + } + + public void setTreeLayout() { + mxCell root = (mxCell) graph.getDefaultParent(); + graph.getModel().beginUpdate(); + try { + mxCompactTreeLayout ctl = new mxCompactTreeLayout(graph); + ctl.setLevelDistance(100); + // ctl.setHorizontal(false); + ctl.setEdgeRouting(false); + for(int i = 0; i < root.getChildCount(); i++) { + ctl.execute(root.getChildAt(i)); + } + } finally { + graph.getModel().endUpdate(); + } + } + + public void setCircleLayout() { + mxCell root = (mxCell) graph.getDefaultParent(); + graph.getModel().beginUpdate(); + try { + mxCircleLayout ctl = new mxCircleLayout(graph); + for(int i = 0; i < root.getChildCount(); i++) { + ctl.execute(root.getChildAt(i)); + } + } finally { + graph.getModel().endUpdate(); + } + } + + public void addResourcePath(ResourcePath res) { + // Force to change to the data-flow modeling stage. + boolean stageChanged = changeStage(STAGE_DATA_FLOW_MODELING); + if (!stageChanged) return; + + ((DataFlowModelingStage) curStage).addResourcePath(res); + model = ((DataFlowModelingStage) curStage).getModel(); + } + + public void addChannel(DataTransferChannel channel) { + // Force to change to the data-flow modeling stage. + boolean stageChanged = changeStage(STAGE_DATA_FLOW_MODELING); + if (!stageChanged) return; + + ((DataFlowModelingStage) curStage).addChannel(channel); + model = ((DataFlowModelingStage) curStage).getModel(); + + } + + public void addIOChannel(DataTransferChannel ioChannel) { + // Force to change to the data-flow modeling stage. + boolean stageChanged = changeStage(STAGE_DATA_FLOW_MODELING); + if (!stageChanged) return; + + ((DataFlowModelingStage) curStage).addIOChannel(ioChannel); + model = ((DataFlowModelingStage) curStage).getModel(); + } + + public void addFormulaChannel(FormulaChannel formulaChannel) { + // Force to change to the data-flow modeling stage. + boolean stageChanged = changeStage(STAGE_DATA_FLOW_MODELING); + if (!stageChanged) return; + + ((DataFlowModelingStage) curStage).addFormulaChannel(formulaChannel); + model = ((DataFlowModelingStage) curStage).getModel(); + } + + public boolean connectEdge(mxCell edge, mxCell src, mxCell dst) { + // Force to change to the data-flow modeling stage. + boolean stageChanged = changeStage(STAGE_DATA_FLOW_MODELING); + if (!stageChanged) return false; + + boolean isConnected = ((DataFlowModelingStage) curStage).connectEdge(edge, src, dst); + + return isConnected; + } + + public void delete() { + // Force to change to the data-flow modeling stage. + boolean stageChanged = changeStage(STAGE_DATA_FLOW_MODELING); + if (!stageChanged) return; + + ((DataFlowModelingStage) curStage).delete(); + } + + public static class SrcDstAttribute extends EdgeAttribute { + private Object src; + private Object dst; + + public SrcDstAttribute(Object src, Object dst) { + this.src = src; + this.dst = dst; + } + + public Object getSrouce() { + return src; + } + + public Object getDestination() { + return dst; + } + + public String toString() { + return ""; + } + } +} diff --git a/AlgebraicDataflowArchitectureModel/src/application/editor/FlowCellEditor.java b/AlgebraicDataflowArchitectureModel/src/application/editor/FlowCellEditor.java new file mode 100644 index 0000000..c44b42d --- /dev/null +++ b/AlgebraicDataflowArchitectureModel/src/application/editor/FlowCellEditor.java @@ -0,0 +1,45 @@ +package application.editor; + +import java.util.EventObject; + +import com.mxgraph.swing.mxGraphComponent; +import com.mxgraph.swing.view.mxICellEditor; + +abstract public class FlowCellEditor implements mxICellEditor { + + protected Stage stage = null; + protected mxGraphComponent graphComponent = null; + + protected Object editingCell = null; + + /************************************************************* + * [ *constructor] + /************************************************************* + * + * @param stage + * @param graphComponent + */ + protected FlowCellEditor(Stage stage, mxGraphComponent graphComponent) { + this.stage = stage; + this.graphComponent = graphComponent; + } + + /************************************************************* + * [ *public ] + /************************************************************* + * + */ + public Object getEditingCell() { + return this.editingCell; + } + + /************************************************************* + * + */ + abstract public void startEditing(Object cellObj, EventObject eventObj); + + /************************************************************* + * + */ + abstract public void stopEditing(boolean cancel); +} diff --git a/AlgebraicDataflowArchitectureModel/src/application/editor/IStageChangeListener.java b/AlgebraicDataflowArchitectureModel/src/application/editor/IStageChangeListener.java new file mode 100644 index 0000000..a345fe2 --- /dev/null +++ b/AlgebraicDataflowArchitectureModel/src/application/editor/IStageChangeListener.java @@ -0,0 +1,5 @@ +package application.editor; + +public interface IStageChangeListener { + public void stageChanged(Stage newStage); +} diff --git a/AlgebraicDataflowArchitectureModel/src/application/editor/InEdgeAttribute.java b/AlgebraicDataflowArchitectureModel/src/application/editor/InEdgeAttribute.java new file mode 100644 index 0000000..5956f6c --- /dev/null +++ b/AlgebraicDataflowArchitectureModel/src/application/editor/InEdgeAttribute.java @@ -0,0 +1,19 @@ +package application.editor; + +import models.dataFlowModel.PushPullAttribute; +import models.dataFlowModel.PushPullValue; +import models.dataFlowModel.ResourceNode; + +public class InEdgeAttribute extends PushPullAttribute { + private ResourceNode srcRes; + + public InEdgeAttribute(PushPullAttribute attr, ResourceNode srcRes) { + super(); + super.setOptions(attr.getOptions()); + this.srcRes = srcRes; + } + + public ResourceNode getSrcResource() { + return srcRes; + } +} diff --git a/AlgebraicDataflowArchitectureModel/src/application/editor/OutEdgeAttribute.java b/AlgebraicDataflowArchitectureModel/src/application/editor/OutEdgeAttribute.java new file mode 100644 index 0000000..3d5c286 --- /dev/null +++ b/AlgebraicDataflowArchitectureModel/src/application/editor/OutEdgeAttribute.java @@ -0,0 +1,18 @@ +package application.editor; + +import application.editor.Editor.SrcDstAttribute; +import models.EdgeAttribute; +import models.dataFlowModel.ResourceNode; + +public class OutEdgeAttribute extends SrcDstAttribute { + private ResourceNode dstRes; + + public OutEdgeAttribute(SrcDstAttribute attr, ResourceNode dstRes) { + super(attr.getSrouce(), attr.getDestination()); + this.dstRes = dstRes; + } + + public ResourceNode getDstResource() { + return dstRes; + } +} diff --git a/AlgebraicDataflowArchitectureModel/src/application/editor/Stage.java b/AlgebraicDataflowArchitectureModel/src/application/editor/Stage.java new file mode 100644 index 0000000..ba5baba --- /dev/null +++ b/AlgebraicDataflowArchitectureModel/src/application/editor/Stage.java @@ -0,0 +1,78 @@ +package application.editor; + +import java.awt.event.MouseListener; + +import com.mxgraph.model.mxCell; +import com.mxgraph.swing.mxGraphComponent; +import com.mxgraph.swing.view.mxICellEditor; +import com.mxgraph.util.mxEventSource.mxIEventListener; +import com.mxgraph.view.mxGraph; + +import models.dataFlowModel.DataTransferModel; + +abstract public class Stage { + protected DataTransferModel model = null; + protected mxGraphComponent graphComponent = null; + protected mxGraph graph = null; + public static final int NODE_LAYER = 0; + public static final int DATA_FLOW_LAYER = 0; + public static final int PUSH_FLOW_LAYER = 1; + public static final int PULL_FLOW_LAYER = 2; + + /************************************************************* + * [ *constructor] + /************************************************************* + * + * @param graphComponent + */ + public Stage(mxGraphComponent graphComponent) { + this.graphComponent = graphComponent; + this.graph = graphComponent.getGraph(); + } + + /************************************************************* + * + * @return model + */ + public DataTransferModel getModel() { + return model; + } + + abstract public boolean canChangeFrom(Stage prevStage); + abstract public void init(Stage prevStage); + abstract public mxICellEditor createCellEditor(mxGraphComponent graphComponent); + abstract public mxIEventListener createChangeEventListener(Editor editor); + abstract public MouseListener createMouseEventListener(Editor editor); + + /************************************************************* + * [ *public ] + /************************************************************* + * + */ + public void setEnabledForLayer(final int layerNo, final boolean isEnable) { + mxCell rootCell = (mxCell) graph.getDefaultParent(); + if(rootCell== null) return; + if(rootCell.getChildCount() <= 0) return; + + graph.getModel().setVisible(rootCell.getChildAt(layerNo), isEnable); + graph.refresh(); + } + + /************************************************************* + * Showing layers are specified number of layers. + * @param you want to show numbers of layers. + */ + public void showOnlyLayer(final int... argsOfLayers) { + mxCell rootCell = (mxCell) graph.getDefaultParent(); + if(rootCell== null) return; + if(rootCell.getChildCount() <= 0) return; + + for(int i = 0; i < rootCell.getChildCount(); i++) { + graph.getModel().setVisible(rootCell.getChildAt(i), false); + } + + for(int layerNo : argsOfLayers) { + graph.getModel().setVisible(rootCell.getChildAt(layerNo), true); + } + } +} diff --git a/AlgebraicDataflowArchitectureModel/src/application/editor/stages/ControlFlowDelegationCellEditor.java b/AlgebraicDataflowArchitectureModel/src/application/editor/stages/ControlFlowDelegationCellEditor.java new file mode 100644 index 0000000..f3caaaf --- /dev/null +++ b/AlgebraicDataflowArchitectureModel/src/application/editor/stages/ControlFlowDelegationCellEditor.java @@ -0,0 +1,183 @@ +package application.editor.stages; + +import java.util.EventObject; +import java.util.logging.Level; + +import javax.swing.CellEditor; +import javax.swing.JOptionPane; + +import com.mxgraph.model.mxCell; +import com.mxgraph.swing.mxGraphComponent; + +import application.ApplicationWindow; +import application.editor.FlowCellEditor; +import models.controlFlowModel.CallEdgeAttribute; +import models.controlFlowModel.EntryPointObjectNode; +import models.controlFlowModel.ObjectNode; +import models.controlFlowModel.ObjectNodeAttribute; +import models.controlFlowModel.StatefulObjectNode; + +/************************************************************* + * + */ +public class ControlFlowDelegationCellEditor extends FlowCellEditor { + private mxCell targetEdgeCell = null; + + /************************************************************* + * [ *constructor ] + /************************************************************* + * + * @param graph + */ + public ControlFlowDelegationCellEditor(ControlFlowDelegationStage stage, mxGraphComponent graphComponent) { + super(stage, graphComponent); + } + + /************************************************************* + * [ *public ] + /************************************************************* + * + */ + @Override + public void startEditing(Object cellObj, EventObject eventObj) { + if (editingCell != null) stopEditing(true); + ControlFlowDelegationStage cfdStage = (ControlFlowDelegationStage) stage; + + switch (cfdStage.getCurState()) { + case SELECTING_AN_EDGE: + // Branching based on the edge click event. + // | double clicked > Showing delegaeatable nodes. + ApplicationWindow.logger.log(Level.INFO, "Double clicked"); + + if (graphComponent.getGraph().getModel().isEdge(cellObj)) { + // cache a target edge of cell; + targetEdgeCell = (mxCell) cellObj; + + // Logging + CallEdgeAttribute callEdgeAttr = (CallEdgeAttribute) graphComponent.getGraph().getModel().getValue(targetEdgeCell); + if (callEdgeAttr == null) return; + + String pairNodeStr = "(" + callEdgeAttr.getSourceObjectNode().getName() + ", " + callEdgeAttr.getDestinationObjectNode().getName() + ")" ; + ApplicationWindow.logger.log(Level.INFO, "Selecting Control-Flow (src, dst) = " + pairNodeStr); + + showDelegatableNodesBySelectedEdge(cellObj); + cfdStage.setState(ControlFlowDelegationStageStatus.SHOWING_DELEGATABLE_NODES); + } + break; + + case SHOWING_DELEGATABLE_NODES: + if (graphComponent.getGraph().getModel().isVertex(cellObj)) { + mxCell dstCell = null; + if (cellObj instanceof mxCell) dstCell = (mxCell) cellObj; + else throw new ClassCastException(); + + // invocating delegation method + CallEdgeAttribute callEdgeAttr = (CallEdgeAttribute) graphComponent.getGraph().getModel().getValue(targetEdgeCell); + if (callEdgeAttr == null) return; + + ObjectNode dstObjNode = ((ObjectNodeAttribute) dstCell.getValue()).getObjectNode(); + if (dstObjNode == null) throw new ClassCastException(); + + if (!cfdStage.isExecutableDelegation(callEdgeAttr, dstObjNode)) { + JOptionPane.showMessageDialog(graphComponent, "It's impossible for \"" + dstObjNode.getName() + "\" to delegate."); + ApplicationWindow.logger.log(Level.INFO, "\"" + dstObjNode.getName() + "\"" + " wasn't able to apply to CFD"); + return; + } + + cfdStage.showDelegatedGraph(graphComponent.getGraph(), targetEdgeCell, (mxCell) cellObj); + ApplicationWindow.logger.log(Level.INFO, "Apply CFD to \"" + dstObjNode.getName() + "\""); + + cfdStage.setState(ControlFlowDelegationStageStatus.SELECTING_AN_EDGE); + } else { + // Logging + ApplicationWindow.logger.log(Level.INFO, "CFD was canceled because it was selected a control-flow"); + + cfdStage.resetAllStyleOfCells(); + cfdStage.setState(ControlFlowDelegationStageStatus.SELECTING_AN_EDGE); + } + break; + + case SHOWING_DEPENDENTABLE_NODES: + if (cfdStage.getCachedCell() == null) return; + this.targetEdgeCell = cfdStage.getCachedCell(); + + if (graphComponent.getGraph().getModel().isVertex(cellObj)) { + mxCell targetObjCell = null; + if (cellObj instanceof mxCell) targetObjCell = (mxCell) cellObj; + else throw new ClassCastException(); + + // invocation + ObjectNodeAttribute targetObjNodeAttr = (targetObjCell.getValue() instanceof ObjectNodeAttribute) + ?(ObjectNodeAttribute)targetObjCell.getValue() + :null; + if(targetObjNodeAttr == null) return; + + ObjectNode targetObjNode = targetObjNodeAttr.getObjectNode(); + if (isNotStatelessObject(targetObjNode)) { + JOptionPane.showMessageDialog(graphComponent, "It's impossible for \"" + targetObjNode.getName() + "\" to dependent."); + ApplicationWindow.logger.log(Level.INFO, "\"" + targetObjNode.getName() + "\"" + " wasn't able to apply to Depends on Mediator"); + return; + } + + dependentObjectNode(targetObjCell); + + // Logging + ApplicationWindow.logger.log(Level.INFO, "Apply Depedents on Mediator to " + "\"" + targetObjNode.getName() + "\""); + + cfdStage.resetAllStyleOfCells(); + cfdStage.setState(ControlFlowDelegationStageStatus.SELECTING_AN_EDGE); + } else { + // Logging + ApplicationWindow.logger.log(Level.INFO, "Depends on Mediator was canceled because it was selected a control-flow"); + + cfdStage.resetAllStyleOfCells(); + cfdStage.setState(ControlFlowDelegationStageStatus.SELECTING_AN_EDGE); + } + break; + } + } + + /************************************************************* + * + */ + @Override + public void stopEditing(boolean cancel) { + } + + /************************************************************* + * [ *private ] + /************************************************************* + * view + ************************************************************** + * + */ + private void showDelegatableNodesBySelectedEdge(Object cellObj) { + CallEdgeAttribute callEdgeAttr = (CallEdgeAttribute) graphComponent.getGraph().getModel().getValue(cellObj); + if (callEdgeAttr == null) + return; + + ControlFlowDelegationStage cfdStage = (ControlFlowDelegationStage) stage; + cfdStage.showDelegatableNodes(graphComponent.getGraph(), callEdgeAttr); + } + + /************************************************************ + * + */ + private void dependentObjectNode(final mxCell targetMediatorCell) { + if(targetMediatorCell == null) return; + + ControlFlowDelegationStage cfdStage = (ControlFlowDelegationStage) stage; + cfdStage.dependsOnMediatorObject(graphComponent.getGraph(), targetEdgeCell, targetMediatorCell); + } + + /************************************************************ + * + */ + private boolean isNotStatelessObject(final ObjectNode targetObjNode) { + if(targetObjNode instanceof StatefulObjectNode) return true; + if(targetObjNode instanceof EntryPointObjectNode) return true; + + return false; + } + +} diff --git a/AlgebraicDataflowArchitectureModel/src/application/editor/stages/ControlFlowDelegationStage.java b/AlgebraicDataflowArchitectureModel/src/application/editor/stages/ControlFlowDelegationStage.java new file mode 100644 index 0000000..802dac5 --- /dev/null +++ b/AlgebraicDataflowArchitectureModel/src/application/editor/stages/ControlFlowDelegationStage.java @@ -0,0 +1,800 @@ +package application.editor.stages; + +import java.awt.event.MouseEvent; +import java.awt.event.MouseListener; +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import java.util.logging.Level; + +import javax.swing.SwingUtilities; + +import com.mxgraph.model.mxCell; +import com.mxgraph.model.mxGeometry; +import com.mxgraph.model.mxGraphModel; +import com.mxgraph.swing.mxGraphComponent; +import com.mxgraph.swing.util.mxMouseAdapter; +import com.mxgraph.util.mxEventSource.mxIEventListener; +import com.mxgraph.util.mxEventObject; +import com.mxgraph.util.mxPoint; +import com.mxgraph.view.mxGraph; + +import application.ApplicationWindow; +import application.editor.Editor; +import application.editor.FlowCellEditor; +import application.editor.Stage; +import application.views.PopupMenuBase; +import application.views.controlFlowDelegation.ControlFlowDelegationStagePopupMenu; +import models.Edge; +import models.Node; +import models.controlFlowModel.CallEdge; +import models.controlFlowModel.CallEdgeAttribute; +import models.controlFlowModel.CallGraph; +import models.controlFlowModel.CompositeCallEdgeAttribute; +import models.controlFlowModel.ControlFlowDelegator; +import models.controlFlowModel.ControlFlowGraph; +import models.controlFlowModel.EntryPointObjectNode; +import models.controlFlowModel.ObjectNode; +import models.controlFlowModel.ObjectNodeAttribute; +import models.controlFlowModel.StatefulObjectNode; +import models.dataFlowModel.DataFlowGraph; +import models.dataFlowModel.PushPullValue; +import models.dataFlowModel.ResourceNode; +import models.dataFlowModel.ResourceNodeAttribute; + +/************************************************************* + * + */ +public class ControlFlowDelegationStage extends Stage { + public final int PORT_DIAMETER = 8; + public final int PORT_RADIUS = PORT_DIAMETER / 2; + + private ControlFlowDelegationStageStatus curState = null; + + private ControlFlowGraph controlFlowGraph = null; + private PopupMenuBase popupMenu = null; + + private mxCell selectedCellOnAnyEvent = null; + + /************************************************************* + * [ *constructor ] + /************************************************************* + * + */ + public ControlFlowDelegationStage(mxGraphComponent graphComoponent) { + super(graphComoponent); + this.curState = ControlFlowDelegationStageStatus.SELECTING_AN_EDGE; + this.popupMenu = new ControlFlowDelegationStagePopupMenu(this, graphComoponent); + } + + /************************************************************* + * [ *public ] + /************************************************************* + * getters / setters + /************************************************************* + */ + public ControlFlowGraph getControlFlowGraph() { + return controlFlowGraph; + } + + /************************************************************* + * + */ + public ControlFlowDelegationStageStatus getCurState() { + return curState; + } + + public void setState(ControlFlowDelegationStageStatus nextState) { + curState = nextState; + } + + + /************************************************************* + * + */ + public void setCellOnAnyEvent(final mxCell selectedCell) { + this.selectedCellOnAnyEvent = selectedCell; + } + + /************************************************************* + * + */ + public mxCell getCachedCell() { + return this.selectedCellOnAnyEvent; + } + + /************************************************************* + * + */ + @Override + public boolean canChangeFrom(Stage prevStage) { + if (prevStage instanceof PushPullSelectionStage) return true; + return false; + } + + /************************************************************* + * + */ + @Override + public void init(Stage prevStage) { + if (prevStage instanceof PushPullSelectionStage) { + model = ((PushPullSelectionStage) prevStage).getModel(); + + DataFlowGraph dataFlowGraph = ((PushPullSelectionStage) prevStage).getDataFlowGraph(); + + controlFlowGraph = new ControlFlowGraph(dataFlowGraph, model); + + clearControlFlowGraphCells(graph); + graph = constructGraph(graph, controlFlowGraph); + } + } + + + /************************************************************* + * + */ + @Override + public FlowCellEditor createCellEditor(mxGraphComponent graphComponent) { + return new ControlFlowDelegationCellEditor(this, graphComponent); + } + + /************************************************************* + * + */ + @Override + public mxIEventListener createChangeEventListener(Editor editor) { + return new mxIEventListener() { + public void invoke(Object sender, mxEventObject evt) { + List terminals = new ArrayList<>(); + mxCell cell = null; + for (Object change: ((List) evt.getProperties().get("changes"))) { + if (change instanceof mxGraphModel.mxTerminalChange) { + mxGraphModel.mxTerminalChange terminalChange = (mxGraphModel.mxTerminalChange) change; + cell = (mxCell) terminalChange.getCell(); + mxCell terminal = (mxCell) terminalChange.getTerminal(); + terminals.add(terminal); + } + } + + if(curState != ControlFlowDelegationStageStatus.SELECTING_AN_EDGE) return; + + if (terminals.size() == 2) { + graph.removeCells(new mxCell[] {cell}); + graph.clearSelection(); + } + } + }; + } + + /************************************************************* + * + */ + @Override + public MouseListener createMouseEventListener(Editor editor) { + MouseListener listener = new mxMouseAdapter() { + @Override + public void mouseReleased(MouseEvent e) { + if(SwingUtilities.isLeftMouseButton(e)) { + if(graphComponent.getCellAt(e.getX(), e.getY()) != null) return; + if(curState.equals(ControlFlowDelegationStageStatus.SELECTING_AN_EDGE)) return; + + ApplicationWindow.logger.log(Level.INFO, "Reset selection"); + resetAllStyleOfCells(); + curState = ControlFlowDelegationStageStatus.SELECTING_AN_EDGE; + + return; + } + else if(SwingUtilities.isRightMouseButton(e)) { + ApplicationWindow.logger.log(Level.INFO, "Open popup menu"); + popupMenu.show(e.getX(), e.getY()); + } + } + }; + return listener; + } + + /************************************************************* + * manipulating the control-graph + /************************************************************* + * control-flow-delegation + */ + public void showDelegatableNodes(mxGraph graph, final CallEdgeAttribute callEdgeAttr){ + mxCell root = (mxCell)graph.getDefaultParent(); + graph.getModel().beginUpdate(); + try { + ObjectNode delegatingNode = callEdgeAttr.getDestinationObjectNode(); + for(int layerNo = Stage.PUSH_FLOW_LAYER; layerNo <= PULL_FLOW_LAYER; layerNo++) { + + mxCell layerCell = (mxCell)root.getChildAt(layerNo); + for(Object node : graph.getChildVertices(layerCell)) { + if( !(node instanceof mxCell) ) continue; + mxCell cell = (mxCell)node; + + ObjectNodeAttribute objNodeAttr = (ObjectNodeAttribute)cell.getValue(); + if(objNodeAttr == null) return; + + ObjectNode objNode = objNodeAttr.getObjectNode(); + ControlFlowDelegator delegator = new ControlFlowDelegator(controlFlowGraph); + List delegatableNodes = delegator.searchDelegatableNodes(callEdgeAttr.getCallEdge()); + + if(delegatableNodes.contains(objNode)) { + graph.getModel().setStyle(cell, objNodeAttr.getEnableStyle()); + } + else { + graph.getModel().setStyle(cell, objNodeAttr.getDisableStyle()); + } + + if(delegatingNode.equals(objNodeAttr.getObjectNode())) + /* base-Node*/graph.getModel().setStyle(cell, objNodeAttr.getDelegatingStyle()); + } + } + } + finally { + graph.getModel().endUpdate(); + graph.refresh(); + } + } + + /************************************************************* + * dependent-on-mediator + */ + public void showDependentableNodes(mxGraph graph, final CallEdgeAttribute callEdgeAttr) { + mxCell root = (mxCell)graph.getDefaultParent(); + mxCell layerCell = (mxCell)root.getChildAt(PULL_FLOW_LAYER); + graph.getModel().beginUpdate(); + try { + ObjectNode delegatingNode = callEdgeAttr.getDestinationObjectNode(); + + for(Object node : graph.getChildVertices(layerCell)) { + if( !(node instanceof mxCell) ) continue; + mxCell cell = (mxCell)node; + + ObjectNodeAttribute objNodeAttr = (ObjectNodeAttribute)cell.getValue(); + if(objNodeAttr == null) return; + + ObjectNode objNode = objNodeAttr.getObjectNode(); + ControlFlowDelegator delegator = new ControlFlowDelegator(controlFlowGraph); + List delegatableNodes = delegator.searchDependentableMediatorNodes(callEdgeAttr.getCallEdge()); + + if(delegatableNodes.contains(objNode)) { + graph.getModel().setStyle(cell, objNodeAttr.getEnableStyle()); + } + else { + graph.getModel().setStyle(cell, objNodeAttr.getDisableStyle()); + } + + if(delegatingNode.equals(objNodeAttr.getObjectNode())) + /* base-Node*/graph.getModel().setStyle(cell, objNodeAttr.getDelegatingStyle()); + } + } + finally { + graph.getModel().endUpdate(); + graph.refresh(); + } + } + + /************************************************************* + * Showing the graph that was executed CFD. + */ + public void showDelegatedGraph(mxGraph graph, mxCell targetEdgeCell, final mxCell dstObjNodeCell) { + ObjectNode dstObjNode = ((ObjectNodeAttribute)dstObjNodeCell.getValue()).getObjectNode(); + if(dstObjNode == null) throw new ClassCastException(); + CallEdgeAttribute targetEdgeAttr = (CallEdgeAttribute)targetEdgeCell.getValue(); + if(targetEdgeAttr == null) throw new ClassCastException(); + + ControlFlowDelegator delegator = new ControlFlowDelegator(controlFlowGraph); + delegator.delegateCallEdge(targetEdgeAttr.getCallEdge(), dstObjNode); + + mxCell root = (mxCell)graph.getDefaultParent(); + mxCell layerCell = null; + switch(targetEdgeAttr.getSelectedOption()) { + case PUSH: + layerCell = (mxCell)root.getChildAt(Stage.PUSH_FLOW_LAYER); + break; + + case PULL: + case PUSHorPULL: + layerCell = (mxCell)root.getChildAt(Stage.PULL_FLOW_LAYER); + } + + try { + mxCell dstNodeCell = targetEdgeAttr.getDestinationCell(); + + // Removing the target edge from graph model. + if(graph.getModel().getValue(targetEdgeCell) != null) { + graph.getModel().remove(targetEdgeCell); + } + + // Insert an edge + CallEdgeAttribute newAttr = new CallEdgeAttribute(targetEdgeAttr.getCallEdge(), targetEdgeAttr.getOriginalSourceObjectNode(),dstObjNodeCell, dstNodeCell); + graph.insertEdge(layerCell, "", newAttr, dstObjNodeCell, dstNodeCell, "movable=false;"); + + resetAllStyleOfCells(); + } + finally { + graph.getModel().endUpdate(); + } + } + + /************************************************************* + * + */ + public void dependsOnMediatorObject(mxGraph graph, mxCell targetEdgeCell ,mxCell targetMediatorObjNodeCell) { + CallEdgeAttribute targetCallEdgeAttr = (CallEdgeAttribute)targetEdgeCell.getValue(); + if(targetCallEdgeAttr == null) return; + + mxCell root = (mxCell)graph.getDefaultParent(); + mxCell pullFlowLayerCell = (mxCell)root.getChildAt(Stage.PULL_FLOW_LAYER); + + graph.getModel().beginUpdate(); + + try { + // Reconnecting each edges of the node. + // Get each of the transformed object + ObjectNode srcObjNode = targetCallEdgeAttr.getSourceObjectNode(); + ObjectNode dstObjNode = targetCallEdgeAttr.getDestinationObjectNode(); + if(srcObjNode == null || dstObjNode == null) throw new NullPointerException(); + if(!(srcObjNode instanceof ObjectNode && dstObjNode instanceof ObjectNode)) throw new ClassCastException(); + + // Get target "Mediator Object" + ObjectNodeAttribute targetObjNodeAttr = (ObjectNodeAttribute)targetMediatorObjNodeCell.getValue(); + if(targetObjNodeAttr == null) throw new NullPointerException(); + + ObjectNode targetMediatorObjNode = targetObjNodeAttr.getObjectNode(); + if(targetMediatorObjNode == null) throw new NullPointerException(); + if(targetMediatorObjNode instanceof StatefulObjectNode || targetMediatorObjNode instanceof EntryPointObjectNode) return; + + + // Connecting I/O Edges to the insert object. + CallEdge srcToMediatorEdge = new CallEdge(targetCallEdgeAttr.getSourceObjectNode(), targetMediatorObjNode, targetCallEdgeAttr.getSelectedOption()); + CallEdge mediatorToDstEdge = new CallEdge(targetMediatorObjNode, dstObjNode, targetCallEdgeAttr.getSelectedOption()); + if(srcToMediatorEdge == null || mediatorToDstEdge == null) throw new NullPointerException(); + + // Manipulate an edge of the source object node. + srcObjNode.addOutEdge(srcToMediatorEdge); + srcObjNode.removeOutEdge(targetCallEdgeAttr.getCallEdge()); + + // Manipulate an edge of the destination object node. + dstObjNode.removeInEdge(targetCallEdgeAttr.getCallEdge()); + + // Connect an edge of the mediation object node. + targetMediatorObjNode.addInEdge(srcToMediatorEdge); + + // Create composition Attribute of the Call-Edge . + // Get already connected call-edge. + CompositeCallEdgeAttribute compositeEdgeAttr = null; + + for(int i = 0; i < pullFlowLayerCell.getChildCount(); i++) { + mxCell edgeCell = (mxCell)pullFlowLayerCell.getChildAt(i); + if (!edgeCell.isEdge() ) continue; + if (!(edgeCell.getValue() instanceof CallEdgeAttribute)) continue; + + CallEdgeAttribute edgeAttr = (CallEdgeAttribute)edgeCell.getValue(); + + if (!(edgeAttr.getSourceObjectNode().equals(targetMediatorObjNode)))continue; + if (!(edgeAttr.getDestinationObjectNode().equals(dstObjNode)))continue; + + compositeEdgeAttr = new CompositeCallEdgeAttribute(edgeAttr); + + break; + } + + if(compositeEdgeAttr != null) + compositeEdgeAttr.mergeCallEdgeAttribute(targetCallEdgeAttr); + + // Manipulate the cell of the graph. + for(int i = 0; i < pullFlowLayerCell.getChildCount(); i++) { + mxCell nodeCell = (mxCell)pullFlowLayerCell.getChildAt(i); + if( !nodeCell.isVertex() ) continue; + + // Check "nodeCell" has an instance of + ObjectNodeAttribute cellObjNodeAttr = (ObjectNodeAttribute)nodeCell.getValue(); + if(cellObjNodeAttr == null) throw new ClassCastException("dosen't have the value of "); + + // Is "nodeCell" the same as the source cell of the call edge? + if(nodeCell.equals(targetCallEdgeAttr.getSourceCell())){ + mxCell srcNodeCell = targetCallEdgeAttr.getSourceCell(); + + // If the target call edge hasn't removed yet. + // then it removes from mxGraphModel. + if(graph.getModel().getValue(targetEdgeCell) != null) + graph.getModel().remove(targetEdgeCell); + + graph.insertEdge(pullFlowLayerCell, null, compositeEdgeAttr, srcNodeCell, targetMediatorObjNodeCell, "movable=false;"); + continue; + } + + } + } + finally { + graph.getModel().endUpdate(); + } + } + + /************************************************************* + * + */ + public void resetAllStyleOfCells() { + mxCell root = (mxCell)graph.getDefaultParent(); + + graph.getModel().beginUpdate(); + try { + for(int layerNo = Stage.PUSH_FLOW_LAYER; layerNo <= Stage.PULL_FLOW_LAYER; layerNo++) { + + mxCell layerCell = (mxCell)root.getChildAt(layerNo); + for(Object node : graph.getChildVertices(layerCell)) { + mxCell cell = null; + if(node instanceof mxCell) cell = (mxCell)node; + else continue; + + ObjectNodeAttribute objNodeAttr = (ObjectNodeAttribute)(cell.getValue()); + if(objNodeAttr == null) throw new NullPointerException(""); + + graph.getModel().setStyle(cell, objNodeAttr.getDefaultStyle()); + } + } + } + finally { + graph.getModel().endUpdate(); + graph.refresh(); + } + } + + /************************************************************* + * Inserting an intermediation object type of . + */ + public void insertObjectNodeCellInControlFlowLayer(mxGraph graph, mxCell targetEdge, final String insertObjName) { + CallEdgeAttribute callEdgeAttr = (CallEdgeAttribute)targetEdge.getValue(); + if(callEdgeAttr == null) throw new NullPointerException(); + + mxCell root = (mxCell)graph.getDefaultParent(); + mxCell layerCell = null; + switch(callEdgeAttr.getSelectedOption()) { + case PUSH: + layerCell = (mxCell)root.getChildAt(Stage.PUSH_FLOW_LAYER); + break; + + case PULL: + case PUSHorPULL: + layerCell = (mxCell)root.getChildAt(Stage.PULL_FLOW_LAYER); + break; + } + + graph.getModel().beginUpdate(); + + try { + // Inserting the node type of to the graph. + ObjectNode insertObjNode = new ObjectNode(insertObjName); + ObjectNodeAttribute objNodeAttr = new ObjectNodeAttribute(insertObjNode); + + mxPoint srcPoint = new mxPoint(callEdgeAttr.getSourceCell().getGeometry().getX(), callEdgeAttr.getSourceCell().getGeometry().getY()); + mxPoint dstPoint = new mxPoint(callEdgeAttr.getDestinationCell().getGeometry().getX(), callEdgeAttr.getDestinationCell().getGeometry().getY()); + mxPoint insertPoint = new mxPoint( + (srcPoint.getX() + dstPoint.getX())/2, + (srcPoint.getY() + dstPoint.getY())/2); + + mxCell insertObjNodeCell = + (mxCell)graph.insertVertex(layerCell, null, objNodeAttr, + /* coordinate*/ insertPoint.getX(), insertPoint.getY(), + /* scale */ 40, 40, + objNodeAttr.getDefaultStyle()); + insertObjNodeCell.setValue(objNodeAttr); + + addObjectNodeToCallGraph(insertObjNode, callEdgeAttr.getSelectedOption()); + + // Reconnecting each edges of the node. + ObjectNode srcObjNode = callEdgeAttr.getSourceObjectNode(); + ObjectNode dstObjNode = callEdgeAttr.getDestinationObjectNode(); + if(srcObjNode == null || dstObjNode == null) throw new NullPointerException(); + if(!(srcObjNode instanceof ObjectNode && dstObjNode instanceof ObjectNode)) throw new ClassCastException(); + + // Connecting I/O Edges to the insert object. + CallEdge srcToInsertEdge = callEdgeAttr.getCallEdge(); + CallEdge insertToDstEdge = new CallEdge(insertObjNode, dstObjNode, callEdgeAttr.getSelectedOption()); + if(srcToInsertEdge == null || insertToDstEdge == null) throw new NullPointerException(); + + // Remove the destination edge of the object node. + // After add the "srcToInsertEdge" to the destination object node. + dstObjNode.removeInEdge(srcToInsertEdge); + dstObjNode.addInEdge(insertToDstEdge); + + srcToInsertEdge.setDestination(insertObjNode); // changing the out of edge of the sourceObjectNode + + insertObjNode.addInEdge(srcToInsertEdge); + insertObjNode.addOutEdge(insertToDstEdge); + + // Update the cell of the graph. + for(int i =0; i < layerCell.getChildCount(); i++) { + mxCell nodeCell = (mxCell)layerCell.getChildAt(i); + if( !nodeCell.isVertex()) continue; + + // Checking "nodeCell" has an instance of + ObjectNodeAttribute cellObjNodeAttr = (ObjectNodeAttribute)nodeCell.getValue(); + if(cellObjNodeAttr == null) throw new ClassCastException("dosen't have the value of "); + + // Is "nodeCell" the same as the source cell of the call edge? + if(nodeCell.equals(callEdgeAttr.getSourceCell())){ + mxCell srcNodeCell = callEdgeAttr.getSourceCell(); + CallEdgeAttribute newInEdgeAttr = new CallEdgeAttribute(srcToInsertEdge, srcNodeCell, insertObjNodeCell); + + // If the target call edge hasn't removed yet. + // then it removes from mxGraphModel. + if(graph.getModel().getValue(targetEdge) != null) + graph.getModel().remove(targetEdge); + + mxCell outPortCell = (mxCell)srcNodeCell.getChildAt(0); + if(outPortCell != null) { + graph.insertEdge(layerCell, null, newInEdgeAttr, outPortCell, insertObjNodeCell, "movable=false;"); + } + else { + graph.insertEdge(layerCell, null, newInEdgeAttr, srcNodeCell, insertObjNodeCell, "movable=false;"); + } + continue; + } + // Is "nodeCell" the same as the destination cell of the call edge? + else if(nodeCell.equals(callEdgeAttr.getDestinationCell())) { + mxCell dstNodeCell = callEdgeAttr.getDestinationCell(); + CallEdgeAttribute newOutEdgeAttr = new CallEdgeAttribute(insertToDstEdge, insertObjNodeCell, dstNodeCell); + + // If the target + if(graph.getModel().getValue(targetEdge) != null) + graph.getModel().remove(targetEdge); + + graph.insertEdge(layerCell, null, newOutEdgeAttr, insertObjNodeCell, dstNodeCell, "movable=false;"); + + continue; + } + } + } + finally { + graph.getModel().endUpdate(); + } + } + + /************************************************************* + * + */ + public boolean isExecutableDelegation(final CallEdgeAttribute targetEdgeAttr, final ObjectNode dstObjNode) { + ControlFlowDelegator delegator = new ControlFlowDelegator(controlFlowGraph); + List delegatableNodes = delegator.searchDelegatableNodes(targetEdgeAttr.getCallEdge()); + + return delegatableNodes.contains(dstObjNode); + } + + /************************************************************* + /************************************************************* + * [ *private ] + /************************************************************* + * + */ + private mxGraph constructGraph(mxGraph graph, ControlFlowGraph controlFlowGraph) { + showOnlyLayer(PUSH_FLOW_LAYER, PULL_FLOW_LAYER); + + graph.getModel().beginUpdate(); + try { + // Creating Control-Flow and separeted Push/Pull which types of + Map pushResNodeCells = createCellsOfResourceMap(graph, PUSH_FLOW_LAYER, controlFlowGraph); + Map pullResNodeCells = createCellsOfResourceMap(graph, PULL_FLOW_LAYER, controlFlowGraph); + + // Creating Entry-Point Object + Map pushFlowEntryNodeCells = createCellsOfInputChannel(graph, PUSH_FLOW_LAYER, controlFlowGraph, pushResNodeCells); + + // Inserting edges of each transfer + graph = insertControlFlowEdges(graph, PUSH_FLOW_LAYER, controlFlowGraph.getPushCallGraph(), pushResNodeCells, pushFlowEntryNodeCells); + graph = insertControlFlowEdges(graph, PULL_FLOW_LAYER, controlFlowGraph.getPullCallGraph(), pullResNodeCells, null); + + } finally { + graph.getModel().endUpdate(); + } + return graph; + } + + + /************************************************************* + * When changed from previous stage, it will be called in initializing. + */ + private void clearControlFlowGraphCells(mxGraph graph) { + mxCell root = (mxCell)graph.getDefaultParent(); + + graph.getModel().beginUpdate(); + try { + // removing child from end of a root cell + root.remove(root.getChildAt(PULL_FLOW_LAYER)); + root.remove(root.getChildAt(PUSH_FLOW_LAYER)); + + root.insert(new mxCell()); + root.insert(new mxCell()); + } finally { + graph.getModel().endUpdate(); + graph.refresh(); + } + } + + + /************************************************************* + * Creating a map of to and Creating 's vertices + * @return constructed the view of the graph + */ + private Map createCellsOfResourceMap(mxGraph graph, final int layerNumber, final ControlFlowGraph controlFlowGraph) { + Map resNodeCells = new HashMap<>(); + + mxCell root = (mxCell)graph.getDefaultParent(); + mxCell nodeLayerCell = (mxCell)root.getChildAt(NODE_LAYER); + mxCell layerCell = (mxCell)root.getChildAt(layerNumber); + + // create resource vertices + for (ResourceNode resNode : controlFlowGraph.getDataFlowGraph().getResouceNodes()) { + + ObjectNode objNode = null; + switch(layerNumber) { + case PUSH_FLOW_LAYER: + if(controlFlowGraph.getPushCallGraph().getStatefulObjectNode(resNode) != null) + objNode = controlFlowGraph.getPushCallGraph().getStatefulObjectNode(resNode); + break; + + case PULL_FLOW_LAYER: + if(controlFlowGraph.getPullCallGraph().getStatefulObjectNode(resNode) != null) + objNode = controlFlowGraph.getPullCallGraph().getStatefulObjectNode(resNode); + break; + } + + if(objNode == null) continue; + + for(int i =0; i < nodeLayerCell.getChildCount(); i++) { + mxCell nodeCell = (mxCell)nodeLayerCell.getChildAt(i); + if( nodeCell.getValue() instanceof ResourceNodeAttribute ) { + nodeCell = (mxCell)nodeLayerCell.getChildAt(i); + } + else continue; + + // Checking if the "node" has a cell of the data-flow-layer is the same as "resNode". + ResourceNodeAttribute resNodeAttr = (ResourceNodeAttribute)nodeCell.getValue(); + if( !resNodeAttr.getResourceNode().equals(resNode) )continue; + + // Getting information from the cell in the data-flow-layer, + // After that, insert a resource as a vertex + ObjectNodeAttribute objNodeAttr = new ObjectNodeAttribute(objNode); + mxCell resNodeObjCell = (mxCell)graph.insertVertex(layerCell, null, objNodeAttr, + /* scale */nodeCell.getGeometry().getX(), nodeCell.getGeometry().getY(), + /*coordinate*/nodeCell.getGeometry().getWidth(), nodeCell.getGeometry().getHeight(), + objNodeAttr.getDefaultStyle()); + + resNodeCells.put(resNode, resNodeObjCell); + } + } + + return resNodeCells; + } + + + /************************************************************* + * Create an input channel object + */ + private Map createCellsOfInputChannel(mxGraph graph, final int layerNumber, final ControlFlowGraph controlGraph, final Map resNodeCell){ + if(layerNumber == PULL_FLOW_LAYER) return null; + + mxCell root = (mxCell)graph.getDefaultParent(); + mxCell layerCell = (mxCell)root.getChildAt(layerNumber); + + Map ioChannelCells = new HashMap<>(); + + graph.getModel().beginUpdate(); + try { + mxGeometry outPortGeometry = new mxGeometry(1.0, 0.5, PORT_DIAMETER, PORT_DIAMETER); + outPortGeometry.setOffset(new mxPoint(-PORT_RADIUS, -PORT_RADIUS)); + outPortGeometry.setRelative(true); + + CallGraph callGraph = controlFlowGraph.getPushCallGraph(); + + // insert an I/O channel as a vertex + for (Node node : callGraph.getNodes()) { + EntryPointObjectNode entryPointObjNode = null; + if(node instanceof EntryPointObjectNode) + entryPointObjNode = (EntryPointObjectNode)node; + else continue; + + ObjectNodeAttribute entryObjAttr = new ObjectNodeAttribute(entryPointObjNode); + + // Taking over geometry information from the channel node with the same name. + mxCell dataFlowLayerCell = (mxCell)root.getChildAt(Stage.DATA_FLOW_LAYER); + for(int i = 0; i < dataFlowLayerCell.getChildCount(); i++) { + mxCell channelCell =(mxCell)dataFlowLayerCell.getChildAt(i); + + String entryPointObjNodeName = entryPointObjNode.getIOChannel().getChannelName(); + String channelCellName = ""; + if(channelCell.getValue() instanceof String) channelCellName = (String) channelCell.getValue(); + else continue; + + if(!entryPointObjNodeName.equals(channelCellName))continue; + + mxCell entryPointCelll = (mxCell)graph.insertVertex(layerCell, null, entryObjAttr, + /* scale */ channelCell.getGeometry().getX(), channelCell.getGeometry().getY(), + /* geometry*/channelCell.getGeometry().getWidth(), channelCell.getGeometry().getHeight()); + mxCell port_out = new mxCell(null, outPortGeometry, "shape=ellipse;perimter=ellipsePerimeter"); + port_out.setVertex(true); + + graph.addCell(port_out, entryPointCelll); // insert the output port of a channel + ioChannelCells.put(entryPointObjNode, entryPointCelll); + } + } + } + finally { + graph.getModel().endUpdate(); + } + + return ioChannelCells; + } + + + /************************************************************* + * + */ + private mxGraph insertControlFlowEdges(mxGraph graph, final int layerNumber, final CallGraph callGraph ,final Map resNodeCells, final Map entryNodeCells) { + mxCell root = (mxCell)graph.getDefaultParent(); + mxCell layerCell = (mxCell)root.getChildAt(layerNumber); + + for (Edge callGraphEdge : callGraph.getEdges()) { + if ( !(callGraphEdge instanceof CallEdge))continue; + CallEdge callEdge = (CallEdge) callGraphEdge; + + // Is checking node connecting a resource? + if(callEdge.getSource() == null || callEdge.getDestination() == null) continue; + + Node srcResNode = null; + ResourceNode dstResNode = ((StatefulObjectNode)callEdge.getDestination()).getResource(); + + mxCell srcNodeCell =null; + mxCell srcOutPortCell = null; + mxCell dstNodeCell = resNodeCells.get(dstResNode); + + if(callEdge.getSource() instanceof StatefulObjectNode) { + srcResNode = ((StatefulObjectNode)callEdge.getSource()).getResource(); + srcNodeCell =resNodeCells.get(srcResNode); + } + else if (callEdge.getSource() instanceof EntryPointObjectNode) { + srcResNode = (EntryPointObjectNode)callEdge.getSource(); + srcNodeCell = entryNodeCells.get(srcResNode); + srcOutPortCell = (mxCell)srcNodeCell.getChildAt(0); + } + else continue; + + if(srcNodeCell == null || dstNodeCell == null) continue; + + CallEdgeAttribute callEdgeAttr = new CallEdgeAttribute(callEdge, (ObjectNode)callEdge.getSource(), srcNodeCell, dstNodeCell); + + // If "srcResNode" types of "EntryPointObjectNode" (= channel) + // then parameter references to geometry of "outPort". + if(srcResNode instanceof ResourceNode) { + graph.insertEdge(layerCell, null, callEdgeAttr, srcNodeCell, dstNodeCell, "movable=false;"); + } + else if(srcResNode instanceof EntryPointObjectNode) { + graph.insertEdge(layerCell, null, callEdgeAttr, srcOutPortCell, dstNodeCell, "movable=false;"); + } + + } + return graph; + } + + + /************************************************************* + * + */ + private void addObjectNodeToCallGraph(final ObjectNode insertObjNode, final PushPullValue selectedOption) { + switch(selectedOption) { + case PUSH: + if(controlFlowGraph.getPushCallGraph().getNodes().contains(insertObjNode))return; + controlFlowGraph.getPushCallGraph().addNode(insertObjNode); + + break; + + case PULL: + case PUSHorPULL: + if(controlFlowGraph.getPullCallGraph().getNodes().contains(insertObjNode))return; + controlFlowGraph.getPullCallGraph().addNode(insertObjNode); + + break; + } + } + +} diff --git a/AlgebraicDataflowArchitectureModel/src/application/editor/stages/ControlFlowDelegationStageStatus.java b/AlgebraicDataflowArchitectureModel/src/application/editor/stages/ControlFlowDelegationStageStatus.java new file mode 100644 index 0000000..93a88a4 --- /dev/null +++ b/AlgebraicDataflowArchitectureModel/src/application/editor/stages/ControlFlowDelegationStageStatus.java @@ -0,0 +1,10 @@ +package application.editor.stages; + +/************************************************************* + * + */ +public enum ControlFlowDelegationStageStatus { + SELECTING_AN_EDGE, + SHOWING_DELEGATABLE_NODES, + SHOWING_DEPENDENTABLE_NODES +} diff --git a/AlgebraicDataflowArchitectureModel/src/application/editor/stages/DataFlowCellEditor.java b/AlgebraicDataflowArchitectureModel/src/application/editor/stages/DataFlowCellEditor.java new file mode 100644 index 0000000..a893a85 --- /dev/null +++ b/AlgebraicDataflowArchitectureModel/src/application/editor/stages/DataFlowCellEditor.java @@ -0,0 +1,152 @@ +package application.editor.stages; + +import java.awt.GridBagConstraints; +import java.awt.GridBagLayout; +import java.awt.Rectangle; +import java.util.EventObject; +import java.util.List; + +import javax.swing.BorderFactory; +import javax.swing.JComboBox; +import javax.swing.JLabel; +import javax.swing.JOptionPane; +import javax.swing.JPanel; +import javax.swing.JTextArea; +import javax.swing.JTextField; + +import com.mxgraph.model.mxCell; +import com.mxgraph.model.mxIGraphModel; +import com.mxgraph.swing.mxGraphComponent; +import com.mxgraph.swing.view.mxICellEditor; +import com.mxgraph.util.mxConstants; +import com.mxgraph.util.mxUtils; +import com.mxgraph.view.mxCellState; + +import application.editor.Editor; +import application.editor.FlowCellEditor; +import models.algebra.Expression; +import models.dataFlowModel.DataTransferModel; +import models.dataFlowModel.DataTransferChannel; +import models.dataFlowModel.PushPullAttribute; +import models.dataFlowModel.PushPullValue; +import models.visualModel.FormulaChannel; +import parser.Parser; +import parser.Parser.TokenStream; +import parser.exceptions.ExpectedColon; +import parser.exceptions.ExpectedRightBracket; +import parser.exceptions.WrongJsonExpression; + +/************************************************************* + * + */ +public class DataFlowCellEditor extends FlowCellEditor { + + /************************************************************* + * [ *constructor ] + /************************************************************* + * + * @param stage + * @param graphComponent + */ + public DataFlowCellEditor(DataFlowModelingStage stage, mxGraphComponent graphComponent) { + super(stage, graphComponent); + } + + /************************************************************* + * + * @param cellObj + * @param eventObj + */ + @Override + public void startEditing(Object cellObj, EventObject eventObj) { + if (editingCell != null) { + stopEditing(true); + } + + if (!graphComponent.getGraph().getModel().isEdge(cellObj)) { + DataTransferChannel ch = (DataTransferChannel) stage.getModel().getChannel((String) ((mxCell) cellObj).getValue()); + if (ch == null) { + ch = (DataTransferChannel) stage.getModel().getIOChannel((String) ((mxCell) cellObj).getValue()); + if(ch == null) { + //resource + return; + } + } + + if (ch instanceof FormulaChannel) { + + JPanel panel = new JPanel(); + JLabel label1 = new JLabel("Formula: "); + JLabel label2 = new JLabel("Source: "); + GridBagLayout layout = new GridBagLayout(); + panel.setLayout(layout); + GridBagConstraints gbc = new GridBagConstraints(); + + gbc.gridx = 0; + gbc.gridy = 0; + layout.setConstraints(label1, gbc); + panel.add(label1); + + gbc.gridx = 1; + gbc.gridy = 0; + JTextField formulaText = new JTextField(((FormulaChannel) ch).getFormula(),15); + layout.setConstraints(formulaText, gbc); + panel.add(formulaText); + + gbc.gridx = 0; + gbc.gridy = 1; + layout.setConstraints(label2, gbc); + panel.add(label2); + + gbc.gridx = 1; + gbc.gridy = 1; + JTextArea textArea = new JTextArea(ch.getSourceText(),7,15); + textArea.setEditable(false); + layout.setConstraints(textArea, gbc); + panel.add(textArea); + + int r = JOptionPane.showConfirmDialog( + null, // owner window + panel, // message + "Edit Formula Channel", // window's title + JOptionPane.OK_CANCEL_OPTION, // option (button types) + JOptionPane.QUESTION_MESSAGE); // message type (icon types) + if (r == JOptionPane.OK_OPTION) { + TokenStream stream = new Parser.TokenStream(); + Parser parser = new Parser(stream); + + String formula = formulaText.getText(); + stream.addLine(formula.split(Parser.EQUALS)[1]); + + + try { + Expression exp = parser.parseTerm(stream, stage.getModel()); + ((FormulaChannel) ch).setFormula(formula); + ((FormulaChannel) ch).setFormulaTerm(exp); + } catch (ExpectedRightBracket | WrongJsonExpression | ExpectedColon e) { + e.printStackTrace(); + } + } + } else { + JPanel panel = new JPanel(); + JTextArea textArea = new JTextArea(ch.getSourceText(), 10, 20); + panel.add(textArea); + // JEditorPane panel = new JEditorPane("text/plain", ch.toString()); + // panel.setEditable(true); + int ret = JOptionPane.showConfirmDialog(null, panel, "Channel Code", JOptionPane.OK_CANCEL_OPTION); + if (ret == JOptionPane.OK_OPTION) { + ((DataFlowModelingStage)stage).setChannelCode(ch, textArea.getText()); + } + } + return; + } + } + + /************************************************************* + * + * @param cancel + */ + @Override + public void stopEditing(boolean cancel) { + } +} diff --git a/AlgebraicDataflowArchitectureModel/src/application/editor/stages/DataFlowModelingStage.java b/AlgebraicDataflowArchitectureModel/src/application/editor/stages/DataFlowModelingStage.java new file mode 100644 index 0000000..db1f2f7 --- /dev/null +++ b/AlgebraicDataflowArchitectureModel/src/application/editor/stages/DataFlowModelingStage.java @@ -0,0 +1,467 @@ +package application.editor.stages; + +import java.awt.event.MouseListener; +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; +import java.util.Map; + +import com.mxgraph.model.mxCell; +import com.mxgraph.model.mxGeometry; +import com.mxgraph.model.mxGraphModel; +import com.mxgraph.swing.mxGraphComponent; +import com.mxgraph.util.mxEventSource.mxIEventListener; +import com.mxgraph.util.mxEventObject; +import com.mxgraph.util.mxPoint; +import com.mxgraph.view.mxGraph; + +import algorithms.Validation; +import application.editor.Editor; +import application.editor.Editor.SrcDstAttribute; +import application.editor.FlowCellEditor; +import application.editor.Stage; +import models.dataConstraintModel.Channel; +import models.dataConstraintModel.ChannelMember; +import models.dataConstraintModel.ResourcePath; +import models.dataFlowModel.DataTransferChannel; +import models.dataFlowModel.DataTransferModel; +import models.dataFlowModel.ResourceNodeAttribute; +import models.visualModel.FormulaChannel; +import parser.Parser; +import parser.Parser.TokenStream; +import parser.exceptions.ExpectedAssignment; +import parser.exceptions.ExpectedChannel; +import parser.exceptions.ExpectedChannelName; +import parser.exceptions.ExpectedColon; +import parser.exceptions.ExpectedEquals; +import parser.exceptions.ExpectedInOrOutOrRefKeyword; +import parser.exceptions.ExpectedLeftCurlyBracket; +import parser.exceptions.ExpectedRHSExpression; +import parser.exceptions.ExpectedRightBracket; +import parser.exceptions.ExpectedStateTransition; +import parser.exceptions.WrongJsonExpression; +import parser.exceptions.WrongLHSExpression; +import parser.exceptions.WrongRHSExpression; + +/************************************************************* + * + * @author n-nitta, k-fujii + */ +public class DataFlowModelingStage extends Stage { + public int PORT_DIAMETER = 8; + public int PORT_RADIUS = PORT_DIAMETER / 2; + + private boolean bReflectingArchitectureModel = false; + + /************************************************************* + * [ *constructor] + /************************************************************* + * + */ + public DataFlowModelingStage(mxGraphComponent graphComponent) { + super(graphComponent); + } + + /************************************************************* + * [ *public ] + /************************************************************* + * + */ + @Override + public boolean canChangeFrom(Stage prevStage) { + return true; + } + + /************************************************************* + * + */ + @Override + public void init(Stage prevStage) { + showOnlyLayer(DATA_FLOW_LAYER); + } + + /************************************************************* + * + */ + @Override + public FlowCellEditor createCellEditor(mxGraphComponent graphComponent) { + return new DataFlowCellEditor(this, graphComponent); + } + + @Override + public mxIEventListener createChangeEventListener(Editor editor) { + return new mxIEventListener() { + public void invoke(Object sender, mxEventObject evt) { + List terminals = new ArrayList<>(); + mxCell cell = null; + for (Object change: ((List) evt.getProperties().get("changes"))) { + if (change instanceof mxGraphModel.mxTerminalChange) { + mxGraphModel.mxTerminalChange terminalChange = (mxGraphModel.mxTerminalChange) change; + cell = (mxCell) terminalChange.getCell(); + mxCell terminal = (mxCell) terminalChange.getTerminal(); + terminals.add(terminal); + } + } + if (terminals.size() == 2) { + if (!editor.connectEdge(cell, terminals.get(0), terminals.get(1))) { + graph.removeCells(new mxCell[] {cell}); + graph.clearSelection(); + } + } + } + }; + } + + @Override + public MouseListener createMouseEventListener(Editor editor) { + return null; + } + + /************************************************************* + * + */ + public void clear() { + model = null; + ((mxGraphModel) graph.getModel()).clear(); + + // Construct layers. + mxCell root = (mxCell) graph.getDefaultParent(); + graph.getModel().beginUpdate(); + try { + root.insert(new mxCell()); // NODE_LAYER, DATA_FLOW_LAYER + root.insert(new mxCell()); // PUSH_FLOW_LAYER + root.insert(new mxCell()); // PULL_FLOW_LAYER + + showOnlyLayer(NODE_LAYER, DATA_FLOW_LAYER); + } + finally { + graph.getModel().endUpdate(); + } + graph.refresh(); + } + + /************************************************************* + * + */ + public DataTransferModel getModel() { + if (model == null) { + setModel(new DataTransferModel()); + } + return model; + } + + /************************************************************* + * + */ + public void setModel(DataTransferModel model) { + clear(); + // Set the model. + this.model = model; + + // Update the mxGraph. + graph = constructGraph(graph, model); + } + + /************************************************************* + * + */ + public boolean isValid() { + if (model == null) return false; + if (!Validation.checkUpdateConflict(model)) return false; + return true; + } + + /************************************************************* + * Construct a mxGraph from DataFlowModel + * @param model + * @param dataFlowGraph + * @return constructed mxGraph + */ + public mxGraph constructGraph(mxGraph graph, DataTransferModel model) { + bReflectingArchitectureModel = true; + mxCell root = (mxCell) graph.getDefaultParent(); + mxCell nodeLayer = (mxCell) root.getChildAt(NODE_LAYER); + mxCell dataFlowLayer = (mxCell) root.getChildAt(DATA_FLOW_LAYER); + + graph.getModel().beginUpdate(); + try { + mxGeometry geo1 = new mxGeometry(0, 0.5, PORT_DIAMETER, PORT_DIAMETER); + geo1.setOffset(new mxPoint(-PORT_RADIUS, -PORT_RADIUS)); + geo1.setRelative(true); + + mxGeometry geo2 = new mxGeometry(1.0, 0.5, PORT_DIAMETER, PORT_DIAMETER); + geo2.setOffset(new mxPoint(-PORT_RADIUS, -PORT_RADIUS)); + geo2.setRelative(true); + + Map channelsIn = new HashMap<>(); + Map channelsOut = new HashMap<>(); + Map resources = new HashMap<>(); + + // create channel vertices + for (Channel c: model.getChannels()) { + DataTransferChannel channelGen = (DataTransferChannel) c; + if (channelsIn.get(channelGen) == null || channelsOut.get(channelGen) == null) { + Object channel = graph.insertVertex(dataFlowLayer, null, channelGen.getChannelName(), 150, 20, 30, 30); // insert a channel as a vertex + mxCell port_in = new mxCell(null, geo1, "shape=ellipse;perimter=ellipsePerimeter"); + port_in.setVertex(true); + graph.addCell(port_in, channel); // insert the input port of a channel + mxCell port_out = new mxCell(null, geo2, "shape=ellipse;perimter=ellipsePerimeter"); + port_out.setVertex(true); + graph.addCell(port_out, channel); // insert the output port of a channel + channelsIn.put(channelGen, port_in); + channelsOut.put(channelGen, port_out); + } + } + + // create resource vertices + for (ResourcePath res: model.getResourcePaths()) { + // insert a resource as a vertex + ResourceNodeAttribute resNodeAttr = new ResourceNodeAttribute(model.getDataFlowGraph().getResouceNode(res)); + Object resource = graph.insertVertex( + dataFlowLayer, null, resNodeAttr, + /*coordinate*/20, 20, + /* scale */80, 30, + resNodeAttr.getDefaultStyle()); + resources.put(res, resource); + } + + // add input, output and reference edges + for (Channel ch: model.getChannels()) { + DataTransferChannel channel = (DataTransferChannel) ch; + // input edge + for (ResourcePath srcRes: channel.getInputResources()) { + graph.insertEdge(dataFlowLayer, null, new SrcDstAttribute(srcRes, channel), resources.get(srcRes), channelsIn.get(channel), "movable=false;strokeColor=#FF0000"); + } + // output edge + for (ResourcePath dstRes: channel.getOutputResources()) { + graph.insertEdge(dataFlowLayer, null, new SrcDstAttribute(channel, dstRes), channelsOut.get(channel), resources.get(dstRes), "movable=false;strokeColor=#FF0000"); + } + // reference edges + for (ResourcePath refRes: channel.getReferenceResources()) { + graph.insertEdge(dataFlowLayer, null, null, resources.get(refRes), channelsIn.get(channel), "dashed=true;movable=false;strokeColor=#FF0000"); + } + } + + for (Channel ioChannel: model.getIOChannels()) { + if (channelsOut.get(ioChannel) == null) { + Object channel = graph.insertVertex(nodeLayer, null, ioChannel.getChannelName(), 150, 20, 30, 30); // insert an I/O channel as a vertex + mxCell port_out = new mxCell(null, geo2, "shape=ellipse;perimter=ellipsePerimeter"); + port_out.setVertex(true); + graph.addCell(port_out, channel); // insert the output port of a channel + channelsOut.put((DataTransferChannel) ioChannel, port_out); + + for (ResourcePath outRes: ((DataTransferChannel) ioChannel).getOutputResources()) { + graph.insertEdge(dataFlowLayer, null, null, port_out, resources.get(outRes), "movable=false;strokeColor=#FF0000"); + } + + } + } + } finally { + graph.getModel().endUpdate(); + } + + bReflectingArchitectureModel = false; + return graph; + } + + /************************************************************* + * + */ + public void addResourcePath(ResourcePath res) { + getModel().addResourcePath(res); + graph.getModel().beginUpdate(); + mxCell root = (mxCell) graph.getDefaultParent(); + mxCell layer = (mxCell) root.getChildAt(NODE_LAYER); + try { + graph.insertVertex(layer, null, res.getResourceName(), 20, 20, 80, 30, + "shape=ellipse;perimeter=ellipsePerimeter"); // insert a resource as a vertex + } finally { + graph.getModel().endUpdate(); + } + } + + /************************************************************* + * + */ + public void addChannel(DataTransferChannel channelGen) { + getModel().addChannel(channelGen); + graph.getModel().beginUpdate(); + mxCell root = (mxCell) graph.getDefaultParent(); + mxCell layer = (mxCell) root.getChildAt(DATA_FLOW_LAYER); + try { + mxGeometry geo1 = new mxGeometry(0, 0.5, PORT_DIAMETER, PORT_DIAMETER); + geo1.setOffset(new mxPoint(-PORT_RADIUS, -PORT_RADIUS)); + geo1.setRelative(true); + + mxGeometry geo2 = new mxGeometry(1.0, 0.5, PORT_DIAMETER, PORT_DIAMETER); + geo2.setOffset(new mxPoint(-PORT_RADIUS, -PORT_RADIUS)); + geo2.setRelative(true); + + Object channel = graph.insertVertex(layer, null, channelGen.getChannelName(), 150, 20, 30, 30); // insert a channel as a vertex + mxCell port_in = new mxCell(null, geo1, "shape=ellipse;perimter=ellipsePerimeter"); + port_in.setVertex(true); + graph.addCell(port_in, channel); // insert the input port of a channel + mxCell port_out = new mxCell(null, geo2, "shape=ellipse;perimter=ellipsePerimeter"); + port_out.setVertex(true); + graph.addCell(port_out, channel); // insert the output port of a channel + } finally { + graph.getModel().endUpdate(); + } + } + + /************************************************************* + * + */ + public void addIOChannel(DataTransferChannel ioChannelGen) { + getModel().addIOChannel(ioChannelGen); + graph.getModel().beginUpdate(); + mxCell root = (mxCell) graph.getDefaultParent(); + mxCell layer = (mxCell) root.getChildAt(NODE_LAYER); + try { + mxGeometry geo2 = new mxGeometry(1.0, 0.5, PORT_DIAMETER, PORT_DIAMETER); + geo2.setOffset(new mxPoint(-PORT_RADIUS, -PORT_RADIUS)); + geo2.setRelative(true); + + Object channel = graph.insertVertex(layer, null, ioChannelGen.getChannelName(), 150, 20, 30, 30); // insert an I/O channel as a vertex + mxCell port_out = new mxCell(null, geo2, "shape=ellipse;perimter=ellipsePerimeter"); + port_out.setVertex(true); + graph.addCell(port_out, channel); // insert the output port of a channel + } finally { + graph.getModel().endUpdate(); + } + } + + public void addFormulaChannel(FormulaChannel formulaChannelGen) { + getModel().addChannel(formulaChannelGen); + graph.getModel().beginUpdate(); + mxCell root = (mxCell) graph.getDefaultParent(); + mxCell layer = (mxCell) root.getChildAt(DATA_FLOW_LAYER); + try { + mxGeometry geo1 = new mxGeometry(0, 0.5, PORT_DIAMETER, PORT_DIAMETER); + geo1.setOffset(new mxPoint(-PORT_RADIUS, -PORT_RADIUS)); + geo1.setRelative(true); + + mxGeometry geo2 = new mxGeometry(1.0, 0.5, PORT_DIAMETER, PORT_DIAMETER); + geo2.setOffset(new mxPoint(-PORT_RADIUS, -PORT_RADIUS)); + geo2.setRelative(true); + + Object channel = graph.insertVertex(layer, null, formulaChannelGen.getChannelName(), 150, 20, 30, 30); // insert a channel as a vertex + mxCell port_in = new mxCell(null, geo1, "shape=ellipse;perimter=ellipsePerimeter"); + port_in.setVertex(true); + graph.addCell(port_in, channel); // insert the input port of a channel + mxCell port_out = new mxCell(null, geo2, "shape=ellipse;perimter=ellipsePerimeter"); + port_out.setVertex(true); + graph.addCell(port_out, channel); // insert the output port of a channel + } finally { + graph.getModel().endUpdate(); + } + } + + public boolean connectEdge(mxCell edge, mxCell src, mxCell dst) { + if (bReflectingArchitectureModel) return false; + DataTransferModel model = getModel(); + + if (!(src.getValue() instanceof String)) return false; + + Channel srcCh = model.getChannel((String) src.getValue()); + if (srcCh == null) { + srcCh = model.getIOChannel((String) src.getValue()); + if (srcCh == null) { + ResourcePath srcRes = model.getResourcePath((String) src.getValue()); + Channel dstCh = model.getChannel((String) dst.getValue()); + if (srcRes == null || dstCh == null) return false; + // resource to channel edge + ChannelMember srcCm = new ChannelMember(srcRes); + ((DataTransferChannel ) dstCh).addChannelMemberAsInput(srcCm); + edge.setValue(new SrcDstAttribute(srcRes, dstCh)); + return true; + } + } + ResourcePath dstRes = model.getResourcePath((String) dst.getValue()); + if (dstRes == null) return false; + // channel to resource edge + ChannelMember dstCm = new ChannelMember(dstRes); + ((DataTransferChannel) srcCh).addChannelMemberAsOutput(dstCm); + edge.setValue(new SrcDstAttribute(srcCh, dstRes)); + return true; + } + + /************************************************************* + * + */ + public void delete() { + for (Object obj: graph.getSelectionCells()) { + mxCell cell = (mxCell) obj; + if (cell.isEdge()) { + String srcName = (String) cell.getSource().getValue(); + String dstName = (String) cell.getTarget().getValue(); + if (model.getResourcePath(srcName) != null) { + // resource to channel edge + Channel ch = model.getChannel(dstName); + ch.removeChannelMember(model.getResourcePath(srcName)); + } else if (model.getResourcePath(dstName) != null) { + // channel to resource edge + Channel ch = model.getChannel(srcName); + if (ch == null) { + ch = model.getIOChannel(srcName); + } + ch.removeChannelMember(model.getResourcePath(dstName)); + } + } else if (cell.isVertex()) { + String name = (String) cell.getValue(); + if (model.getChannel(name) != null) { + model.removeChannel(name); + } else if (model.getIOChannel(name) != null) { + model.removeIOChannel(name); + } else if (model.getResourcePath(name) != null) { + model.removeResourcePath(name); + } + } + } + graph.removeCells(graph.getSelectionCells()); + } + + /************************************************************* + * + */ + public void setChannelCode(DataTransferChannel ch, String code) { + ch.setSourceText(code); + TokenStream stream = new TokenStream(); + Parser parser = new Parser(stream); + + for (String line: code.split("\n")) { + stream.addLine(line); + } + try { + DataTransferChannel ch2 = parser.parseChannel(getModel()); + for (ChannelMember chm2: ch2.getInputChannelMembers()) { + for (ChannelMember chm: ch.getInputChannelMembers()) { + if (chm2.getResource() == chm.getResource()) { + chm.setStateTransition(chm2.getStateTransition()); + break; + } + } + } + for (ChannelMember chm2: ch2.getOutputChannelMembers()) { + for (ChannelMember chm: ch.getOutputChannelMembers()) { + if (chm2.getResource() == chm.getResource()) { + chm.setStateTransition(chm2.getStateTransition()); + break; + } + } + } + for (ChannelMember chm2: ch2.getReferenceChannelMembers()) { + for (ChannelMember chm: ch.getReferenceChannelMembers()) { + if (chm2.getResource() == chm.getResource()) { + chm.setStateTransition(chm2.getStateTransition()); + break; + } + } + } + } catch (ExpectedRightBracket | ExpectedChannel | ExpectedChannelName | ExpectedLeftCurlyBracket + | ExpectedInOrOutOrRefKeyword | ExpectedStateTransition | ExpectedEquals | ExpectedRHSExpression + | WrongLHSExpression | WrongRHSExpression | ExpectedAssignment | WrongJsonExpression | ExpectedColon e) { + e.printStackTrace(); + } + } +} diff --git a/AlgebraicDataflowArchitectureModel/src/application/editor/stages/PushPullSelectionCellEditor.java b/AlgebraicDataflowArchitectureModel/src/application/editor/stages/PushPullSelectionCellEditor.java new file mode 100644 index 0000000..67611b4 --- /dev/null +++ b/AlgebraicDataflowArchitectureModel/src/application/editor/stages/PushPullSelectionCellEditor.java @@ -0,0 +1,168 @@ +package application.editor.stages; + +import java.awt.Rectangle; +import java.util.EventObject; +import java.util.List; +import java.util.logging.Level; + +import javax.swing.BorderFactory; +import javax.swing.JComboBox; + +import com.mxgraph.model.mxIGraphModel; +import com.mxgraph.swing.mxGraphComponent; +import com.mxgraph.util.mxConstants; +import com.mxgraph.util.mxUtils; +import com.mxgraph.view.mxCellState; + +import application.ApplicationWindow; +import application.editor.FlowCellEditor; +import models.dataFlowModel.PushPullAttribute; +import models.dataFlowModel.PushPullValue; + +/************************************************************* + * + */ +public class PushPullSelectionCellEditor extends FlowCellEditor { + public int DEFAULT_MIN_WIDTH = 70; + public int DEFAULT_MIN_HEIGHT = 30; + public double DEFAULT_MINIMUM_EDITOR_SCALE = 1; + + protected double minimumEditorScale = DEFAULT_MINIMUM_EDITOR_SCALE; + protected int minimumWidth = DEFAULT_MIN_WIDTH; + protected int minimumHeight = DEFAULT_MIN_HEIGHT; + + private EventObject trigger; + private JComboBox comboBox; + + /************************************************************* + * [ *constructor ] + /************************************************************* + * @param stage + * @param graphComponent + */ + public PushPullSelectionCellEditor(PushPullSelectionStage stage, mxGraphComponent graphComponent) { + super(stage, graphComponent); + } + + /************************************************************* + * + * @param cellObj + * @param eventObj + */ + @Override + public void startEditing(Object cellObj, EventObject eventObj) { + if (editingCell != null) { + stopEditing(true); + } + + if (graphComponent.getGraph().getModel().isEdge(cellObj)) { + mxCellState state = graphComponent.getGraph().getView().getState(cellObj); + if (state != null && state.getLabel() != null && !state.getLabel().equals("")) { + editingCell = cellObj; + trigger = eventObj; + + double scale = Math.max(minimumEditorScale, graphComponent.getGraph().getView().getScale()); + Object value = graphComponent.getGraph().getModel().getValue(cellObj); + if (value != null && value instanceof PushPullAttribute) { + PushPullAttribute attr = (PushPullAttribute) value; + comboBox = new JComboBox<>(attr.getOptionStrings()); + comboBox.setBorder(BorderFactory.createEmptyBorder()); + comboBox.setOpaque(false); + comboBox.setBounds(getEditorBounds(state, scale)); + comboBox.setVisible(true); + graphComponent.getGraphControl().add(comboBox, 0); + comboBox.updateUI(); + } + } + } + } + + /************************************************************* + * + * @param cancel + */ + @Override + public void stopEditing(boolean cancel) { + if (editingCell != null) { + comboBox.transferFocusUpCycle(); + Object cell = editingCell; + editingCell = null; + if (!cancel) { + EventObject trig = trigger; + trigger = null; + Object value = graphComponent.getGraph().getModel().getValue(cell); + if (value != null && value instanceof PushPullAttribute) { + PushPullAttribute attr = (PushPullAttribute) value; + List options = attr.getOptions(); + PushPullValue selected = null; + for (PushPullValue option: options) { + if (option.toString().equals(getCurrentValue())) { + selected = option; + break; + } + } + if (selected != null) { + options.remove(selected); + options.add(0, selected); + ApplicationWindow.logger.log(Level.INFO, selected.name()); // log output + } + graphComponent.labelChanged(cell, attr, trig); + } + } else { + mxCellState state = graphComponent.getGraph().getView().getState(cell); + graphComponent.redraw(state); + } + + if (comboBox.getParent() != null) { + comboBox.setVisible(false); + comboBox.getParent().remove(comboBox); + } + + graphComponent.requestFocusInWindow(); + } + } + + public String getCurrentValue() { + return (String) comboBox.getSelectedItem(); + } + + /** + * Returns the bounds to be used for the editor. + */ + public Rectangle getEditorBounds(mxCellState state, double scale) { + mxIGraphModel model = state.getView().getGraph().getModel(); + Rectangle bounds = null; + + bounds = state.getLabelBounds().getRectangle(); + bounds.height += 10; + + // Applies the horizontal and vertical label positions + if (model.isVertex(state.getCell())) { + String horizontal = mxUtils.getString(state.getStyle(), mxConstants.STYLE_LABEL_POSITION, mxConstants.ALIGN_CENTER); + + if (horizontal.equals(mxConstants.ALIGN_LEFT)) { + bounds.x -= state.getWidth(); + } else if (horizontal.equals(mxConstants.ALIGN_RIGHT)) { + bounds.x += state.getWidth(); + } + + String vertical = mxUtils.getString(state.getStyle(), + mxConstants.STYLE_VERTICAL_LABEL_POSITION, + mxConstants.ALIGN_MIDDLE); + + if (vertical.equals(mxConstants.ALIGN_TOP)) { + bounds.y -= state.getHeight(); + } else if (vertical.equals(mxConstants.ALIGN_BOTTOM)) { + bounds.y += state.getHeight(); + } + } + + bounds.setSize( + (int) Math.max(bounds.getWidth(), + Math.round(minimumWidth * scale)), + (int) Math.max(bounds.getHeight(), + Math.round(minimumHeight * scale))); + + return bounds; + } +} diff --git a/AlgebraicDataflowArchitectureModel/src/application/editor/stages/PushPullSelectionStage.java b/AlgebraicDataflowArchitectureModel/src/application/editor/stages/PushPullSelectionStage.java new file mode 100644 index 0000000..f77ced3 --- /dev/null +++ b/AlgebraicDataflowArchitectureModel/src/application/editor/stages/PushPullSelectionStage.java @@ -0,0 +1,139 @@ +package application.editor.stages; + +import java.awt.event.MouseListener; +import java.util.ArrayList; +import java.util.List; + +import com.mxgraph.model.mxCell; +import com.mxgraph.model.mxGraphModel; +import com.mxgraph.swing.mxGraphComponent; +import com.mxgraph.util.mxEventObject; +import com.mxgraph.util.mxEventSource.mxIEventListener; +import com.mxgraph.view.mxGraph; + +import algorithms.DataTransferModelAnalyzer; +import application.editor.Editor.SrcDstAttribute; +import application.editor.Editor; +import application.editor.FlowCellEditor; +import application.editor.InEdgeAttribute; +import application.editor.OutEdgeAttribute; +import application.editor.Stage; +import models.Edge; +import models.dataFlowModel.DataFlowEdge; +import models.dataFlowModel.DataFlowGraph; +import models.dataFlowModel.DataTransferChannel; +import models.dataFlowModel.DataTransferModel; +import models.dataFlowModel.PushPullAttribute; +import models.dataFlowModel.ResourceNode; + +public class PushPullSelectionStage extends Stage { + protected DataFlowGraph dataFlowGraph = null; + + public PushPullSelectionStage(mxGraphComponent graphComponent) { + super(graphComponent); + } + + @Override + public boolean canChangeFrom(Stage prevStage) { + if (prevStage instanceof DataFlowModelingStage) { + if (!((DataFlowModelingStage) prevStage).isValid()) return false; + return true; + } + if (prevStage instanceof ControlFlowDelegationStage) return true; + return false; + } + + @Override + public void init(Stage prevStage) { + if (prevStage instanceof DataFlowModelingStage) { + model = ((DataFlowModelingStage) prevStage).getModel(); + dataFlowGraph = analyzeDataTransferModel(graph, model); + showOnlyLayer(DATA_FLOW_LAYER); + } + + if(prevStage instanceof ControlFlowDelegationStage) { + showOnlyLayer(DATA_FLOW_LAYER); + } + } + + @Override + public FlowCellEditor createCellEditor(mxGraphComponent graphComponent) { + return new PushPullSelectionCellEditor(this, graphComponent); + } + + @Override + public mxIEventListener createChangeEventListener(Editor editor) { + return new mxIEventListener() { + public void invoke(Object sender, mxEventObject evt) { + List terminals = new ArrayList<>(); + mxCell cell = null; + for (Object change: ((List) evt.getProperties().get("changes"))) { + if (change instanceof mxGraphModel.mxTerminalChange) { + mxGraphModel.mxTerminalChange terminalChange = (mxGraphModel.mxTerminalChange) change; + cell = (mxCell) terminalChange.getCell(); + mxCell terminal = (mxCell) terminalChange.getTerminal(); + terminals.add(terminal); + } + } + if (terminals.size() == 2) { + // cancel connect + graph.removeCells(new mxCell[] {cell}); + graph.clearSelection(); + } + } + }; + } + + @Override + public MouseListener createMouseEventListener(Editor editor) { + return null; + } + + + public DataFlowGraph getDataFlowGraph() { + return dataFlowGraph; + } + + public DataFlowGraph analyzeDataTransferModel(mxGraph graph, DataTransferModel model) { + DataFlowGraph flowGraph = DataTransferModelAnalyzer.createDataFlowGraphWithStateStoringAttribute(model); + DataFlowGraph dataFlowGraph = DataTransferModelAnalyzer.annotateWithSelectableDataTransferAttiribute(flowGraph); + updateEdgeAttiributes(graph, dataFlowGraph); + return dataFlowGraph; + } + + private void updateEdgeAttiributes(mxGraph graph, DataFlowGraph dataFlowGraph) { + mxCell root = (mxCell) graph.getDefaultParent(); + mxCell layer = (mxCell) root.getChildAt(DATA_FLOW_LAYER); + + graph.getModel().beginUpdate(); + try { + // update attributes of input and output edges + for (Edge e : dataFlowGraph.getEdges()) { + if (e instanceof DataFlowEdge) { + DataFlowEdge dataFlow = (DataFlowEdge) e; + DataTransferChannel channel = dataFlow.getChannel(); + ResourceNode srcRes = (ResourceNode) dataFlow.getSource(); + ResourceNode dstRes = (ResourceNode) dataFlow.getDestination(); + for (Object edge: graph.getChildEdges(layer)) { + mxCell edgeCell = (mxCell) edge; + if (edgeCell.getValue() instanceof SrcDstAttribute) { + SrcDstAttribute edgeAttr = (SrcDstAttribute) edgeCell.getValue(); + if (edgeAttr.getSrouce() == srcRes.getResource() && edgeAttr.getDestination() == channel) { + // input edge + edgeCell.setValue(new InEdgeAttribute((PushPullAttribute) dataFlow.getAttribute(), srcRes)); + break; + } else if (edgeAttr.getSrouce() == channel && edgeAttr.getDestination() == dstRes.getResource()) { + // output edge + edgeCell.setValue(new OutEdgeAttribute(edgeAttr, dstRes)); + break; + } + } + } + } + } + } finally { + graph.getModel().endUpdate(); + } + graph.refresh(); + } +} diff --git a/AlgebraicDataflowArchitectureModel/src/application/layouts/DAGLayout.java b/AlgebraicDataflowArchitectureModel/src/application/layouts/DAGLayout.java new file mode 100644 index 0000000..ed9181a --- /dev/null +++ b/AlgebraicDataflowArchitectureModel/src/application/layouts/DAGLayout.java @@ -0,0 +1,154 @@ +package application.layouts; + +import java.util.ArrayList; +import java.util.Arrays; +import java.util.Collections; +import java.util.List; + +import com.mxgraph.layout.mxGraphLayout; +import com.mxgraph.model.mxCell; +import com.mxgraph.model.mxGeometry; +import com.mxgraph.model.mxICell; +import com.mxgraph.model.mxIGraphModel; +import com.mxgraph.util.mxRectangle; +import com.mxgraph.view.mxCellState; +import com.mxgraph.view.mxGraph; +import com.mxgraph.view.mxGraphView; + +import models.controlFlowModel.ObjectNodeAttribute; +import models.dataConstraintModel.Channel; +import models.dataConstraintModel.ResourcePath; +import models.dataFlowModel.ResourceNodeAttribute; + +public class DAGLayout extends mxGraphLayout { + + public DAGLayout(mxGraph graph) { + super(graph); + } + + @Override + public void execute(Object parent) { + mxIGraphModel model = graph.getModel(); + + model.beginUpdate(); + try { + List> map = new ArrayList>(); + List moved = new ArrayList<>(); + + for (int i = 0; i < model.getChildCount(parent); i++) { + + mxCell cell = (mxCell) model.getChildAt(parent, i); + + if (model.isVertex(cell)) { + mxGraphView view = graph.getView(); + mxCellState state = view.getState(cell); + + if (!"ellipse".equals(state.getStyle().get("shape")) && (cell.getEdgeCount() == 1) && !"true".equals(state.getStyle().get("dashed"))) { + List newline = new ArrayList(); + map.add(newline); + lines(map, cell); + } + } + } + + sort(map, 0, false); + + // layout + int count; + int skip = 0; + mxGraphView view = graph.getView(); + for (int i = 0; i < map.size(); i++) { + count = 0; + for (int j = 0; j < map.get(i).size(); j++) { + mxGeometry geom = (mxGeometry) map.get(i).get(j).getGeometry().clone(); + mxCellState state = view.getState(map.get(i).get(j)); + + + if (checkmoved(moved, map.get(i).get(j))) { + if ("ellipse".equals(state.getStyle().get("shape"))){ + geom.setX(50 + j*200); + } else { + geom.setX(100 + j*200); + } + geom.setY(100 + (i-skip)*100); + model.setGeometry(map.get(i).get(j), geom); + moved.add(map.get(i).get(j).getId()); + } else if (geom.getX() < 100 + j*150) { + if ("ellipse".equals(state.getStyle().get("shape"))){ + geom.setX(50 + j*200); + } else { + geom.setX(100 + j*200); + } + geom.setY(100 + (i-skip)*100); + model.setGeometry(map.get(i).get(j), geom); + } else { + count++; + } + } + if (count >= map.get(i).size())skip++; + } + + } finally { + model.endUpdate(); + } + } + + + public void lines(List> mapping, mxCell next) { + mapping.get(mapping.size()-1).add(next); + int tagcount = 0; + mxCell edge; + mxGraphView view = graph.getView(); + for (int i = 0; i < next.getEdgeCount(); i++) { + edge = (mxCell) next.getEdgeAt(i); + mxCellState state = view.getState(edge); + if (next != (mxCell) edge.getTarget() && ((mxCell) edge.getTarget() != null) && !"true".equals(state.getStyle().get("dashed"))) { + tagcount++; + if (tagcount > 1) { + List newline = new ArrayList(mapping.get(mapping.size()-1)); + while (newline.get(newline.size()-1).getId() != next.getId()) { + newline.remove(newline.size()-1); + } + mapping.add(newline); + lines(mapping, (mxCell) edge.getTarget()); + + } else { + lines(mapping, (mxCell) edge.getTarget()); + } + } + } + } + + public boolean checkmoved(List list, mxCell cell) { + for (int i = 0; i < list.size(); i++) { + if (list.get(i).equals(cell.getId()))return false; + } + return true; + } + + public void sort(List> map, int n, boolean check) { + int msize = -1; + int mnum = -1; + if (check) { + for (int i = n; i < map.size(); i++) { + if (map.get(i).size() > msize && (map.get(n-1).get(0).getId().equals(map.get(i).get(0).getId()))) { + mnum = i; + } + } + } else { + for (int i = n; i < map.size(); i++) { + if (map.get(i).size() > msize) { + mnum = i; + } + } + } + if (mnum >= 0) { + Collections.swap(map, n, mnum); + sort(map, n+1, true); + } else if(n < map.size()) { + sort(map, n+1, false); + } + } + + +} \ No newline at end of file diff --git a/AlgebraicDataflowArchitectureModel/src/application/views/NavigationWindow.java b/AlgebraicDataflowArchitectureModel/src/application/views/NavigationWindow.java new file mode 100644 index 0000000..9a7d700 --- /dev/null +++ b/AlgebraicDataflowArchitectureModel/src/application/views/NavigationWindow.java @@ -0,0 +1,160 @@ +package application.views; + +import java.awt.Container; +import java.awt.Point; +import java.awt.event.ActionEvent; +import java.awt.event.ActionListener; +import java.util.logging.Level; + +import javax.swing.ButtonGroup; +import javax.swing.JDialog; +import javax.swing.JToggleButton; + +import application.ApplicationLanguage; +import application.ApplicationWindow; +import application.editor.Editor; +import application.editor.IStageChangeListener; +import application.editor.Stage; +import application.editor.stages.ControlFlowDelegationStage; +import application.editor.stages.DataFlowModelingStage; +import application.editor.stages.PushPullSelectionStage; + +public class NavigationWindow extends JDialog implements IStageChangeListener { + private String title = "Navigation"; + private Editor editor; + private JToggleButton dataFlowModelingButton; + private JToggleButton pushPullSelectionButton; + private JToggleButton controlFlowDelegationButton; + private boolean forbidReentry = false; + + public NavigationWindow(ApplicationWindow owner, Editor editor) { + super(owner); + setTitle(title); + setDefaultCloseOperation(HIDE_ON_CLOSE); + this.editor = editor; + Container panel = getContentPane(); + panel.setLayout(new java.awt.GridLayout(3, 1)); + dataFlowModelingButton = new JToggleButton(ApplicationLanguage.getInstance().getOptionByPropName("dataFlowModeling")); + pushPullSelectionButton = new JToggleButton(ApplicationLanguage.getInstance().getOptionByPropName("pushpullSelection")); + controlFlowDelegationButton = new JToggleButton(ApplicationLanguage.getInstance().getOptionByPropName("pushpullExtension")); + dataFlowModelingButton.addActionListener(new DataFlowModelingButtonListener()); + pushPullSelectionButton.addActionListener(new PushPullSelectionButtonListener()); + controlFlowDelegationButton.addActionListener(new ControlFlowDelegationButtonListener()); + ButtonGroup group = new ButtonGroup(); + group.add(dataFlowModelingButton); + group.add(pushPullSelectionButton); + group.add(controlFlowDelegationButton); + panel.add(dataFlowModelingButton); + panel.add(pushPullSelectionButton); + panel.add(controlFlowDelegationButton); + controlFlowDelegationButton.setEnabled(false); + pushPullSelectionButton.setEnabled(false); + dataFlowModelingButton.setSelected(true); + pack(); + + Point location = new Point(owner.getX() + owner.getWidth() - this.getWidth(), owner.getY() + owner.getHeight() - this.getHeight()); + setLocation(location); + + setResizable(false); + } + + @Override + public void stageChanged(Stage newStage) { + if (forbidReentry) return; + ApplicationWindow.logger.log(Level.INFO, newStage.toString()); + if (newStage instanceof DataFlowModelingStage) { + dataFlowModelingButton.setSelected(true); + if (editor.canChange(Editor.STAGE_PUSH_PULL_SELECTION)) { + pushPullSelectionButton.setEnabled(true); + } else { + pushPullSelectionButton.setEnabled(false); + } + if (editor.canChange(Editor.STAGE_CONTROL_FLOW_DELEGATION)) { + controlFlowDelegationButton.setEnabled(true); + } else { + controlFlowDelegationButton.setEnabled(false); + } + } else if (newStage instanceof PushPullSelectionStage) { + pushPullSelectionButton.setSelected(true); + if (editor.canChange(Editor.STAGE_DATA_FLOW_MODELING)) { + dataFlowModelingButton.setEnabled(true); + } else { + dataFlowModelingButton.setEnabled(false); + } + if (editor.canChange(Editor.STAGE_CONTROL_FLOW_DELEGATION)) { + controlFlowDelegationButton.setEnabled(true); + } else { + controlFlowDelegationButton.setEnabled(false); + } + } else if (newStage instanceof ControlFlowDelegationStage) { + controlFlowDelegationButton.setSelected(true); + if (editor.canChange(Editor.STAGE_DATA_FLOW_MODELING)) { + dataFlowModelingButton.setEnabled(true); + } else { + dataFlowModelingButton.setEnabled(false); + } + if (editor.canChange(Editor.STAGE_PUSH_PULL_SELECTION)) { + pushPullSelectionButton.setEnabled(true); + } else { + pushPullSelectionButton.setEnabled(false); + } + } + } + + private class DataFlowModelingButtonListener implements ActionListener { + @Override + public void actionPerformed(ActionEvent e) { + forbidReentry = true; + editor.changeStage(Editor.STAGE_DATA_FLOW_MODELING); + forbidReentry = false; + if (editor.canChange(Editor.STAGE_PUSH_PULL_SELECTION)) { + pushPullSelectionButton.setEnabled(true); + } else { + pushPullSelectionButton.setEnabled(false); + } + if (editor.canChange(Editor.STAGE_CONTROL_FLOW_DELEGATION)) { + controlFlowDelegationButton.setEnabled(true); + } else { + controlFlowDelegationButton.setEnabled(false); + } + } + } + + private class PushPullSelectionButtonListener implements ActionListener { + @Override + public void actionPerformed(ActionEvent e) { + forbidReentry = true; + editor.changeStage(Editor.STAGE_PUSH_PULL_SELECTION); + forbidReentry = false; + if (editor.canChange(Editor.STAGE_DATA_FLOW_MODELING)) { + dataFlowModelingButton.setEnabled(true); + } else { + dataFlowModelingButton.setEnabled(false); + } + if (editor.canChange(Editor.STAGE_CONTROL_FLOW_DELEGATION)) { + controlFlowDelegationButton.setEnabled(true); + } else { + controlFlowDelegationButton.setEnabled(false); + } + } + } + + private class ControlFlowDelegationButtonListener implements ActionListener { + @Override + public void actionPerformed(ActionEvent e) { + forbidReentry = true; + editor.changeStage(Editor.STAGE_CONTROL_FLOW_DELEGATION); + forbidReentry = false; + if (editor.canChange(Editor.STAGE_DATA_FLOW_MODELING)) { + dataFlowModelingButton.setEnabled(true); + } else { + dataFlowModelingButton.setEnabled(false); + } + if (editor.canChange(Editor.STAGE_PUSH_PULL_SELECTION)) { + pushPullSelectionButton.setEnabled(true); + } else { + pushPullSelectionButton.setEnabled(false); + } + } + } +} diff --git a/AlgebraicDataflowArchitectureModel/src/application/views/PopupMenuBase.java b/AlgebraicDataflowArchitectureModel/src/application/views/PopupMenuBase.java new file mode 100644 index 0000000..625774c --- /dev/null +++ b/AlgebraicDataflowArchitectureModel/src/application/views/PopupMenuBase.java @@ -0,0 +1,47 @@ +package application.views; + +import java.awt.Component; + +import javax.swing.JMenuItem; +import javax.swing.JPopupMenu; + +import com.mxgraph.model.mxCell; +import com.mxgraph.swing.mxGraphComponent; + +import application.actions.AbstractPopupAction; + +/************************************************************* + * + */ +public abstract class PopupMenuBase { + protected JPopupMenu popupMenu = null; + protected mxGraphComponent graphComponent = null; + + /************************************************************* + * [ *constructor ] + /************************************************************* + */ + public PopupMenuBase(final mxGraphComponent graphComponent) { + this.graphComponent = graphComponent; + this.popupMenu = new JPopupMenu(); + } + + /************************************************************* + * [ *public ] + /************************************************************* + * + */ + public void show(int x, int y) { + popupMenu.show(graphComponent, x, y); + } + + /************************************************************* + * [ *protected ] + /************************************************************* + * + */ + protected void addMenuItem(JMenuItem menuItem) { + popupMenu.add(menuItem); + } + +} diff --git a/AlgebraicDataflowArchitectureModel/src/application/views/controlFlowDelegation/ControlFlowDelegationStagePopupMenu.java b/AlgebraicDataflowArchitectureModel/src/application/views/controlFlowDelegation/ControlFlowDelegationStagePopupMenu.java new file mode 100644 index 0000000..dc088bc --- /dev/null +++ b/AlgebraicDataflowArchitectureModel/src/application/views/controlFlowDelegation/ControlFlowDelegationStagePopupMenu.java @@ -0,0 +1,120 @@ +package application.views.controlFlowDelegation; + +import java.awt.Component; + +import javax.swing.JMenuItem; + +import com.mxgraph.model.mxCell; +import com.mxgraph.swing.mxGraphComponent; + +import application.actions.AbstractPopupAction; +import application.actions.ChangeCallOrderAction; +import application.actions.ShowDependentableMediatorAction; +import application.actions.InsertStatelessObjectAction; +import application.editor.stages.ControlFlowDelegationStage; +import application.views.PopupMenuBase; +import models.controlFlowModel.CallEdgeAttribute; +import models.dataFlowModel.PushPullValue; + +/************************************************************* + * + */ +public class ControlFlowDelegationStagePopupMenu extends PopupMenuBase { + private ControlFlowDelegationStage stage = null; + private mxCell selectedCell = null; + + /************************************************************* + * [ *constructor ] + /************************************************************* + */ + public ControlFlowDelegationStagePopupMenu(final ControlFlowDelegationStage stage, mxGraphComponent graphComponent) { + super(graphComponent); + this.stage = stage; + + addMenuItem(new JMenuItem(new InsertStatelessObjectAction(stage, graphComponent, selectedCell))); + addMenuItem(new JMenuItem(new ChangeCallOrderAction(graphComponent, selectedCell))); + addMenuItem(new JMenuItem(new ShowDependentableMediatorAction(stage, graphComponent, selectedCell))); + } + + /************************************************************* + * [ *public ] + /************************************************************* + * + */ + @Override + public void show(int x, int y) { + if( graphComponent.getCellAt(x, y) instanceof mxCell ) { + selectedCell =(mxCell) graphComponent.getCellAt(x, y); + } + else { + selectedCell = null; + } + + if(this.selectedCell == null) return; + + notifyCellCached(selectedCell); + stage.setCellOnAnyEvent(selectedCell); + + boolean isEnable = (graphComponent.getCellAt(x, y) != null) + ? true + : false; + + setEnableMenuItems(isEnable); + + super.show(x, y); + } + + /************************************************************* + * [ *private ] + /************************************************************* + */ + private void notifyCellCached(final mxCell cell) { + if(cell == null) return; + + for(Component component : popupMenu.getComponents()) { + JMenuItem menuItem = null; + if(component instanceof JMenuItem) menuItem = (JMenuItem)component; + else return; + + AbstractPopupAction action = null; + if(menuItem.getAction() instanceof AbstractPopupAction) { + action = (AbstractPopupAction)menuItem.getAction(); + } + else return; + + action.updateTargetCell(cell); + } + } + + /************************************************************* + * + */ + private void setEnableMenuItems(final boolean isEnable) { + if(this.selectedCell == null) return; + + for(Component component : popupMenu.getComponents()) { + component.setEnabled(isEnable); + + // pull only + if(!isSelectedPullCallEdge(selectedCell)) { + JMenuItem menuItem = null; + if(component instanceof JMenuItem) menuItem = (JMenuItem)component; + + if(menuItem.getAction() instanceof ShowDependentableMediatorAction) { + component.setEnabled(false); + continue; + } + } + + } + } + + /************************************************************* + * + */ + private boolean isSelectedPullCallEdge(final mxCell selectedCell) { + CallEdgeAttribute callEdgeAttr = (CallEdgeAttribute)selectedCell.getValue(); + return callEdgeAttr.getSelectedOption().equals(PushPullValue.PULL); + } + +} diff --git a/AlgebraicDataflowArchitectureModel/src/application/views/controlFlowDelegation/FlowLayerValue.java b/AlgebraicDataflowArchitectureModel/src/application/views/controlFlowDelegation/FlowLayerValue.java new file mode 100644 index 0000000..0c9317c --- /dev/null +++ b/AlgebraicDataflowArchitectureModel/src/application/views/controlFlowDelegation/FlowLayerValue.java @@ -0,0 +1,10 @@ +package application.views.controlFlowDelegation; + +/************************************************************* + * + */ +public enum FlowLayerValue { + DATA_FLOW, + PUSH_FLOW, + PULL_FLOW +} diff --git a/AlgebraicDataflowArchitectureModel/src/application/views/controlFlowDelegation/FlowLayerWindow.java b/AlgebraicDataflowArchitectureModel/src/application/views/controlFlowDelegation/FlowLayerWindow.java new file mode 100644 index 0000000..18f9c69 --- /dev/null +++ b/AlgebraicDataflowArchitectureModel/src/application/views/controlFlowDelegation/FlowLayerWindow.java @@ -0,0 +1,106 @@ +package application.views.controlFlowDelegation; + +import java.awt.Container; +import java.awt.GridLayout; +import java.awt.event.ActionEvent; +import java.awt.event.ActionListener; + +import javax.swing.JCheckBox; +import javax.swing.JDialog; + +import application.ApplicationWindow; +import application.editor.Editor; +import application.editor.IStageChangeListener; +import application.editor.Stage; +import application.editor.stages.ControlFlowDelegationStage; + +/************************************************************* + * Window to change visibility of layers for the control-flow-modeling. + */ +public class FlowLayerWindow extends JDialog implements IStageChangeListener { + private String title = "Flow Layer"; + private JCheckBox dataFlowCheckBox = null; + private JCheckBox pushFlowCheckBox = null; + private JCheckBox pullFlowCheckBox = null; + + private ControlFlowDelegationStage stage = null; + + /************************************************************* + * [ *constructor ] + /************************************************************* + * + */ + public FlowLayerWindow(final ApplicationWindow owner) { + super(owner); + + setTitle(title); + setDefaultCloseOperation(HIDE_ON_CLOSE); + + stage = Editor.STAGE_CONTROL_FLOW_DELEGATION; + + // initialize buttons + dataFlowCheckBox = new JCheckBox("Data-Flow", false); + pushFlowCheckBox = new JCheckBox("Push-Flow", true); + pullFlowCheckBox = new JCheckBox("Pull-Flow", true); + + // each add handler + dataFlowCheckBox.addActionListener(new ActionListener() { + @Override + public void actionPerformed(ActionEvent e) { + stage.setEnabledForLayer(Stage.DATA_FLOW_LAYER, dataFlowCheckBox.isSelected()); + }}); + + pushFlowCheckBox.addActionListener(new ActionListener() { + @Override + public void actionPerformed(ActionEvent e) { + stage.setEnabledForLayer(Stage.PUSH_FLOW_LAYER, pushFlowCheckBox.isSelected()); + }}); + + pullFlowCheckBox.addActionListener(new ActionListener() { + @Override + public void actionPerformed(ActionEvent e) { + stage.setEnabledForLayer(Stage.PULL_FLOW_LAYER, pullFlowCheckBox.isSelected()); + }}); + + dataFlowCheckBox.setEnabled(false); + pushFlowCheckBox.setEnabled(false); + pullFlowCheckBox.setEnabled(false); + + // initialize panel + Container panel = getContentPane(); + panel.setLayout(new GridLayout(/*low*/3, /*col*/1)); + panel.add(dataFlowCheckBox); + panel.add(pushFlowCheckBox); + panel.add(pullFlowCheckBox); + + pack(); + setResizable(false); + } + + /************************************************************* + * [ *public ] + /************************************************************* + * + */ + @Override + public void stageChanged(Stage newStage) { + if((newStage instanceof ControlFlowDelegationStage)) { + + dataFlowCheckBox.setEnabled(true); + pushFlowCheckBox.setEnabled(true); + pullFlowCheckBox.setEnabled(true); + + newStage.setEnabledForLayer(Stage.PUSH_FLOW_LAYER, pushFlowCheckBox.isSelected()); + newStage.setEnabledForLayer(Stage.PULL_FLOW_LAYER, pullFlowCheckBox.isSelected()); + } + else { + dataFlowCheckBox.setEnabled(false); + pushFlowCheckBox.setEnabled(false); + pullFlowCheckBox.setEnabled(false); + + newStage.setEnabledForLayer(Stage.PUSH_FLOW_LAYER, false); + newStage.setEnabledForLayer(Stage.PULL_FLOW_LAYER, false); + } + } +} + diff --git a/AlgebraicDataflowArchitectureModel/src/code/ast/ASTNode.java b/AlgebraicDataflowArchitectureModel/src/code/ast/ASTNode.java index 0e250a1..202e700 100644 --- a/AlgebraicDataflowArchitectureModel/src/code/ast/ASTNode.java +++ b/AlgebraicDataflowArchitectureModel/src/code/ast/ASTNode.java @@ -1,6 +1,8 @@ package code.ast; -public abstract class ASTNode { +import java.io.Serializable; + +public abstract class ASTNode implements Serializable{ private ASTNode parent; public ASTNode getParent() { diff --git a/AlgebraicDataflowArchitectureModel/src/code/ast/ImportDeclaration.java b/AlgebraicDataflowArchitectureModel/src/code/ast/ImportDeclaration.java index 9135d68..fdb6309 100644 --- a/AlgebraicDataflowArchitectureModel/src/code/ast/ImportDeclaration.java +++ b/AlgebraicDataflowArchitectureModel/src/code/ast/ImportDeclaration.java @@ -1,6 +1,8 @@ package code.ast; -public class ImportDeclaration { +import java.io.Serializable; + +public class ImportDeclaration implements Serializable { private String name; public ImportDeclaration(String name) { diff --git a/AlgebraicDataflowArchitectureModel/src/code/ast/MethodDeclaration.java b/AlgebraicDataflowArchitectureModel/src/code/ast/MethodDeclaration.java index fc4e104..fad7629 100644 --- a/AlgebraicDataflowArchitectureModel/src/code/ast/MethodDeclaration.java +++ b/AlgebraicDataflowArchitectureModel/src/code/ast/MethodDeclaration.java @@ -21,7 +21,7 @@ this(methodName, false); } - public MethodDeclaration(String methodName,Type returnType) { + public MethodDeclaration(String methodName, Type returnType) { this(methodName, false); this.returnType = returnType; } diff --git a/AlgebraicDataflowArchitectureModel/src/code/ast/TypeDeclaration.java b/AlgebraicDataflowArchitectureModel/src/code/ast/TypeDeclaration.java index 1dc5cf3..0406d59 100644 --- a/AlgebraicDataflowArchitectureModel/src/code/ast/TypeDeclaration.java +++ b/AlgebraicDataflowArchitectureModel/src/code/ast/TypeDeclaration.java @@ -34,6 +34,10 @@ methods.add(method); } + public void removeMethod(MethodDeclaration method) { + methods.remove(method); + } + public List getFields() { return fields; } @@ -41,6 +45,12 @@ public List getMethods() { return methods; } + + public MethodDeclaration createConstructor() { + MethodDeclaration constructor = new MethodDeclaration(typeName, true); + addMethod(constructor); + return constructor; + } @Override public Annotation getAnnotation(String name) { diff --git a/AlgebraicDataflowArchitectureModel/src/code/ast/VariableDeclaration.java b/AlgebraicDataflowArchitectureModel/src/code/ast/VariableDeclaration.java index 6a7b25b..d4f5c86 100644 --- a/AlgebraicDataflowArchitectureModel/src/code/ast/VariableDeclaration.java +++ b/AlgebraicDataflowArchitectureModel/src/code/ast/VariableDeclaration.java @@ -6,7 +6,7 @@ import models.algebra.Type; -public class VariableDeclaration extends ASTNode implements IAnnotatable { +public class VariableDeclaration extends ASTNode implements IAnnotatable{ private Type type; private String variableName; private Map annotations = new HashMap<>(); diff --git a/AlgebraicDataflowArchitectureModel/src/generators/CodeGenerator.java b/AlgebraicDataflowArchitectureModel/src/generators/CodeGenerator.java new file mode 100644 index 0000000..4ccaf6d --- /dev/null +++ b/AlgebraicDataflowArchitectureModel/src/generators/CodeGenerator.java @@ -0,0 +1,370 @@ +package generators; + +import java.util.ArrayList; +import java.util.Arrays; +import java.util.Collection; +import java.util.HashMap; +import java.util.HashSet; +import java.util.List; +import java.util.Map; +import java.util.Set; + +import code.ast.Block; +import code.ast.CompilationUnit; +import code.ast.FieldDeclaration; +import code.ast.MethodDeclaration; +import code.ast.TypeDeclaration; +import code.ast.VariableDeclaration; +import models.Edge; +import models.Node; +import models.algebra.Expression; +import models.algebra.Field; +import models.algebra.Parameter; +import models.algebra.Symbol; +import models.algebra.Term; +import models.algebra.Type; +import models.algebra.Variable; +import models.controlFlowModel.EntryPointObjectNode; +import models.controlFlowModel.ObjectNode; +import models.controlFlowModel.StatefulObjectNode; +import models.dataConstraintModel.Channel; +import models.dataConstraintModel.ChannelMember; +import models.dataConstraintModel.DataConstraintModel; +import models.dataConstraintModel.ResourcePath; +import models.dataFlowModel.DataFlowEdge; +import models.dataFlowModel.DataTransferChannel; +import models.dataFlowModel.DataTransferModel; +import models.dataFlowModel.IFlowGraph; +import models.dataFlowModel.PushPullAttribute; +import models.dataFlowModel.PushPullValue; +import models.dataFlowModel.ResourceNode; +import models.dataFlowModel.DataTransferChannel.IResourceStateAccessor; + +/** + * Common generator for prototypes + * + * @author Nitta + * + */ +public abstract class CodeGenerator { + public static final String fieldOfResourceState = "value"; + public static final String getterOfResourceState = "getValue"; + public static final String updateMethodName = "update"; + private static String mainTypeName = null; + + public static String getMainTypeName() { + return mainTypeName; + } + + public static void setMainTypeName(String mainTypeName) { + CodeGenerator.mainTypeName = mainTypeName; + } + + public static void resetMainTypeName() { + CodeGenerator.mainTypeName = null; + } + + /** + * Generate source codes in specified language from data-flow/control-flow graph. + * + * @param model architecture model + * @param flowGraph data-flow or control-flow graph + * @param langSpec specified language + * @return source codes + */ + public ArrayList generateCode(DataTransferModel model, IFlowGraph flowGraph, ILanguageSpecific langSpec) { + ArrayList codes = new ArrayList<>(); + + // Sort the all components. + ArrayList> components = determineComponentOrder(flowGraph); + + // Add the main component. + if (mainTypeName == null) { + mainTypeName = langSpec.getMainComponentName(); + } + TypeDeclaration mainComponent = langSpec.newTypeDeclaration(mainTypeName); + MethodDeclaration mainConstructor = mainComponent.createConstructor(); + CompilationUnit mainCU = langSpec.newCompilationUnit(mainComponent); + codes.add(mainCU); + + // Generate the other components. + generateCodeFromFlowGraph(model, flowGraph, components, mainComponent, mainConstructor, codes, langSpec); + + return codes; + } + + public abstract void generateCodeFromFlowGraph(DataTransferModel model, IFlowGraph flowGraph, ArrayList> components, + TypeDeclaration mainComponent, MethodDeclaration mainConstructor, ArrayList codes, ILanguageSpecific langSpec); + + private static ArrayList> determineComponentOrder(IFlowGraph graph) { + ArrayList> objects = new ArrayList<>(); + Set> visited = new HashSet<>(); + Map> allNodeSets = graph.getAllNodes(); + for (Set nodeSet: allNodeSets.values()) { + if (!(nodeSet.iterator().next() instanceof EntryPointObjectNode)) { + topologicalSort(allNodeSets, nodeSet, visited, objects); + } + } + return objects; + } + + private static void topologicalSort(Map> allNodeSets, Set curNodeSet, Set> visited, List> orderedList) { + if (visited.contains(curNodeSet)) return; + visited.add(curNodeSet); + // a caller is before the callee + for (Node curNode: curNodeSet) { + for (Edge e: curNode.getInEdges()) { + if (!(e.getSource() instanceof EntryPointObjectNode)) { + if (!(e instanceof DataFlowEdge) || ((PushPullAttribute)((DataFlowEdge) e).getAttribute()).getOptions().get(0) == PushPullValue.PUSH) { + // for a call edge or PUSH data-flow edge + topologicalSort(allNodeSets, allNodeSets.get(e.getSource()), visited, orderedList); + } + } + } + } +// if (curNode instanceof StatefulObjectNode) { +// ResourceNode resNode = ((StatefulObjectNode) curNode).getResource(); +// for (Node n: allNodes) { +// if (n != curNode && n instanceof StatefulObjectNode && !visited.contains(n)) { +// if (resNode.equals(((StatefulObjectNode) n).getResource())) { +// // n and curNode are identical (one in PUSH call graph and another in PULL call graph). +// visited.add(n); +// for (Edge e: n.getInEdges()) { +// if (!(e.getSource() instanceof EntryPointObjectNode)) { +// if (!(e instanceof DataFlowEdge)) { +// // for a call edge +// topologicalSort(allNodes, e.getSource(), visited, orderedList); +// } +// } +// } +// } +// } +// } +// } + if (curNodeSet.iterator().next() instanceof ResourceNode) { + for (Node curNode: curNodeSet) { + for (Edge e: curNode.getOutEdges()) { + DataFlowEdge de = (DataFlowEdge) e; + if (((PushPullAttribute) de.getAttribute()).getOptions().get(0) != PushPullValue.PUSH) { + // for a PULL data-flow edge + topologicalSort(allNodeSets, allNodeSets.get(e.getDestination()), visited, orderedList); + } + } + } + } + // For reference resources. + ResourceNode cn = null; + Node curNode = curNodeSet.iterator().next(); + if (curNode instanceof ResourceNode) { + cn = (ResourceNode) curNode; + } else if (curNode instanceof StatefulObjectNode) { + cn = ((StatefulObjectNode) curNode).getResource(); + } + if (cn != null) { + for (Node n: allNodeSets.keySet()) { + ResourceNode rn = null; + if (n instanceof ResourceNode) { + rn = (ResourceNode) n; + } else if (n instanceof StatefulObjectNode) { + rn = ((StatefulObjectNode) n).getResource(); + } + if (rn != null) { + for (Edge e: rn.getOutEdges()) { + DataTransferChannel ch = ((DataFlowEdge) e).getChannel(); + for (ChannelMember m: ch.getReferenceChannelMembers()) { + if (m.getResource() == cn.getResource()) { + topologicalSort(allNodeSets, allNodeSets.get(n), visited, orderedList); + } + } + } + } + } + } + orderedList.add(0, curNodeSet); + } + + protected void updateMainComponent(TypeDeclaration mainType, MethodDeclaration mainConstructor, Node componentNode, + MethodDeclaration constructor, ILanguageSpecific langSpec) { + // Declare the field to refer to each object in the main type. + ResourceNode resNode = null; + String nodeName = null; + if (componentNode instanceof ResourceNode) { + resNode = (ResourceNode) componentNode; + nodeName = resNode.getResource().getResourceName(); + } else if (componentNode instanceof ObjectNode) { + nodeName = ((ObjectNode) componentNode).getName(); + if (componentNode instanceof StatefulObjectNode) { + resNode = ((StatefulObjectNode) componentNode).getResource(); + } + } + String componentName = langSpec.toComponentName(nodeName); + // Declare a field to refer each object. + if (langSpec.declareField()) { + FieldDeclaration refField = langSpec.newFieldDeclaration(new Type(componentName, componentName), nodeName); + mainType.addField(refField); + } + // Add a statement to instantiate each object to the main constructor. + List parameters = new ArrayList<>(); + if (constructor.getParameters() != null) { + for (VariableDeclaration var: constructor.getParameters()) { + parameters.add(var.getName()); + } + } + + Block mainConstructorBody = mainConstructor.getBody(); + if (mainConstructorBody == null) { + mainConstructorBody = new Block(); + mainConstructor.setBody(mainConstructorBody); + } + mainConstructorBody.addStatement(langSpec.getFieldAccessor(nodeName) + langSpec.getAssignment() + langSpec.getConstructorInvocation(componentName, parameters) + langSpec.getStatementDelimiter()); + } + + protected void addReference(TypeDeclaration component, MethodDeclaration constructor, Node dstNode, ILanguageSpecific langSpec) { + String dstNodeName = null; + if (dstNode instanceof ResourceNode) { + dstNodeName = ((ResourceNode) dstNode).getResource().getResourceName(); + } else if (dstNode instanceof ObjectNode) { + dstNodeName = ((ObjectNode) dstNode).getName(); + } + String dstComponentName = langSpec.toComponentName(dstNodeName); + if (langSpec.declareField()) { + // Declare a field to refer to another component. + component.addField(langSpec.newFieldDeclaration(new Type(dstComponentName, dstComponentName), dstNodeName)); + } + // Initialize the field to refer to another component. + constructor.addParameter(langSpec.newVariableDeclaration(new Type(dstComponentName, dstComponentName), dstNodeName)); + constructor.getBody().addStatement(langSpec.getFieldAccessor(dstNodeName) + langSpec.getAssignment() + dstNodeName + langSpec.getStatementDelimiter()); + } + + protected void fillGetterMethodToReturnStateField(MethodDeclaration getter, Type resStateType, ILanguageSpecific langSpec) { + // returns the state field when all incoming data-flow edges are PUSH-style. + if (langSpec.isValueType(resStateType)) { + getter.addStatement(langSpec.getReturnStatement(langSpec.getFieldAccessor(fieldOfResourceState)) + langSpec.getStatementDelimiter()); // return value; + } else { + // copy the current state to be returned as a 'value' + String implTypeName = resStateType.getImplementationTypeName(); +// String interfaceTypeName = resourceType.getInterfaceTypeName(); +// String concreteTypeName; +// if (interfaceTypeName.contains("<")) { +// String typeName = implTypeName.substring(0, implTypeName.indexOf("<")); +//// String generics = interfaceTypeName.substring(interfaceTypeName.indexOf("<") + 1, interfaceTypeName.lastIndexOf(">")); +// concreteTypeName = typeName + "<>"; +// } else { +// concreteTypeName = implTypeName; +// } + List parameters = new ArrayList<>(); + parameters.add(langSpec.getFieldAccessor(fieldOfResourceState)); + getter.addStatement(langSpec.getReturnStatement(langSpec.getConstructorInvocation(implTypeName, parameters)) + langSpec.getStatementDelimiter()); // return new Resource(value); + } + } + + protected void declareAccessorInMainComponent(TypeDeclaration mainComponent, ResourcePath accessRes, ILanguageSpecific langSpec) { + MethodDeclaration getter = langSpec.newMethodDeclaration("get" + langSpec.toComponentName(accessRes.getResourceName()), accessRes.getResourceStateType()); + Block block = new Block(); + block.addStatement(langSpec.getReturnStatement(langSpec.getMethodInvocation(accessRes.getResourceName(), getterOfResourceState)) + langSpec.getStatementDelimiter()); + getter.setBody(block); + mainComponent.addMethod(getter); + } + + protected void declareFieldsToReferenceResources(DataTransferModel model, ResourceNode resourceNode, TypeDeclaration component, MethodDeclaration constructor, + final List depends, ILanguageSpecific langSpec) { + Set refs = new HashSet<>(); + for (Channel ch : model.getChannels()) { + DataTransferChannel c = (DataTransferChannel) ch; + if (c.getInputResources().contains(resourceNode.getResource())) { + for (ResourcePath id: c.getReferenceResources()) { + if (!refs.contains(id) && !depends.contains(id)) { + refs.add(id); + String refResName = langSpec.toComponentName(id.getResourceName()); + component.addField(langSpec.newFieldDeclaration(new Type(refResName, refResName), id.getResourceName())); + constructor.addParameter(langSpec.newVariableDeclaration(new Type(refResName, refResName), id.getResourceName())); + constructor.getBody().addStatement(langSpec.getFieldAccessor(id.getResourceName()) + langSpec.getAssignment() + id.getResourceName() + langSpec.getStatementDelimiter()); + } + } + } + } + } + + protected MethodDeclaration getUpdateMethod(Edge inEdge, TypeDeclaration component, + Map>> dataFlowInform, ILanguageSpecific langSpec) { + List passedResoueces = dataFlowInform.get(inEdge).get(PushPullValue.PUSH); + String methodName = updateMethodName; + for (ResourceNode rn: passedResoueces) { + ResourcePath rId = rn.getResource(); + methodName += langSpec.toComponentName(rId.getResourceName()); + } + return getMethod(component, methodName); + } + + protected MethodDeclaration getInputMethod(ResourceNode resourceNode, DataTransferChannel ch, TypeDeclaration component) { + MethodDeclaration input = null; + for (ChannelMember out : ch.getOutputChannelMembers()) { + if (out.getResource().equals(resourceNode.getResource())) { + Expression message = out.getStateTransition().getMessageExpression(); + if (message instanceof Term) { + input = getMethod(component, ((Term) message).getSymbol().getImplName()); + } else if (message instanceof Variable) { + // Declare an input method in this component. + input = getMethod(component, ((Variable) message).getName()); + } + break; + } + } + return input; + } + + protected MethodDeclaration getMethod(TypeDeclaration component, String methodName) { + for (MethodDeclaration m: component.getMethods()) { + if (m.getName().equals(methodName)) return m; + } + return null; + } + + protected IResourceStateAccessor getPushAccessor() { + return new IResourceStateAccessor() { + @Override + public Expression getCurrentStateAccessorFor(ResourcePath target, ResourcePath from) { + if (target.equals(from)) { + return new Field(fieldOfResourceState, + target.getResourceStateType() != null ? target.getResourceStateType() + : DataConstraintModel.typeInt); + } + // for reference channel member + return new Parameter(target.getResourceName(), + target.getResourceStateType() != null ? target.getResourceStateType() + : DataConstraintModel.typeInt); + } + + @Override + public Expression getNextStateAccessorFor(ResourcePath target, ResourcePath from) { + return new Parameter(target.getResourceName(), + target.getResourceStateType() != null ? target.getResourceStateType() + : DataConstraintModel.typeInt); + } + }; + } + + protected IResourceStateAccessor getPullAccessor() { + return new IResourceStateAccessor() { + @Override + public Expression getCurrentStateAccessorFor(ResourcePath target, ResourcePath from) { + if (target.equals(from)) { + return new Field(fieldOfResourceState, + target.getResourceStateType() != null ? target.getResourceStateType() + : DataConstraintModel.typeInt); + } + // for reference channel member + Term getter = new Term(new Symbol(getterOfResourceState, 1, Symbol.Type.METHOD)); + getter.addChild(new Field(target.getResourceName(), target.getResourceStateType())); + return getter; + } + + @Override + public Expression getNextStateAccessorFor(ResourcePath target, ResourcePath from) { + Term getter = new Term(new Symbol(getterOfResourceState, 1, Symbol.Type.METHOD)); + getter.addChild(new Field(target.getResourceName(), target.getResourceStateType())); + return getter; + } + }; + } +} diff --git a/AlgebraicDataflowArchitectureModel/src/generators/CodeGeneratorFromControlFlowGraph.java b/AlgebraicDataflowArchitectureModel/src/generators/CodeGeneratorFromControlFlowGraph.java new file mode 100644 index 0000000..1b449d4 --- /dev/null +++ b/AlgebraicDataflowArchitectureModel/src/generators/CodeGeneratorFromControlFlowGraph.java @@ -0,0 +1,908 @@ +package generators; + +import java.util.ArrayList; +import java.util.Arrays; +import java.util.HashMap; +import java.util.HashSet; +import java.util.List; +import java.util.Map; +import java.util.Set; + +import code.ast.Block; +import code.ast.CompilationUnit; +import code.ast.FieldDeclaration; +import code.ast.MethodDeclaration; +import code.ast.TypeDeclaration; +import code.ast.VariableDeclaration; +import models.Edge; +import models.Node; +import models.algebra.Constant; +import models.algebra.Expression; +import models.algebra.Field; +import models.algebra.InvalidMessage; +import models.algebra.ParameterizedIdentifierIsFutureWork; +import models.algebra.Symbol; +import models.algebra.Term; +import models.algebra.Type; +import models.algebra.UnificationFailed; +import models.algebra.ValueUndefined; +import models.algebra.Variable; +import models.controlFlowModel.ControlFlowGraph; +import models.controlFlowModel.EntryPointObjectNode; +import models.controlFlowModel.ObjectNode; +import models.controlFlowModel.StatefulObjectNode; +import models.dataConstraintModel.ChannelMember; +import models.dataConstraintModel.DataConstraintModel; +import models.dataConstraintModel.ResourcePath; +import models.dataFlowModel.DataFlowEdge; +import models.dataFlowModel.DataTransferChannel; +import models.dataFlowModel.DataTransferModel; +import models.dataFlowModel.IFlowGraph; +import models.dataFlowModel.PushPullAttribute; +import models.dataFlowModel.PushPullValue; +import models.dataFlowModel.ResolvingMultipleDefinitionIsFutureWork; +import models.dataFlowModel.ResourceNode; +import models.dataFlowModel.StoreAttribute; +import models.dataFlowModel.DataTransferChannel.IResourceStateAccessor; + +public class CodeGeneratorFromControlFlowGraph extends CodeGenerator { + + @Override + public void generateCodeFromFlowGraph(DataTransferModel model, IFlowGraph flowGraph, ArrayList> components, + TypeDeclaration mainComponent, MethodDeclaration mainConstructor, ArrayList codes, ILanguageSpecific langSpec) { + // Reconstruct data-flow information. + Map>> dataFlowInform = new HashMap<>(); + ControlFlowGraph controlFlowGraph = (ControlFlowGraph) flowGraph; + for (Node root: controlFlowGraph.getPushCallGraph().getRootNodes()) { + Set treeResources = traverseCallTree(root, new HashSet<>()); + annotateDataFlowAttributes(root, dataFlowInform, treeResources, new ArrayList<>()); + removeRedundantAttributes(root, dataFlowInform); + } + for (Node root: controlFlowGraph.getPullCallGraph().getRootNodes()) { + Set treeResources = traverseCallTree(root, new HashSet<>()); + annotateDataFlowAttributes(root, dataFlowInform, treeResources, new ArrayList<>()); + removeRedundantAttributes(root, dataFlowInform); + } + + // For each component other than the main component. + Map componentMap = new HashMap<>(); + for (Set componentNodeSet: components) { + // Declare this component. + Node componentNode = componentNodeSet.iterator().next(); + String componentName = langSpec.toComponentName(((ObjectNode) componentNode).getName()); + TypeDeclaration component = langSpec.newTypeDeclaration(componentName); + for (Node compNode: componentNodeSet) { + componentMap.put(compNode, component); + } + + // Declare the constructor and the fields to refer to the callee components. + List depends = new ArrayList<>(); + MethodDeclaration constructor = declareConstructorAndFieldsToCalleeComponents(componentNodeSet, component, depends, langSpec); + + if (componentNode instanceof StatefulObjectNode) { + // For this resource. + ResourceNode resourceNode = ((StatefulObjectNode) componentNode).getResource(); + ResourcePath res = resourceNode.getResource(); + Type resStateType = res.getResourceStateType(); + + // Declare the field in this resource to store the state. + if (((StoreAttribute) resourceNode.getAttribute()).isStored()) { + FieldDeclaration stateField = langSpec.newFieldDeclaration(resStateType, fieldOfResourceState, langSpec.getFieldInitializer(resStateType, res.getInitialValue())); + component.addField(stateField); + } + + // Declare the accessor method in the main component to call the getter method. + declareAccessorInMainComponent(mainComponent, res, langSpec); + + // Declare the fields to refer to reference resources. + declareFieldsToReferenceResources(model, resourceNode, component, constructor, depends, langSpec); + } + + // Update the main component for this component. + updateMainComponent(mainComponent, mainConstructor, componentNode, constructor, langSpec); + if (constructor.getParameters() == null) { + component.removeMethod(constructor); + } + + // Add compilation unit for this component. + CompilationUnit cu = langSpec.newCompilationUnit(component); + codes.add(cu); + } + + // Declare and Fill the getter method to return the resource state. + for (Node node: controlFlowGraph.getPushCallGraph().getNodes()) { + TypeDeclaration component = componentMap.get(node); + if (node instanceof StatefulObjectNode) { + ResourceNode resourceNode = ((StatefulObjectNode) node).getResource(); + Type resStateType = resourceNode.getResource().getResourceStateType(); + if (((StoreAttribute) resourceNode.getAttribute()).isStored()) { + // Declare the getter method in this resource to obtain the state. + MethodDeclaration getter = langSpec.newMethodDeclaration(getterOfResourceState, resStateType); + component.addMethod(getter); + fillGetterMethodToReturnStateField(getter, resourceNode.getResource().getResourceStateType(), langSpec); // return this.value; + } + } + } + + for (Node node: controlFlowGraph.getPullCallGraph().getNodes()) { + String nodeName = ((ObjectNode) node).getName(); + if (componentMap.get(node) == null) { + for (Node node2: componentMap.keySet()) { + if (((ObjectNode) node2).getName().equals(nodeName)) { + componentMap.put(node, componentMap.get(node2)); // Since nodes shared by PUSH and PULL call graphs are duplicated. + break; + } + } + } + } + + // Declare other getter methods. + for (Node root: controlFlowGraph.getPullCallGraph().getRootNodes()) { + MethodDeclaration getter = declareAndFillGetterMethods(root, null, dataFlowInform, componentMap, langSpec); + } + + // Declare update and input methods. + for (Node root: controlFlowGraph.getPushCallGraph().getRootNodes()) { + MethodDeclaration input = declareAndFillUpdateAndInputMethods(root, null, null, dataFlowInform, componentMap, langSpec); + mainComponent.addMethod(input); + } + } + + private Set traverseCallTree(Node node, Set visited) { + if (node instanceof StatefulObjectNode) { + ResourceNode resNode = ((StatefulObjectNode) node).getResource(); + visited.add(resNode); + } + // Traverse the call tree. + for (Edge e: node.getOutEdges()) { + visited = traverseCallTree(e.getDestination(), visited); + } + return visited; + } + + private void annotateDataFlowAttributes(Node node, Map>> dataFlowInform, Set resourceNodes, List path) { + if (node instanceof StatefulObjectNode) { + // Add data-flow attributes to the path to node. + ResourceNode resNode = ((StatefulObjectNode) node).getResource(); + for (Edge outE: resNode.getOutEdges()) { + // If resNode is the source of data-flow. + ResourceNode dstOfDataFlowNode = (ResourceNode) outE.getDestination(); + if (resourceNodes.contains(dstOfDataFlowNode)) { + // If the data transfer is closed within this call tree. + for (Edge e: path) { + // Add pull attributes to the path to resNode. + Map> edgeAttributes = dataFlowInform.get(e); + if (edgeAttributes == null) { + edgeAttributes = new HashMap<>(); + dataFlowInform.put(e, edgeAttributes); + } + List pullSrcs = edgeAttributes.get(PushPullValue.PULL); + if (pullSrcs == null) { + pullSrcs = new ArrayList<>(); + edgeAttributes.put(PushPullValue.PULL, pullSrcs); + } + pullSrcs.add(resNode); + } + } + } + for (Edge inE: resNode.getInEdges()) { + // If resNode is a destination of data-flow. + ResourceNode srcOfDataFlowNode = (ResourceNode) inE.getSource(); + if (resourceNodes.contains(srcOfDataFlowNode)) { + // If the data transfer is closed done within this call tree. + for (Edge e: path) { + // Add push attributes to the path to resNode. + Map> edgeAttributes = dataFlowInform.get(e); + if (edgeAttributes == null) { + edgeAttributes = new HashMap<>(); + dataFlowInform.put(e, edgeAttributes); + } + List pushSrcs = edgeAttributes.get(PushPullValue.PUSH); + if (pushSrcs == null) { + pushSrcs = new ArrayList<>(); + edgeAttributes.put(PushPullValue.PUSH, pushSrcs); + } + pushSrcs.add(srcOfDataFlowNode); + } + } + } + } + // Traverse the call tree. + for (Edge e: node.getOutEdges()) { + path.add(e); + annotateDataFlowAttributes(e.getDestination(), dataFlowInform, resourceNodes, path); + path.remove(e); + } + } + + private void removeRedundantAttributes(Node node, Map>> dataFlowInform) { + // Traverse the call tree. + for (Edge e: node.getOutEdges()) { + // Remove attributes that are common to PUSH and PULL. + if (dataFlowInform.get(e) == null) { + dataFlowInform.put(e, new HashMap<>()); + } + List pushFlows = dataFlowInform.get(e).get(PushPullValue.PUSH); + List pullFlows = dataFlowInform.get(e).get(PushPullValue.PULL); + if (pushFlows == null) { + pushFlows = new ArrayList<>(); + } + if (pullFlows == null) { + pullFlows = new ArrayList<>(); + } + List pushFlowsOrg = new ArrayList<>(pushFlows); + for (ResourceNode r: pullFlows) { + pushFlows.remove(r); + } + for (ResourceNode r: pushFlowsOrg) { + pullFlows.remove(r); + } + pushFlows = new ArrayList<>(new HashSet<>(pushFlows)); + pullFlows = new ArrayList<>(new HashSet<>(pullFlows)); + dataFlowInform.get(e).put(PushPullValue.PUSH, pushFlows); + dataFlowInform.get(e).put(PushPullValue.PULL, pullFlows); + removeRedundantAttributes(e.getDestination(), dataFlowInform); + } + } + + private MethodDeclaration declareConstructorAndFieldsToCalleeComponents(Set componentNodeSet, TypeDeclaration component, + List depends, ILanguageSpecific langSpec) { + // Declare a constructor in each component. + MethodDeclaration constructor = component.createConstructor(); + Block block = new Block(); + constructor.setBody(block); + + // Declare fields in each component. (for control-flow graph) + for (Node componentNode: componentNodeSet) { + for (Edge e: componentNode.getOutEdges()) { + ObjectNode dstNode = (ObjectNode) e.getDestination(); + addReference(component, constructor, dstNode, langSpec); + if (dstNode instanceof StatefulObjectNode) { + ResourcePath dstRes = ((StatefulObjectNode) dstNode).getResource().getResource(); + if (!depends.contains(dstRes)) depends.add(dstRes); + } + } + } + return constructor; + } + + + private MethodDeclaration declareAndFillGetterMethods(Node node, Edge inEdge, + Map>> dataFlowInform, Map componentMap, + ILanguageSpecific langSpec) { + TypeDeclaration component = componentMap.get(node); + List resourcesToReturn = null; + if (inEdge != null) { + resourcesToReturn = dataFlowInform.get(inEdge).get(PushPullValue.PULL); + } + if (node instanceof StatefulObjectNode) { + ResourceNode resourceNode = ((StatefulObjectNode) node).getResource(); + Type resStateType = resourceNode.getResource().getResourceStateType(); + MethodDeclaration getter = langSpec.newMethodDeclaration(getterOfResourceState, resStateType); + MethodDeclaration getter2 = getMethod(component, getter.getName()); + if (getter2 == null) { + component.addMethod(getter); + } else { + getter = getter2; + } + if (((StoreAttribute) resourceNode.getAttribute()).isStored()) { + if (getter2 == null) { + // Declare the getter method in this resource to obtain the state. + fillGetterMethodToReturnStateField(getter, resourceNode.getResource().getResourceStateType(), langSpec); // return this.value; + } + } else { + // Invocations to other getter methods when at least one incoming data-flow edges is PULL-style. + boolean isContainedPush = false; + DataTransferChannel ch = null; + HashMap inputResourceToStateAccessor = new HashMap<>(); + for (Edge eIn: resourceNode.getInEdges()) { + DataFlowEdge dataFlowInEdge = (DataFlowEdge) eIn; + if (((PushPullAttribute) dataFlowInEdge.getAttribute()).getOptions().get(0) == PushPullValue.PUSH) { + // PUSH data transfer + isContainedPush = true; + inputResourceToStateAccessor.put(((ResourceNode) dataFlowInEdge.getSource()).getResource(), getPushAccessor()); + } else { + // PULL data transfer + for (Edge callEdge: node.getOutEdges()) { + // For each call edge. + ObjectNode calledNode = (ObjectNode) callEdge.getDestination(); + List returnedResources = dataFlowInform.get(callEdge).get(PushPullValue.PULL); + if (returnedResources.contains((ResourceNode) dataFlowInEdge.getSource())) { + if (returnedResources.size() == 1) { + MethodDeclaration nextGetter = declareAndFillGetterMethods(calledNode, callEdge, dataFlowInform, componentMap, langSpec); + inputResourceToStateAccessor.put(((ResourceNode) dataFlowInEdge.getSource()).getResource(), getPullAccessor(calledNode.getName(), nextGetter.getName())); + break; + } else { + MethodDeclaration nextGetter = declareAndFillGetterMethods(calledNode, callEdge, dataFlowInform, componentMap, langSpec); + int idx = returnedResources.indexOf((ResourceNode) dataFlowInEdge.getSource()); + int len = returnedResources.size(); + inputResourceToStateAccessor.put(((ResourceNode) dataFlowInEdge.getSource()).getResource(), + getPullAccessor(langSpec.getTupleGet(langSpec.getMethodInvocation(langSpec.getFieldAccessor(calledNode.getName()), nextGetter.getName()), idx, len))); + break; + } + } + } + ch = dataFlowInEdge.getChannel(); // Always unique. + } + } + // For reference channel members. + for (ChannelMember c: ch.getReferenceChannelMembers()) { + inputResourceToStateAccessor.put(c.getResource(), getPullAccessor()); // by pull data transfer + } + + // Add a return statement. + try { + for (ChannelMember out: ch.getOutputChannelMembers()) { + if (out.getResource().equals(resourceNode.getResource())) { + String[] sideEffects = new String[] {""}; + // The following process is common to the cases of 1) and 2). + // 1) All incoming edges are in PULL-style. + // 2) At least one incoming edge is in PUSH-style. + String curState = ch.deriveUpdateExpressionOf(out, getPullAccessor(), inputResourceToStateAccessor).toImplementation(sideEffects); + getter.addStatement(sideEffects[0] + langSpec.getReturnStatement(curState) + langSpec.getStatementDelimiter()); + break; + } + } + } catch (ParameterizedIdentifierIsFutureWork | ResolvingMultipleDefinitionIsFutureWork + | InvalidMessage | UnificationFailed | ValueUndefined e) { + e.printStackTrace(); + } + } + if (resourcesToReturn == null || resourcesToReturn.size() == 1) return getter; + } else if (resourcesToReturn == null || resourcesToReturn.size() == 1) { + // Declare a mediate getter method to return a single value. + String getterMethodName = "get"; + ResourceNode returnedRes = null; + if (resourcesToReturn != null) { + returnedRes = resourcesToReturn.get(0); + } else { + // Unexpected. + } + getterMethodName += langSpec.toComponentName(returnedRes.getResource().getResourceName()) + "Value"; + MethodDeclaration mediateGetter = getMethod(component, getterMethodName); + if (mediateGetter != null) return mediateGetter; + mediateGetter = langSpec.newMethodDeclaration(getterMethodName, returnedRes.getResource().getResourceStateType()); + component.addMethod(mediateGetter); + + // Add a return statement. + if (node.getOutdegree() == 1) { + Edge callEdge = node.getOutEdges().iterator().next(); + ObjectNode calledNode = (ObjectNode) callEdge.getDestination(); + MethodDeclaration nextGetter = declareAndFillGetterMethods(calledNode, callEdge, dataFlowInform, componentMap, langSpec); + mediateGetter.addStatement( + langSpec.getReturnStatement(langSpec.getMethodInvocation(langSpec.getFieldAccessor(calledNode.getName()), nextGetter.getName())) + + langSpec.getStatementDelimiter()); + } else { + // Unexpected. + } + return mediateGetter; + } + // Declare a mediate getter method to return multiple values. + String getterMethodName = "get"; + for (ResourceNode rn: resourcesToReturn) { + getterMethodName += langSpec.toComponentName(rn.getResource().getResourceName()); + } + getterMethodName += "Values"; + MethodDeclaration mediateGetter = getMethod(component, getterMethodName); + if (mediateGetter != null) return mediateGetter; + Type returnType = createReturnType(resourcesToReturn, langSpec); + mediateGetter = langSpec.newMethodDeclaration(getterMethodName, returnType); + component.addMethod(mediateGetter); + + // Add a return statement. + if (node.getOutdegree() == 1 && resourcesToReturn != null + && resourcesToReturn.equals(dataFlowInform.get(node.getOutEdges().iterator().next()).get(PushPullValue.PULL))) { + // Directly returns the returned value. + Edge outEdge = node.getOutEdges().iterator().next(); + ObjectNode dstNode = (ObjectNode) outEdge.getDestination(); + MethodDeclaration nextGetter = declareAndFillGetterMethods(dstNode, outEdge, dataFlowInform, componentMap, langSpec); + String getterInvocation = langSpec.getMethodInvocation(langSpec.getFieldAccessor(dstNode.getName()), nextGetter.getName()); + mediateGetter.addStatement(langSpec.getReturnStatement(getterInvocation) + langSpec.getStatementDelimiter()); + } else { + List params = new ArrayList<>(); + for (ResourceNode rn: resourcesToReturn) { + ResourcePath rId = rn.getResource(); + if (rId.getResourceName().equals(((ObjectNode) node).getName())) { + params.add(langSpec.getMethodInvocation(getterOfResourceState)); + } else { + for (Edge outEdge: node.getOutEdges()) { + ObjectNode dstNode = (ObjectNode) outEdge.getDestination(); + List returnedResources = dataFlowInform.get(outEdge).get(PushPullValue.PULL); + if (returnedResources.contains(rn)) { + if (returnedResources.size() == 1) { + MethodDeclaration nextGetter = declareAndFillGetterMethods(dstNode, outEdge, dataFlowInform, componentMap, langSpec); + params.add(langSpec.getMethodInvocation(langSpec.getFieldAccessor(dstNode.getName()), nextGetter.getName())); + } else { + MethodDeclaration nextGetter = declareAndFillGetterMethods(dstNode, outEdge, dataFlowInform, componentMap, langSpec); + int idx = returnedResources.indexOf(rn); + int len = returnedResources.size(); + params.add(langSpec.getTupleGet(langSpec.getMethodInvocation(langSpec.getFieldAccessor(dstNode.getName()), nextGetter.getName()), idx, len)); + } + break; + } + } + } + } + mediateGetter.addStatement( + langSpec.getReturnStatement(langSpec.getConstructorInvocation(returnType.getImplementationTypeName(), params)) + + langSpec.getStatementDelimiter()); + } + return mediateGetter; + } + + private MethodDeclaration declareAndFillUpdateAndInputMethods(Node node, Edge inEdge, Node prevResNode, + Map>> dataFlowInform, Map componentMap, ILanguageSpecific langSpec) { + TypeDeclaration component = componentMap.get(node); + List resourcesToReturn = null; + List resourcesToReceive = null; + if (dataFlowInform.get(inEdge) != null) { + resourcesToReturn = dataFlowInform.get(inEdge).get(PushPullValue.PULL); + resourcesToReceive = dataFlowInform.get(inEdge).get(PushPullValue.PUSH); + } + if (node instanceof StatefulObjectNode) { + // Declare update or input method in the resource component. + ResourceNode resourceNode = ((StatefulObjectNode) node).getResource(); + MethodDeclaration updateOrInput = null; + if (!(prevResNode instanceof EntryPointObjectNode) + || (resourcesToReceive != null && resourcesToReceive.size() > 0)) { + updateOrInput = getUpdateMethod(inEdge, component, dataFlowInform, langSpec); + if (updateOrInput != null) return updateOrInput; + // Declare an update method. + updateOrInput = declareUpdateMethod(node, inEdge, component, dataFlowInform, langSpec); + } else { + DataTransferChannel ch = ((EntryPointObjectNode) prevResNode).getIOChannel(); + updateOrInput = getInputMethod(resourceNode, ch, component); + if (updateOrInput != null) return updateOrInput; + // Declare an input method. + updateOrInput = declareInputMethod(resourceNode, ch, langSpec); + } + component.addMethod(updateOrInput); + + Map resToVar = new HashMap<>(); + Map> varToRes = new HashMap<>(); + for (Edge outEdge: node.getOutEdges()) { + Node dstNode = outEdge.getDestination(); + MethodDeclaration calleeMethod = declareAndFillUpdateAndInputMethods(dstNode, outEdge, node, dataFlowInform, componentMap, langSpec); + // Add a statement to call the destination method. + List returnedResources = dataFlowInform.get(outEdge).get(PushPullValue.PULL); + String varName = addInvocationInResourceUpdate(node, updateOrInput, calleeMethod, ((ObjectNode) dstNode).getName(), returnedResources, langSpec); + if (varName != null && returnedResources != null) { + for (ResourceNode rn: returnedResources) { + String resName = rn.getResource().getResourceName(); + resToVar.put(rn, resName); + varToRes.put(resName, Arrays.asList(new ResourceNode[] {rn})); + } +// // Alternative implementation. +// varToRes.put(varName, returnedResources); +// for (ResourceNode rn: returnedResources) { +// resToVar.put(rn, varName); +// } + } + } + + if (resourcesToReturn != null && resourcesToReturn.size() > 0) { + // Set the return type and add a return statement. + Type returnType = createReturnType(resourcesToReturn, langSpec); + updateOrInput.setReturnType(returnType); + String returnValue = createReturnValue(resourcesToReturn, node, returnType, resToVar, varToRes, langSpec); + updateOrInput.addStatement(langSpec.getReturnStatement(returnValue) + langSpec.getStatementDelimiter()); + } + return updateOrInput; + } else if (node instanceof EntryPointObjectNode) { + // Declare an input method. + MethodDeclaration input = null; + for (Edge outEdge: node.getOutEdges()) { + Node dstNode = outEdge.getDestination(); + MethodDeclaration calleeMethod = declareAndFillUpdateAndInputMethods(dstNode, outEdge, node, dataFlowInform, componentMap, langSpec); + if (input == null) { + // Declare an input method. + if (calleeMethod.getParameters() != null) { + input = langSpec.newMethodDeclaration(calleeMethod.getName(), false, null, new ArrayList<>(calleeMethod.getParameters())); + } else { + input = langSpec.newMethodDeclaration(calleeMethod.getName(), null); + } + } + // Add a statement to call the destination method. + String varName = addInvocationInMediatorUpdate(input, calleeMethod, ((ObjectNode) dstNode).getName(), dataFlowInform.get(outEdge).get(PushPullValue.PULL), langSpec); + } + return input; + } else { + // Declare update or input method in the mediate component. + List updateMethods = getUpdateMethods(component); + if (updateMethods.size() > 0) return updateMethods.get(0); + MethodDeclaration updateOrInput = null; + if (!(prevResNode instanceof EntryPointObjectNode) + || (resourcesToReceive != null && resourcesToReceive.size() > 0)) { + // Declare an update method. + updateOrInput = declareUpdateMethod(node, inEdge, component, dataFlowInform, langSpec); + component.addMethod(updateOrInput); + } + + if (node.getOutdegree() == 1 && resourcesToReturn != null && resourcesToReturn.size() > 0 + && resourcesToReturn.equals(dataFlowInform.get(node.getOutEdges().iterator().next()).get(PushPullValue.PULL))) { + // Directly returns the returned value. + Edge outEdge = node.getOutEdges().iterator().next(); + ObjectNode dstNode = (ObjectNode) outEdge.getDestination(); + MethodDeclaration calleeMethod = declareAndFillUpdateAndInputMethods(dstNode, outEdge, prevResNode, dataFlowInform, componentMap, langSpec); + if (updateOrInput == null && prevResNode instanceof EntryPointObjectNode) { + // Declare an input method. + if (calleeMethod.getParameters() != null) { + updateOrInput = langSpec.newMethodDeclaration(calleeMethod.getName(), false, null, new ArrayList<>(calleeMethod.getParameters())); + } else { + updateOrInput = langSpec.newMethodDeclaration(calleeMethod.getName(), null); + } + component.addMethod(updateOrInput); + } + // Set the return type and add a return statement. + updateOrInput.setReturnType(calleeMethod.getReturnType()); + String updateInvocation = langSpec.getMethodInvocation(langSpec.getFieldAccessor(dstNode.getName()), calleeMethod.getName()); + updateOrInput.addStatement(langSpec.getReturnStatement(updateInvocation) + langSpec.getStatementDelimiter()); + } else { + Map resToVar = new HashMap<>(); + Map> varToRes = new HashMap<>(); + for (Edge outEdge: node.getOutEdges()) { + Node dstNode = outEdge.getDestination(); + MethodDeclaration calleeMethod = declareAndFillUpdateAndInputMethods(dstNode, outEdge, prevResNode, dataFlowInform, componentMap, langSpec); + if (updateOrInput == null && prevResNode instanceof EntryPointObjectNode) { + // Declare an input method. + if (calleeMethod.getParameters() != null) { + updateOrInput = langSpec.newMethodDeclaration(calleeMethod.getName(), false, null, new ArrayList<>(calleeMethod.getParameters())); + } else { + updateOrInput = langSpec.newMethodDeclaration(calleeMethod.getName(), null); + } + component.addMethod(updateOrInput); + } + // Add a statement to call the destination method. + List returnedResources = dataFlowInform.get(outEdge).get(PushPullValue.PULL); + String varName = addInvocationInMediatorUpdate(updateOrInput, calleeMethod, ((ObjectNode) dstNode).getName(), returnedResources, langSpec); + if (varName != null && returnedResources != null) { + for (ResourceNode rn: returnedResources) { + String resName = rn.getResource().getResourceName(); + resToVar.put(rn, resName); + varToRes.put(resName, Arrays.asList(new ResourceNode[] {rn})); + } +// // Alternative implementation. +// varToRes.put(varName, returnedResources); +// for (ResourceNode rn: returnedResources) { +// resToVar.put(rn, varName); +// } + } + } + if (resourcesToReturn != null && resourcesToReturn.size() > 0) { + // Set the return type and add a return statement. + Type returnType = createReturnType(resourcesToReturn, langSpec); + updateOrInput.setReturnType(returnType); + String returnValue = createReturnValue(resourcesToReturn, node, returnType, resToVar, varToRes, langSpec); + updateOrInput.addStatement(langSpec.getReturnStatement(returnValue) + langSpec.getStatementDelimiter()); + } + } + return updateOrInput; + } + } + + private MethodDeclaration declareUpdateMethod(Node node, Edge inEdge, TypeDeclaration component, + Map>> dataFlowInform, ILanguageSpecific langSpec) { + // Declare an update method in the component. + ArrayList vars = new ArrayList<>(); + List passedResoueces = dataFlowInform.get(inEdge).get(PushPullValue.PUSH); + Set passedIds = new HashSet<>(); + String methodName = updateMethodName; + for (ResourceNode rn: passedResoueces) { + ResourcePath rId = rn.getResource(); + passedIds.add(rId); + methodName += langSpec.toComponentName(rId.getResourceName()); + vars.add(langSpec.newVariableDeclaration(rId.getResourceStateType(), rId.getResourceName())); + } + MethodDeclaration update = langSpec.newMethodDeclaration(methodName, false, null, vars); + + if (node instanceof StatefulObjectNode) { + // Add a statement to update the state field + ResourceNode resourceNode = ((StatefulObjectNode) node).getResource(); + if (((StoreAttribute) resourceNode.getAttribute()).isStored()) { + try { + boolean stateUpdateAdded = false; + for (Edge e: resourceNode.getInEdges()) { + DataFlowEdge re = (DataFlowEdge) e; + for (ChannelMember in: re.getChannel().getInputChannelMembers()) { + if (passedIds.contains(in.getResource())) { + for (ChannelMember out: re.getChannel().getOutputChannelMembers()) { + if (out.getResource().equals(resourceNode.getResource())) { + Expression updateExp = re.getChannel().deriveUpdateExpressionOf(out, getPushAccessor()); + String[] sideEffects = new String[] {""}; + String curState = updateExp.toImplementation(sideEffects); + String updateStatement; + if (updateExp instanceof Term && ((Term) updateExp).getSymbol().isImplWithSideEffect()) { + updateStatement = sideEffects[0]; + } else { + updateStatement = sideEffects[0] + langSpec.getFieldAccessor(fieldOfResourceState) + langSpec.getAssignment() + curState + langSpec.getStatementDelimiter(); // this.value = ... + } + update.addFirstStatement(updateStatement); + stateUpdateAdded = true; + break; + } + } + } + if (stateUpdateAdded) break; + } + if (stateUpdateAdded) break; + } + } catch (ParameterizedIdentifierIsFutureWork | ResolvingMultipleDefinitionIsFutureWork + | InvalidMessage | UnificationFailed | ValueUndefined e1) { + e1.printStackTrace(); + } + } + + // Declare the field to cache the state of the source resource in the type of the destination resource. + if (node.getIndegree() > 1) { + // If incoming edges are multiple + for (ResourcePath srcRes: passedIds) { + String srcResName = srcRes.getResourceName(); + if (langSpec.declareField()) { + // Declare the cache field. + FieldDeclaration cacheField = langSpec.newFieldDeclaration( + srcRes.getResourceStateType(), + srcResName, + langSpec.getFieldInitializer(srcRes.getResourceStateType(), srcRes.getInitialValue())); + component.addField(cacheField); + + } + // Update the cache field. + String cashStatement = langSpec.getFieldAccessor(srcResName) + langSpec.getAssignment() + srcResName + langSpec.getStatementDelimiter(); + update.addFirstStatement(cashStatement); + } + } + } + return update; + } + + private MethodDeclaration declareInputMethod(ResourceNode resourceNode, DataTransferChannel ch, ILanguageSpecific langSpec) { + MethodDeclaration input = null; + for (ChannelMember out : ch.getOutputChannelMembers()) { + if (out.getResource().equals(resourceNode.getResource())) { + Expression message = out.getStateTransition().getMessageExpression(); + if (message instanceof Term) { + // Declare an input method in this component. + ArrayList params = new ArrayList<>(); + for (Variable var: message.getVariables().values()) { + params.add(langSpec.newVariableDeclaration(var.getType(), var.getName())); + } + input = langSpec.newMethodDeclaration(((Term) message).getSymbol().getImplName(), false, null, params); + } else if (message instanceof Variable) { + // Declare an input method in this component. + input = langSpec.newMethodDeclaration(((Variable) message).getName(), null); + } + + if (input != null) { + // Add a statement to update the state field to the input method. + try { + String[] sideEffects = new String[] {""}; + Expression updateExp; + updateExp = ch.deriveUpdateExpressionOf(out, getPullAccessor()); + String newState = updateExp.toImplementation(sideEffects); + String updateStatement; + if (updateExp instanceof Term && ((Term) updateExp).getSymbol().isImplWithSideEffect()) { + updateStatement = sideEffects[0]; + } else { + updateStatement = sideEffects[0] + langSpec.getFieldAccessor(fieldOfResourceState) + langSpec.getAssignment() + newState + langSpec.getStatementDelimiter(); + } + input.addFirstStatement(updateStatement); + } catch (ParameterizedIdentifierIsFutureWork | ResolvingMultipleDefinitionIsFutureWork + | InvalidMessage | UnificationFailed | ValueUndefined e) { + e.printStackTrace(); + } + } + break; + } + } + return input; + } + + private String createReturnValue(List resourcesToReturn, Node node, Type returnType, Map resToVar, Map> varToRes, ILanguageSpecific langSpec) { + List params = new ArrayList<>(); + for (ResourceNode rn: resourcesToReturn) { + ResourcePath rId = rn.getResource(); + if (rId.getResourceName().equals(((ObjectNode) node).getName())) { + params.add(langSpec.getFieldAccessor(fieldOfResourceState)); + } else { + String varName = resToVar.get(rn); + if (varToRes.get(varName).size() == 1) { + params.add(varName); + } else { + params.add(langSpec.getTupleGet(varName, varToRes.get(varName).indexOf(rn), varToRes.get(varName).size())); + } + } + } + if (params.size() == 1) { + return params.iterator().next(); + } else { + return langSpec.getConstructorInvocation(returnType.getImplementationTypeName(), params); + } + } + + private Type createReturnType(List resourcesToReturn, ILanguageSpecific langSpec) { + if (resourcesToReturn.size() == 1) { + return resourcesToReturn.iterator().next().getResource().getResourceStateType(); + } + List compTypes = new ArrayList<>(); + for (ResourceNode rn: resourcesToReturn) { + ResourcePath rId = rn.getResource(); + compTypes.add(rId.getResourceStateType()); + } + Type returnType = langSpec.newTupleType(compTypes); + return returnType; + } + + + private String addInvocationInResourceUpdate(Node node, MethodDeclaration resourceUpdateMethod, MethodDeclaration calleeMethod, String dstNodeName, List returnResources, ILanguageSpecific langSpec) { + List params = new ArrayList<>(); + params.add(langSpec.getFieldAccessor(fieldOfResourceState)); + if (calleeMethod.getParameters() != null) { + for (VariableDeclaration v: calleeMethod.getParameters()) { + if (!((ObjectNode) node).getName().equals(v.getName())) { + params.add(v.getName()); + } + } + } +// for (ChannelMember rc: re.getChannelGenerator().getReferenceChannelMembers()) { +// // to get the value of reference member. +// IdentifierTemplate ref = rc.getIdentifierTemplate(); +// if (referredSet == null) { +// referredSet = new HashSet<>(); +// referredResources.put(update, referredSet); +// } +// if (ref != resourceNode.getIdentifierTemplate()) { +// String refVarName = ref.getResourceName(); +// if (!referredSet.contains(ref)) { +// referredSet.add(ref); +// Expression refGetter = langSpec.getPullAccessor().getCurrentStateAccessorFor(ref, ((ResourceNode) dOut.getSource()).getIdentifierTemplate()); +// String[] sideEffects = new String[] {""}; +// String refExp = refGetter.toImplementation(sideEffects); +// String refTypeName = ref.getResourceStateType().getInterfaceTypeName(); +// resourceUpdateMethod.addFirstStatement(sideEffects[0] + langSpec.getVariableDeclaration(refTypeName, refVarName) + langSpec.getAssignment() + refExp + langSpec.getStatementDelimiter()); +// } +// params.add(refVarName); +// } +// } + if (calleeMethod.getReturnType() == null || langSpec.isVoidType(calleeMethod.getReturnType()) || returnResources == null) { + resourceUpdateMethod.addStatement(langSpec.getMethodInvocation(langSpec.getFieldAccessor(dstNodeName), + calleeMethod.getName(), + params) + langSpec.getStatementDelimiter()); // this.dst.updateSrc(value, refParams); + return null; + } else { + String targetVarName = null; + if (returnResources.size() == 1) { + ResourceNode targetNode = returnResources.get(0); + targetVarName = targetNode.getResource().getResourceName(); + resourceUpdateMethod.addStatement( + langSpec.getVariableDeclaration(calleeMethod.getReturnType().getInterfaceTypeName(), targetVarName) + + langSpec.getAssignment() + + langSpec.getMethodInvocation(langSpec.getFieldAccessor(dstNodeName), + calleeMethod.getName(), + params) + langSpec.getStatementDelimiter()); // ResType res = this.dst.updateSrc(value, refParams); + } else { + targetVarName = getMultipleResourcesVarName(returnResources, langSpec); + VariableDeclaration targetVar = langSpec.newVariableDeclaration(calleeMethod.getReturnType(), targetVarName); + List vars = new ArrayList<>(); + for (ResourceNode rn: returnResources) { + ResourcePath rId = rn.getResource(); + vars.add(langSpec.newVariableDeclaration(rId.getResourceStateType(), rId.getResourceName())); + } + resourceUpdateMethod.addStatement( + langSpec.getDecomposedTuple( + langSpec.getMethodInvocation(langSpec.getFieldAccessor(dstNodeName), calleeMethod.getName(), params), + targetVar, // ResType res = this.dst.updateSrc(value, refParams); + vars)); // Type1 res1 = res.getKey(); Type2 res2 = res.getValue(); + } + return targetVarName; + } + } + + private String addInvocationInMediatorUpdate(MethodDeclaration resourceUpdateMethod, MethodDeclaration calleeMethod, String dstNodeName, List returnResources, ILanguageSpecific langSpec) { + List params = new ArrayList<>(); + if (calleeMethod.getParameters() != null) { + for (VariableDeclaration v: calleeMethod.getParameters()) { + params.add(v.getName()); + } + } + if (calleeMethod.getReturnType() == null || langSpec.isVoidType(calleeMethod.getReturnType()) || returnResources == null ) { + resourceUpdateMethod.addStatement(langSpec.getMethodInvocation(langSpec.getFieldAccessor(dstNodeName), + calleeMethod.getName(), + params) + langSpec.getStatementDelimiter()); // this.dst.updateSrc(value, refParams); + return null; + } else { + String targetVarName = null; + if (returnResources.size() == 1) { + ResourceNode targetNode = returnResources.get(0); + targetVarName = targetNode.getResource().getResourceName(); + resourceUpdateMethod.addStatement( + langSpec.getVariableDeclaration(calleeMethod.getReturnType().getInterfaceTypeName(), targetVarName) + + langSpec.getAssignment() + + langSpec.getMethodInvocation(langSpec.getFieldAccessor(dstNodeName), + calleeMethod.getName(), + params) + langSpec.getStatementDelimiter()); // ResType res = this.dst.updateSrc(value, refParams); + } else { + targetVarName = getMultipleResourcesVarName(returnResources, langSpec); + VariableDeclaration targetVar = langSpec.newVariableDeclaration(calleeMethod.getReturnType(), targetVarName); + List vars = new ArrayList<>(); + for (ResourceNode rn: returnResources) { + ResourcePath rId = rn.getResource(); + vars.add(langSpec.newVariableDeclaration(rId.getResourceStateType(), rId.getResourceName())); + } + resourceUpdateMethod.addStatement( + langSpec.getDecomposedTuple( + langSpec.getMethodInvocation(langSpec.getFieldAccessor(dstNodeName), calleeMethod.getName(), params), + targetVar, // ResType res = this.dst.updateSrc(value, refParams); + vars)); // Type1 res1 = res.getKey(); Type2 res2 = res.getValue(); + } + return targetVarName; + } + } + + private String getMultipleResourcesVarName(List resources, ILanguageSpecific langSpec) { + String varName = null; + for (ResourceNode rn: resources) { + if (varName == null) { + varName = rn.getResource().getResourceName(); + } else { + varName += langSpec.toComponentName(rn.getResource().getResourceName()); + } + } + return varName; + } + + private List getUpdateMethods(TypeDeclaration component) { + List updates = new ArrayList<>(); + for (MethodDeclaration m: component.getMethods()) { + if (m.getName().startsWith(updateMethodName)) { + updates.add(m); + } + } + return updates; + } + + protected IResourceStateAccessor getPullAccessor(final String receiverName, final String getterOfResourceState) { + return new IResourceStateAccessor() { + @Override + public Expression getCurrentStateAccessorFor(ResourcePath target, ResourcePath from) { + if (target.equals(from)) { + return new Field(fieldOfResourceState, + target.getResourceStateType() != null ? target.getResourceStateType() + : DataConstraintModel.typeInt); + } + // for reference channel member + Term getter = new Term(new Symbol(getterOfResourceState, 1, Symbol.Type.METHOD)); + getter.addChild(new Field(receiverName, target.getResourceStateType())); + return getter; + } + + @Override + public Expression getNextStateAccessorFor(ResourcePath target, ResourcePath from) { + Term getter = new Term(new Symbol(getterOfResourceState, 1, Symbol.Type.METHOD)); + getter.addChild(new Field(receiverName, target.getResourceStateType())); + return getter; + } + }; + } + + protected IResourceStateAccessor getPullAccessor(final String resourceAccessor) { + return new IResourceStateAccessor() { + @Override + public Expression getCurrentStateAccessorFor(ResourcePath target, ResourcePath from) { + if (target.equals(from)) { + return new Field(fieldOfResourceState, + target.getResourceStateType() != null ? target.getResourceStateType() + : DataConstraintModel.typeInt); + } + // for reference channel member + Term getter = new Term(new Symbol(getterOfResourceState, 1, Symbol.Type.METHOD)); + getter.addChild(new Field(target.getResourceName(), target.getResourceStateType())); + return getter; + } + + @Override + public Expression getNextStateAccessorFor(ResourcePath target, ResourcePath from) { + return new Constant(resourceAccessor); + } + }; + } +} diff --git a/AlgebraicDataflowArchitectureModel/src/generators/CodeGeneratorFromDataFlowGraph.java b/AlgebraicDataflowArchitectureModel/src/generators/CodeGeneratorFromDataFlowGraph.java new file mode 100644 index 0000000..ce5ab0c --- /dev/null +++ b/AlgebraicDataflowArchitectureModel/src/generators/CodeGeneratorFromDataFlowGraph.java @@ -0,0 +1,412 @@ +package generators; + +import java.util.ArrayList; +import java.util.HashMap; +import java.util.HashSet; +import java.util.List; +import java.util.Map; +import java.util.Set; + +import code.ast.Block; +import code.ast.CompilationUnit; +import code.ast.FieldDeclaration; +import code.ast.MethodDeclaration; +import code.ast.TypeDeclaration; +import code.ast.VariableDeclaration; +import models.Edge; +import models.Node; +import models.algebra.Expression; +import models.algebra.InvalidMessage; +import models.algebra.ParameterizedIdentifierIsFutureWork; +import models.algebra.Term; +import models.algebra.Type; +import models.algebra.UnificationFailed; +import models.algebra.ValueUndefined; +import models.algebra.Variable; +import models.dataConstraintModel.Channel; +import models.dataConstraintModel.ChannelMember; +import models.dataConstraintModel.ResourcePath; +import models.dataFlowModel.DataFlowEdge; +import models.dataFlowModel.DataTransferChannel; +import models.dataFlowModel.DataTransferModel; +import models.dataFlowModel.IFlowGraph; +import models.dataFlowModel.PushPullAttribute; +import models.dataFlowModel.PushPullValue; +import models.dataFlowModel.ResolvingMultipleDefinitionIsFutureWork; +import models.dataFlowModel.ResourceNode; +import models.dataFlowModel.StoreAttribute; +import models.dataFlowModel.DataTransferChannel.IResourceStateAccessor; + +public class CodeGeneratorFromDataFlowGraph extends CodeGenerator { + + public void generateCodeFromFlowGraph(DataTransferModel model, IFlowGraph flowGraph, ArrayList> components, + TypeDeclaration mainComponent, MethodDeclaration mainConstructor, ArrayList codes, ILanguageSpecific langSpec) { + // For each of other components. + for (Set componentNodeSet: components) { + // Declare this resource. + Node componentNode = componentNodeSet.iterator().next(); + ResourceNode resourceNode = (ResourceNode) componentNode; + String resourceName = langSpec.toComponentName(resourceNode.getResource().getResourceName()); + TypeDeclaration component = langSpec.newTypeDeclaration(resourceName); + + // Declare the constructor and the fields to refer to other resources. + List depends = new ArrayList<>(); + MethodDeclaration constructor = declareConstructorAndFieldsToReferToResources(resourceNode, component, depends, langSpec); + + // Update the main component for this component. + updateMainComponent(mainComponent, mainConstructor, componentNode, constructor, langSpec); + + ResourcePath res = resourceNode.getResource(); + Type resStateType = res.getResourceStateType(); + + // Declare the field in this resource to store the state. + if (((StoreAttribute) resourceNode.getAttribute()).isStored()) { + FieldDeclaration stateField = langSpec.newFieldDeclaration(resStateType, fieldOfResourceState, langSpec.getFieldInitializer(resStateType, res.getInitialValue())); + component.addField(stateField); + } + + // Declare the getter method in this resource to obtain the state. + MethodDeclaration getter = declareGetterMethod(resourceNode, component, resStateType, langSpec); + + // Declare the accessor method in the main component to call the getter method. + declareAccessorInMainComponent(mainComponent, res, langSpec); + + // Declare the fields to refer to reference resources. + declareFieldsToReferenceResources(model, resourceNode, component, constructor, depends, langSpec); + + // Declare cache fields and update methods in this resource. + List updates = declareCacheFieldsAndUpdateMethods(resourceNode, component, langSpec); + + // Declare input methods in this component and the main component. + List inputs = declareInputMethodsInThisAndMainComponents(resourceNode, component, mainComponent, model, langSpec); + + if (constructor.getParameters() == null) { + component.removeMethod(constructor); + } + + // Add compilation unit for this component. + CompilationUnit cu = langSpec.newCompilationUnit(component); + codes.add(cu); + } + } + + private MethodDeclaration declareConstructorAndFieldsToReferToResources(ResourceNode resourceNode, TypeDeclaration component, + List depends, ILanguageSpecific langSpec) { + // Declare a constructor in each component. + MethodDeclaration constructor = component.createConstructor(); + Block block = new Block(); + constructor.setBody(block); + + // Declare fields in each component. (for data-flow graph) + for (Edge e: resourceNode.getOutEdges()) { + if (((PushPullAttribute) ((DataFlowEdge) e).getAttribute()).getOptions().get(0) == PushPullValue.PUSH) { + // for PUSH transfer + addReference(component, constructor, e.getDestination(), langSpec); + ResourcePath dstId = ((ResourceNode) e.getDestination()).getResource(); + if (!depends.contains(dstId)) depends.add(dstId); + } + } + for (Edge e: resourceNode.getInEdges()) { + if (((PushPullAttribute) ((DataFlowEdge) e).getAttribute()).getOptions().get(0) != PushPullValue.PUSH) { + // for PULL transfer + addReference(component, constructor, e.getSource(), langSpec); + ResourcePath srcId = ((ResourceNode) e.getSource()).getResource(); + if (!depends.contains(srcId)) depends.add(srcId); + } + } + return constructor; + } + + private MethodDeclaration declareGetterMethod(ResourceNode resourceNode, TypeDeclaration component, Type resStateType, ILanguageSpecific langSpec) { + // Declare the getter method of the resource state. + MethodDeclaration getter = langSpec.newMethodDeclaration(getterOfResourceState, resStateType); + component.addMethod(getter); + + if (((StoreAttribute) resourceNode.getAttribute()).isStored()) { + fillGetterMethodToReturnStateField(getter, resStateType, langSpec); + } else { + // invocations to other getter methods when at least one incoming data-flow edges is PULL-style. + boolean isContainedPush = false; + DataTransferChannel ch = null; + HashMap inputResourceToStateAccessor = new HashMap<>(); + for (Edge eIn: resourceNode.getInEdges()) { + DataFlowEdge dIn = (DataFlowEdge) eIn; + if (((PushPullAttribute) dIn.getAttribute()).getOptions().get(0) == PushPullValue.PUSH) { + // PUSH transfer + isContainedPush = true; + inputResourceToStateAccessor.put(((ResourceNode) dIn.getSource()).getResource(), getPushAccessor()); + } else { + // PULL transfer + inputResourceToStateAccessor.put(((ResourceNode) dIn.getSource()).getResource(), getPullAccessor()); + ch = dIn.getChannel(); + } + } + // for reference channel members. + for (ChannelMember c: ch.getReferenceChannelMembers()) { + inputResourceToStateAccessor.put(c.getResource(), getPullAccessor()); // by pull data transfer + } + + // generate a return statement. + try { + for (ChannelMember out: ch.getOutputChannelMembers()) { + if (out.getResource().equals(resourceNode.getResource())) { + String[] sideEffects = new String[] {""}; + if (!isContainedPush) { + // All incoming edges are in PULL-style. + String curState = ch.deriveUpdateExpressionOf(out, getPullAccessor()).toImplementation(sideEffects); + getter.addStatement(sideEffects[0] + langSpec.getReturnStatement(curState) + langSpec.getStatementDelimiter()); + } else { + // At least one incoming edge is in PUSH-style. + String curState = ch.deriveUpdateExpressionOf(out, getPullAccessor(), inputResourceToStateAccessor).toImplementation(sideEffects); + getter.addStatement(sideEffects[0] + langSpec.getReturnStatement(curState) + langSpec.getStatementDelimiter()); + } + break; + } + } + } catch (ParameterizedIdentifierIsFutureWork | ResolvingMultipleDefinitionIsFutureWork + | InvalidMessage | UnificationFailed | ValueUndefined e) { + e.printStackTrace(); + } + } + + return getter; + } + + private List declareCacheFieldsAndUpdateMethods(ResourceNode resourceNode, TypeDeclaration component, ILanguageSpecific langSpec) { + // Declare cash fields and update methods in the component. + String resComponentName = langSpec.toComponentName(resourceNode.getResource().getResourceName()); + List updateMethods = new ArrayList<>(); + for (Edge e: resourceNode.getInEdges()) { + DataFlowEdge re = (DataFlowEdge) e; + ResourcePath srcRes = ((ResourceNode) re.getSource()).getResource(); + String srcResName = srcRes.getResourceName(); + String srcResComponentName = langSpec.toComponentName(srcResName); + if (((PushPullAttribute) re.getAttribute()).getOptions().get(0) == PushPullValue.PUSH) { + // for push data transfer + + // Declare an update method in the type of the destination resource. + ArrayList vars = new ArrayList<>(); + vars.add(langSpec.newVariableDeclaration(srcRes.getResourceStateType(), srcRes.getResourceName())); + // For the refs. + DataTransferChannel ch = (DataTransferChannel) re.getChannel(); + for (ResourcePath ref: ch.getReferenceResources()) { + if (!ref.equals(resourceNode.getResource())) { + vars.add(langSpec.newVariableDeclaration(ref.getResourceStateType(), ref.getResourceName())); + } + } + MethodDeclaration update = langSpec.newMethodDeclaration(updateMethodName + srcResComponentName, false, null, vars); + component.addMethod(update); + updateMethods.add(update); + + // Add a statement to update the state field + if (((StoreAttribute) resourceNode.getAttribute()).isStored()) { + try { + for (ChannelMember out: re.getChannel().getOutputChannelMembers()) { + if (out.getResource().equals(resourceNode.getResource())) { + Expression updateExp = re.getChannel().deriveUpdateExpressionOf(out, getPushAccessor()); + String[] sideEffects = new String[] {""}; + String curState = updateExp.toImplementation(sideEffects); + String updateStatement; + if (updateExp instanceof Term && ((Term) updateExp).getSymbol().isImplWithSideEffect()) { + updateStatement = sideEffects[0]; + } else { + updateStatement = sideEffects[0] + langSpec.getFieldAccessor(fieldOfResourceState) + langSpec.getAssignment() + curState + langSpec.getStatementDelimiter(); // this.value = ... + } + if (update.getBody() == null || !update.getBody().getStatements().contains(updateStatement)) { + update.addFirstStatement(updateStatement); + } + break; + } + } + } catch (ParameterizedIdentifierIsFutureWork | ResolvingMultipleDefinitionIsFutureWork + | InvalidMessage | UnificationFailed | ValueUndefined e1) { + e1.printStackTrace(); + } + } + + // Declare the field to cache the state of the source resource in the type of the destination resource. + if (resourceNode.getIndegree() > 1) { + // If incoming edges are multiple + if (langSpec.declareField()) { + // Declare the cache field. + FieldDeclaration cacheField = langSpec.newFieldDeclaration( + srcRes.getResourceStateType(), + srcRes.getResourceName(), + langSpec.getFieldInitializer(srcRes.getResourceStateType(), srcRes.getInitialValue())); + component.addField(cacheField); + + } + // Update the cache field. + String cashStatement = langSpec.getFieldAccessor(srcResName) + langSpec.getAssignment() + srcResName + langSpec.getStatementDelimiter(); + if (update.getBody() == null || !update.getBody().getStatements().contains(cashStatement)) { + update.addFirstStatement(cashStatement); + } + } + + // Add an invocation to another update method (for a chain of update method invocations). + for (Edge eOut: resourceNode.getOutEdges()) { + DataFlowEdge dOut = (DataFlowEdge) eOut; + if (((PushPullAttribute) dOut.getAttribute()).getOptions().get(0) == PushPullValue.PUSH) { + // PUSH transfer + Map> referredResources = new HashMap<>(); + List params = new ArrayList<>(); + params.add(langSpec.getFieldAccessor(fieldOfResourceState)); + Set referredSet = referredResources.get(update); + for (ChannelMember rc: re.getChannel().getReferenceChannelMembers()) { + // to get the value of reference member. + ResourcePath ref = rc.getResource(); + if (referredSet == null) { + referredSet = new HashSet<>(); + referredResources.put(update, referredSet); + } + if (!ref.equals(resourceNode.getResource())) { + String refVarName = ref.getResourceName(); + if (!referredSet.contains(ref)) { + referredSet.add(ref); + Expression refGetter = getPullAccessor().getCurrentStateAccessorFor(ref, ((ResourceNode) dOut.getSource()).getResource()); + String[] sideEffects = new String[] {""}; + String refExp = refGetter.toImplementation(sideEffects); + String refTypeName = ref.getResourceStateType().getInterfaceTypeName(); + update.addFirstStatement(sideEffects[0] + langSpec.getVariableDeclaration(refTypeName, refVarName) + langSpec.getAssignment() + refExp + langSpec.getStatementDelimiter()); + } + params.add(refVarName); + } + } + update.addStatement(langSpec.getMethodInvocation(langSpec.getFieldAccessor(((ResourceNode) dOut.getDestination()).getResource().getResourceName()), + updateMethodName + resComponentName, + params) + langSpec.getStatementDelimiter()); // this.dst.updateSrc(value, refParams); + } + } + } + } + return updateMethods; + } + + private List declareInputMethodsInThisAndMainComponents(ResourceNode resourceNode, TypeDeclaration component, + TypeDeclaration mainComponent, DataTransferModel model, ILanguageSpecific langSpec) { + // Declare input methods. + String resName = resourceNode.getResource().getResourceName(); + String resComponentName = langSpec.toComponentName(resName); + List inputMethods = new ArrayList<>(); + for (Channel ch : model.getIOChannels()) { + for (ChannelMember out : ((DataTransferChannel) ch).getOutputChannelMembers()) { + if (out.getResource().equals(resourceNode.getResource())) { + Expression message = out.getStateTransition().getMessageExpression(); + MethodDeclaration input = null; + MethodDeclaration mainInput = null; + if (message instanceof Term) { + // Declare an input method in this component. + ArrayList params = new ArrayList<>(); + for (Variable var: message.getVariables().values()) { + params.add(langSpec.newVariableDeclaration(var.getType(), var.getName())); + } + input = langSpec.newMethodDeclaration(((Term) message).getSymbol().getImplName(), false, null, params); + component.addMethod(input); + inputMethods.add(input); + + // Declare the accessor in the main component to call the input method. + String str = ((Term) message).getSymbol().getImplName(); + mainInput = getMethod(mainComponent, str); + if (mainInput == null) { + mainInput = langSpec.newMethodDeclaration(str, false, null, params); + mainComponent.addMethod(mainInput); + } else { + // Add type to a parameter without type. + if (mainInput.getParameters() != null) { + for (VariableDeclaration param: mainInput.getParameters()) { + if (param.getType() == null) { + for (VariableDeclaration p: params) { + if (param.getName().equals(p.getName()) && p.getType() != null) { + param.setType(p.getType()); + } + } + } + } + } + } + } else if (message instanceof Variable) { + // Declare an input method in this component. + input = langSpec.newMethodDeclaration(((Variable) message).getName(), null); + component.addMethod(input); + inputMethods.add(input); + String str = ((Variable) message).getName(); + + // Declare the accessor in the main component to call the input method. + mainInput = getMethod(mainComponent, str); + if (mainInput == null) { + mainInput = langSpec.newMethodDeclaration(str, null); + mainComponent.addMethod(mainInput); + } + } + + // Add an invocation to the accessor method. + if (mainInput != null) { + List args = new ArrayList<>(); + if (message instanceof Term) { + for (Variable var: message.getVariables().values()) { + args.add(var.getName()); + } + } + mainInput.addStatement(langSpec.getMethodInvocation(langSpec.getFieldAccessor(resName), input.getName(), args) + langSpec.getStatementDelimiter()); + } + + if (input != null) { + // Add a statement to update the state field to the input method. + try { + String[] sideEffects = new String[] {""}; + Expression updateExp; + updateExp = ((DataTransferChannel) ch).deriveUpdateExpressionOf(out, getPullAccessor()); + String newState = updateExp.toImplementation(sideEffects); + String updateStatement; + if (updateExp instanceof Term && ((Term) updateExp).getSymbol().isImplWithSideEffect()) { + updateStatement = sideEffects[0]; + } else { + updateStatement = sideEffects[0] + langSpec.getFieldAccessor(fieldOfResourceState) + langSpec.getAssignment() + newState + langSpec.getStatementDelimiter(); + } + input.addFirstStatement(updateStatement); + } catch (ParameterizedIdentifierIsFutureWork | ResolvingMultipleDefinitionIsFutureWork + | InvalidMessage | UnificationFailed | ValueUndefined e) { + e.printStackTrace(); + } + + // Add an invocation to an update method (for a chain of update method invocations). + for (Edge eOut: resourceNode.getOutEdges()) { + DataFlowEdge dOut = (DataFlowEdge) eOut; + if (((PushPullAttribute) dOut.getAttribute()).getOptions().get(0) == PushPullValue.PUSH) { + // PUSH transfer + Map> referredResources = new HashMap<>(); + List params = new ArrayList<>(); + params.add(langSpec.getFieldAccessor(fieldOfResourceState)); + Set referredSet = referredResources.get(input); + for (ChannelMember rc: ((DataTransferChannel) ch).getReferenceChannelMembers()) { + // to get the value of reference member. + ResourcePath ref = rc.getResource(); + if (referredSet == null) { + referredSet = new HashSet<>(); + referredResources.put(input, referredSet); + } + if (!ref.equals(resourceNode.getResource())) { + String refVarName = ref.getResourceName(); + if (!referredSet.contains(ref)) { + referredSet.add(ref); + Expression refGetter = getPullAccessor().getCurrentStateAccessorFor(ref, ((ResourceNode) dOut.getSource()).getResource()); + String[] sideEffects = new String[] {""}; + String refExp = refGetter.toImplementation(sideEffects); + String refTypeName = ref.getResourceStateType().getInterfaceTypeName(); + input.addFirstStatement(sideEffects[0] + langSpec.getVariableDeclaration(refTypeName, refVarName) + langSpec.getAssignment() + refExp + langSpec.getStatementDelimiter()); + } + params.add(refVarName); + } + } + input.addStatement(langSpec.getMethodInvocation(langSpec.getFieldAccessor(((ResourceNode) dOut.getDestination()).getResource().getResourceName()), + updateMethodName + resComponentName, + params) + langSpec.getStatementDelimiter()); // this.dst.updateSrc(value, refParams); + } + } + } + } + } + } + return inputMethods; + } +} diff --git a/AlgebraicDataflowArchitectureModel/src/generators/ILanguageSpecific.java b/AlgebraicDataflowArchitectureModel/src/generators/ILanguageSpecific.java new file mode 100644 index 0000000..f223c0b --- /dev/null +++ b/AlgebraicDataflowArchitectureModel/src/generators/ILanguageSpecific.java @@ -0,0 +1,45 @@ +package generators; + +import java.util.ArrayList; +import java.util.List; + +import code.ast.CompilationUnit; +import code.ast.FieldDeclaration; +import code.ast.MethodDeclaration; +import code.ast.TypeDeclaration; +import code.ast.VariableDeclaration; +import models.algebra.Expression; +import models.algebra.Type; +import models.dataFlowModel.DataTransferChannel.IResourceStateAccessor; + +public interface ILanguageSpecific { + CompilationUnit newCompilationUnit(TypeDeclaration component); + TypeDeclaration newTypeDeclaration(String typeName); + VariableDeclaration newVariableDeclaration(Type type, String varName); + MethodDeclaration newMethodDeclaration(String methodName, Type returnType); + MethodDeclaration newMethodDeclaration(String methodName, boolean isConstructor, Type returnType, List parameters); + FieldDeclaration newFieldDeclaration(Type fieldType, String fieldName); + FieldDeclaration newFieldDeclaration(Type fieldType, String fieldName, String fieldInitializer); + Type newListType(String compTypeName); + Type newMapType(Type keyType, String compTypeName); + Type newTupleType(List compTypes); + String getVariableDeclaration(String typeName, String varName); + String getFieldInitializer(Type type, Expression initialValue); + boolean declareField(); + String getFieldAccessor(String fieldName); + String getMethodInvocation(String methodName); + String getMethodInvocation(String receivertName, String methodName); + String getMethodInvocation(String receivertName, String methodName, List parameters); + String getConstructorInvocation(String componentName, List parameters); + String getReturnStatement(String returnValue); + String toComponentName(String name); + String toVariableName(String name); + String getMainComponentName(); + String getTupleGet(String tupleExp, int idx, int length); + String getDecomposedTuple(String tupleExp, VariableDeclaration tupleVar, List vars); + String getAssignment(); + String getStatementDelimiter(); + String getStringDelimiter(); + boolean isValueType(Type type); + boolean isVoidType(Type type); +} diff --git a/AlgebraicDataflowArchitectureModel/src/generators/JavaCodeGenerator.java b/AlgebraicDataflowArchitectureModel/src/generators/JavaCodeGenerator.java index 74ed6a8..34590cf 100644 --- a/AlgebraicDataflowArchitectureModel/src/generators/JavaCodeGenerator.java +++ b/AlgebraicDataflowArchitectureModel/src/generators/JavaCodeGenerator.java @@ -23,13 +23,13 @@ import models.algebra.Term; import models.algebra.Type; import models.algebra.Variable; -import models.dataConstraintModel.ChannelGenerator; +import models.dataConstraintModel.Channel; import models.dataConstraintModel.ChannelMember; import models.dataConstraintModel.DataConstraintModel; -import models.dataConstraintModel.IdentifierTemplate; +import models.dataConstraintModel.ResourcePath; import models.dataFlowModel.DataTransferModel; -import models.dataFlowModel.DataTransferChannelGenerator; -import models.dataFlowModel.DataTransferChannelGenerator.IResourceStateAccessor; +import models.dataFlowModel.DataTransferChannel; +import models.dataFlowModel.DataTransferChannel.IResourceStateAccessor; import models.dataFlowModel.PushPullAttribute; import models.dataFlowModel.PushPullValue; import models.dataFlowModel.DataFlowEdge; @@ -76,16 +76,16 @@ // For each resource. for (ResourceNode rn: resources) { boolean f = false; - String resourceName = rn.getIdentifierTemplate().getResourceName().substring(0, 1).toUpperCase() - + rn.getIdentifierTemplate().getResourceName().substring(1); + String resourceName = rn.getResource().getResourceName().substring(0, 1).toUpperCase() + + rn.getResource().getResourceName().substring(1); TypeDeclaration type = new TypeDeclaration(resourceName); // Declare the field to refer to each resource in the main type. String fieldInitializer = "new " + resourceName + "("; - Set depends = new HashSet<>(); + Set depends = new HashSet<>(); for (Edge e : rn.getOutEdges()) { DataFlowEdge re = (DataFlowEdge) e; - IdentifierTemplate dstRes = ((ResourceNode) re.getDestination()).getIdentifierTemplate(); + ResourcePath dstRes = ((ResourceNode) re.getDestination()).getResource(); String resName = dstRes.getResourceName().substring(0, 1).toUpperCase() + dstRes.getResourceName().substring(1); if (((PushPullAttribute) re.getAttribute()).getOptions().get(0) == PushPullValue.PUSH) { depends.add(dstRes); @@ -95,7 +95,7 @@ } for (Edge e : rn.getInEdges()) { DataFlowEdge re = (DataFlowEdge) e; - IdentifierTemplate srcRes = ((ResourceNode) re.getSource()).getIdentifierTemplate(); + ResourcePath srcRes = ((ResourceNode) re.getSource()).getResource(); String resName = srcRes.getResourceName().substring(0, 1).toUpperCase() + srcRes.getResourceName().substring(1); if (((PushPullAttribute) re.getAttribute()).getOptions().get(0) != PushPullValue.PUSH) { depends.add(srcRes); @@ -104,20 +104,20 @@ } else { if (rn.getIndegree() > 1) { // Declare a field to cash the state of the source resource in the type of the destination resource. - IdentifierTemplate cashResId = ((ResourceNode) re.getSource()).getIdentifierTemplate(); + ResourcePath cashResId = ((ResourceNode) re.getSource()).getResource(); type.addField(new FieldDeclaration( - cashResId.getResourceStateType(), ((ResourceNode) re.getSource()).getIdentifierTemplate().getResourceName(), getInitializer(cashResId))); + cashResId.getResourceStateType(), ((ResourceNode) re.getSource()).getResource().getResourceName(), getInitializer(cashResId))); } } } - Set refs = new HashSet<>(); - for (ChannelGenerator cg : model.getChannelGenerators()) { - DataTransferChannelGenerator c = (DataTransferChannelGenerator) cg; - if (c.getInputIdentifierTemplates().contains(rn.getIdentifierTemplate())) { - for (IdentifierTemplate id: c.getReferenceIdentifierTemplates()) { - if (!refs.contains(id) && !depends.contains(id)) { - refs.add(id); - String refResName = id.getResourceName(); + Set refs = new HashSet<>(); + for (Channel ch : model.getChannels()) { + DataTransferChannel c = (DataTransferChannel) ch; + if (c.getInputResources().contains(rn.getResource())) { + for (ResourcePath res: c.getReferenceResources()) { + if (!refs.contains(res) && !depends.contains(res)) { + refs.add(res); + String refResName = res.getResourceName(); fieldInitializer += refResName.toLowerCase() + ","; f = true; } @@ -126,14 +126,14 @@ } if (f) fieldInitializer = fieldInitializer.substring(0, fieldInitializer.length() - 1); fieldInitializer += ")"; - FieldDeclaration field = new FieldDeclaration(new Type(resourceName, resourceName), rn.getIdentifierTemplate().getResourceName()); + FieldDeclaration field = new FieldDeclaration(new Type(resourceName, resourceName), rn.getResource().getResourceName()); mainType.addField(field); - Block manConstructorBody = mainConstructor.getBody(); - if (manConstructorBody == null) { - manConstructorBody = new Block(); - mainConstructor.setBody(manConstructorBody); + Block mainConstructorBody = mainConstructor.getBody(); + if (mainConstructorBody == null) { + mainConstructorBody = new Block(); + mainConstructor.setBody(mainConstructorBody); } - manConstructorBody.addStatement(rn.getIdentifierTemplate().getResourceName() + " = " + fieldInitializer + ";"); + mainConstructorBody.addStatement(rn.getResource().getResourceName() + " = " + fieldInitializer + ";"); // Declare a constructor, fields and update methods in the type of each resource. MethodDeclaration constructor = new MethodDeclaration(resourceName, true); @@ -141,7 +141,7 @@ depends = new HashSet<>(); for (Edge e : rn.getOutEdges()) { DataFlowEdge re = (DataFlowEdge) e; - IdentifierTemplate dstRes = ((ResourceNode) re.getDestination()).getIdentifierTemplate(); + ResourcePath dstRes = ((ResourceNode) re.getDestination()).getResource(); String dstResName = dstRes.getResourceName().substring(0, 1).toUpperCase() + dstRes.getResourceName().substring(1); if (((PushPullAttribute) re.getAttribute()).getOptions().get(0) == PushPullValue.PUSH) { // Declare a field to refer to the destination resource of push transfer. @@ -153,7 +153,7 @@ } for (Edge e : rn.getInEdges()) { DataFlowEdge re = (DataFlowEdge) e; - IdentifierTemplate srcRes = ((ResourceNode) re.getSource()).getIdentifierTemplate(); + ResourcePath srcRes = ((ResourceNode) re.getSource()).getResource(); String srcResName = srcRes.getResourceName().substring(0, 1).toUpperCase() + srcRes.getResourceName().substring(1); if (((PushPullAttribute) re.getAttribute()).getOptions().get(0) != PushPullValue.PUSH) { // Declare a field to refer to the source resource of pull transfer. @@ -165,9 +165,9 @@ // Declare an update method in the type of the destination resource. ArrayList vars = new ArrayList<>(); vars.add(new VariableDeclaration(srcRes.getResourceStateType(), srcRes.getResourceName())); - DataTransferChannelGenerator c = (DataTransferChannelGenerator) re.getChannelGenerator(); - for (IdentifierTemplate ref: c.getReferenceIdentifierTemplates()) { - if (ref != rn.getIdentifierTemplate()) { + DataTransferChannel c = (DataTransferChannel) re.getChannel(); + for (ResourcePath ref: c.getReferenceResources()) { + if (!ref.equals(rn.getResource())) { vars.add(new VariableDeclaration(ref.getResourceStateType(), ref.getResourceName())); } } @@ -176,17 +176,17 @@ } // Declare a field to refer to the reference resource. refs = new HashSet<>(); - for (ChannelGenerator cg : model.getChannelGenerators()) { - DataTransferChannelGenerator c = (DataTransferChannelGenerator) cg; - if (c.getInputIdentifierTemplates().contains(rn.getIdentifierTemplate())) { - for (IdentifierTemplate id: c.getReferenceIdentifierTemplates()) { - if (!refs.contains(id) && !depends.contains(id)) { - refs.add(id); - String refResName = id.getResourceName(); + for (Channel ch : model.getChannels()) { + DataTransferChannel c = (DataTransferChannel) ch; + if (c.getInputResources().contains(rn.getResource())) { + for (ResourcePath res: c.getReferenceResources()) { + if (!refs.contains(res) && !depends.contains(res)) { + refs.add(res); + String refResName = res.getResourceName(); refResName = refResName.substring(0, 1).toUpperCase() + refResName.substring(1); - type.addField(new FieldDeclaration(new Type(refResName, refResName), id.getResourceName())); - constructor.addParameter(new VariableDeclaration(new Type(refResName, refResName), id.getResourceName())); - block.addStatement("this." + id.getResourceName() + " = " + id.getResourceName() + ";"); + type.addField(new FieldDeclaration(new Type(refResName, refResName), res.getResourceName())); + constructor.addParameter(new VariableDeclaration(new Type(refResName, refResName), res.getResourceName())); + block.addStatement("this." + res.getResourceName() + " = " + res.getResourceName() + ";"); } } } @@ -196,11 +196,11 @@ type.addMethod(constructor); // Declare input methods in resources and the main type. - for (ChannelGenerator cg : model.getIOChannelGenerators()) { - for (ChannelMember cm : ((DataTransferChannelGenerator) cg).getOutputChannelMembers()) { - if (cm.getIdentifierTemplate().equals(rn.getIdentifierTemplate())) { + for (Channel ch : model.getIOChannels()) { + for (ChannelMember cm : ((DataTransferChannel) ch).getOutputChannelMembers()) { + if (cm.getResource().equals(rn.getResource())) { Expression message = cm.getStateTransition().getMessageExpression(); - if (message.getClass() == Term.class) { + if (message instanceof Term) { ArrayList params = new ArrayList<>(); for (Variable var: message.getVariables().values()) { params.add(new VariableDeclaration(var.getType(), var.getName())); @@ -226,7 +226,7 @@ } } } - } else if (message.getClass() == Variable.class) { + } else if (message instanceof Variable) { MethodDeclaration input = new MethodDeclaration( ((Variable) cm.getStateTransition().getMessageExpression()).getName(), false, typeVoid, null); @@ -244,13 +244,13 @@ // Declare the field to store the state in the type of each resource. if (((StoreAttribute) rn.getAttribute()).isStored()) { - IdentifierTemplate resId = rn.getIdentifierTemplate(); - type.addField(new FieldDeclaration(resId.getResourceStateType(), "value", getInitializer(resId))); + ResourcePath res = rn.getResource(); + type.addField(new FieldDeclaration(res.getResourceStateType(), "value", getInitializer(res))); } // Declare the getter method to obtain the state in the type of each resource. type.addMethod(new MethodDeclaration("getValue", - rn.getIdentifierTemplate().getResourceStateType())); + rn.getResource().getResourceStateType())); // Add compilation unit for each resource. CompilationUnit cu = new CompilationUnit(type); @@ -262,7 +262,7 @@ boolean isCreatedPair = false; for(ResourceNode rn : resources) { if(isCreatedPair) continue; - if(model.getType("Pair").isAncestorOf(rn.getIdentifierTemplate().getResourceStateType())) { + if(model.getType("Pair").isAncestorOf(rn.getResource().getResourceStateType())) { TypeDeclaration type = new TypeDeclaration("Pair"); type.addField(new FieldDeclaration(new Type("Double", "T"), "left")); type.addField(new FieldDeclaration(new Type("Double", "T"), "right")); @@ -297,12 +297,12 @@ for (Node n : graph.getNodes()) { ResourceNode rn = (ResourceNode) n; MethodDeclaration getter = new MethodDeclaration( - "get" + rn.getIdentifierTemplate().getResourceName().substring(0, 1).toUpperCase() - + rn.getIdentifierTemplate().getResourceName().substring(1), - rn.getIdentifierTemplate().getResourceStateType()); + "get" + rn.getResource().getResourceName().substring(0, 1).toUpperCase() + + rn.getResource().getResourceName().substring(1), + rn.getResource().getResourceStateType()); getter.setBody(new Block()); getter.getBody().addStatement( - "return " + rn.getIdentifierTemplate().getResourceName() + ".getValue();"); + "return " + rn.getResource().getResourceName() + ".getValue();"); mainType.addMethod(getter); } @@ -324,7 +324,7 @@ return codes; } - private static String getInitializer(IdentifierTemplate resId) { + private static String getInitializer(ResourcePath resId) { Type stateType = resId.getResourceStateType(); String initializer = null; if (resId.getInitialValue() != null) { @@ -413,8 +413,8 @@ ResourceNode rn = (ResourceNode) n; for (Edge e : rn.getOutEdges()) { DataFlowEdge re = (DataFlowEdge) e; - for (ChannelMember m: re.getChannelGenerator().getReferenceChannelMembers()) { - if (m.getIdentifierTemplate() == curNode.getIdentifierTemplate()) { + for (ChannelMember m: re.getChannel().getReferenceChannelMembers()) { + if (m.getResource().equals(curNode.getResource())) { topologicalSort(graph, rn, visited, orderedList); } } @@ -432,7 +432,7 @@ static public IResourceStateAccessor pushAccessor = new IResourceStateAccessor() { @Override - public Expression getCurrentStateAccessorFor(IdentifierTemplate target, IdentifierTemplate from) { + public Expression getCurrentStateAccessorFor(ResourcePath target, ResourcePath from) { if (target.equals(from)) { return new Field("value", target.getResourceStateType() != null ? target.getResourceStateType() @@ -445,7 +445,7 @@ } @Override - public Expression getNextStateAccessorFor(IdentifierTemplate target, IdentifierTemplate from) { + public Expression getNextStateAccessorFor(ResourcePath target, ResourcePath from) { return new Parameter(target.getResourceName(), target.getResourceStateType() != null ? target.getResourceStateType() : DataConstraintModel.typeInt); @@ -453,7 +453,7 @@ }; static public IResourceStateAccessor pullAccessor = new IResourceStateAccessor() { @Override - public Expression getCurrentStateAccessorFor(IdentifierTemplate target, IdentifierTemplate from) { + public Expression getCurrentStateAccessorFor(ResourcePath target, ResourcePath from) { if (target.equals(from)) { return new Field("value", target.getResourceStateType() != null ? target.getResourceStateType() @@ -466,7 +466,7 @@ } @Override - public Expression getNextStateAccessorFor(IdentifierTemplate target, IdentifierTemplate from) { + public Expression getNextStateAccessorFor(ResourcePath target, ResourcePath from) { Term getter = new Term(new Symbol("getValue", 1, Symbol.Type.METHOD)); getter.addChild(new Field(target.getResourceName(), target.getResourceStateType())); return getter; diff --git a/AlgebraicDataflowArchitectureModel/src/generators/JavaMethodBodyGenerator.java b/AlgebraicDataflowArchitectureModel/src/generators/JavaMethodBodyGenerator.java index ec17706..1e8aec5 100644 --- a/AlgebraicDataflowArchitectureModel/src/generators/JavaMethodBodyGenerator.java +++ b/AlgebraicDataflowArchitectureModel/src/generators/JavaMethodBodyGenerator.java @@ -21,13 +21,13 @@ import models.algebra.UnificationFailed; import models.algebra.ValueUndefined; import models.algebra.Variable; -import models.dataConstraintModel.ChannelGenerator; +import models.dataConstraintModel.Channel; import models.dataConstraintModel.ChannelMember; import models.dataConstraintModel.DataConstraintModel; -import models.dataConstraintModel.IdentifierTemplate; +import models.dataConstraintModel.ResourcePath; import models.dataFlowModel.DataTransferModel; -import models.dataFlowModel.DataTransferChannelGenerator; -import models.dataFlowModel.DataTransferChannelGenerator.IResourceStateAccessor; +import models.dataFlowModel.DataTransferChannel; +import models.dataFlowModel.DataTransferChannel.IResourceStateAccessor; import models.dataFlowModel.PushPullAttribute; import models.dataFlowModel.PushPullValue; import models.dataFlowModel.ResolvingMultipleDefinitionIsFutureWork; @@ -48,24 +48,24 @@ // Generate the body of each update or getter method. try { - Map> referredResources = new HashMap<>(); + Map> referredResources = new HashMap<>(); for (Edge e: graph.getEdges()) { DataFlowEdge d = (DataFlowEdge) e; PushPullAttribute pushPull = (PushPullAttribute) d.getAttribute(); ResourceNode src = (ResourceNode) d.getSource(); ResourceNode dst = (ResourceNode) d.getDestination(); - String srcResourceName = src.getIdentifierTemplate().getResourceName(); - String dstResourceName = dst.getIdentifierTemplate().getResourceName(); + String srcResourceName = src.getResource().getResourceName(); + String dstResourceName = dst.getResource().getResourceName(); TypeDeclaration srcType = typeMap.get(srcResourceName); TypeDeclaration dstType = typeMap.get(dstResourceName); - for (ChannelMember out: d.getChannelGenerator().getOutputChannelMembers()) { - if (out.getIdentifierTemplate() == dst.getIdentifierTemplate()) { + for (ChannelMember out: d.getChannel().getOutputChannelMembers()) { + if (out.getResource().equals(dst.getResource())) { if (pushPull.getOptions().get(0) == PushPullValue.PUSH && srcType != null) { // for push data transfer MethodDeclaration update = getUpdateMethod(dstType, srcType); if (((StoreAttribute) dst.getAttribute()).isStored()) { // update stored state of dst side resource (when every incoming edge is in push style) - Expression updateExp = d.getChannelGenerator().deriveUpdateExpressionOf(out, JavaCodeGenerator.pushAccessor); + Expression updateExp = d.getChannel().deriveUpdateExpressionOf(out, JavaCodeGenerator.pushAccessor); String[] sideEffects = new String[] {""}; String curState = updateExp.toImplementation(sideEffects); String updateStatement; @@ -89,7 +89,7 @@ if (((StoreAttribute) dst.getAttribute()).isStored()) { // returns the current state stored in a field. if (getter.getBody() == null || getter.getBody().getStatements().size() == 0) { - Type resourceType = dst.getIdentifierTemplate().getResourceStateType(); + Type resourceType = dst.getResource().getResourceStateType(); if (model.isPrimitiveType(resourceType)) { getter.addStatement("return value;"); } else { @@ -111,19 +111,19 @@ // src side (for a chain of update method invocations) for (MethodDeclaration srcUpdate: getUpdateMethods(srcType)) { String refParams = ""; - Set referredSet = referredResources.get(srcUpdate); - for (ChannelMember rc: d.getChannelGenerator().getReferenceChannelMembers()) { + Set referredSet = referredResources.get(srcUpdate); + for (ChannelMember rc: d.getChannel().getReferenceChannelMembers()) { // to get the value of reference member. - IdentifierTemplate ref = rc.getIdentifierTemplate(); + ResourcePath ref = rc.getResource(); if (referredSet == null) { referredSet = new HashSet<>(); referredResources.put(srcUpdate, referredSet); } - if (ref != dst.getIdentifierTemplate()) { + if (!ref.equals(dst.getResource())) { String refVarName = ref.getResourceName(); if (!referredSet.contains(ref)) { referredSet.add(ref); - Expression refGetter = JavaCodeGenerator.pullAccessor.getCurrentStateAccessorFor(ref, src.getIdentifierTemplate()); + Expression refGetter = JavaCodeGenerator.pullAccessor.getCurrentStateAccessorFor(ref, src.getResource()); String[] sideEffects = new String[] {""}; String refExp = refGetter.toImplementation(sideEffects); String refTypeName = ref.getResourceStateType().getInterfaceTypeName(); @@ -136,19 +136,19 @@ } for (MethodDeclaration srcInput: getInputMethods(srcType, src, model)) { String refParams = ""; - Set referredSet = referredResources.get(srcInput); - for (ChannelMember rc: d.getChannelGenerator().getReferenceChannelMembers()) { + Set referredSet = referredResources.get(srcInput); + for (ChannelMember rc: d.getChannel().getReferenceChannelMembers()) { // to get the value of reference member. - IdentifierTemplate ref = rc.getIdentifierTemplate(); + ResourcePath ref = rc.getResource(); if (referredSet == null) { referredSet = new HashSet<>(); referredResources.put(srcInput, referredSet); } - if (ref != dst.getIdentifierTemplate()) { + if (!ref.equals(dst.getResource())) { String refVarName = ref.getResourceName(); if (!referredSet.contains(ref)) { referredSet.add(ref); - Expression refGetter = JavaCodeGenerator.pullAccessor.getCurrentStateAccessorFor(ref, src.getIdentifierTemplate()); + Expression refGetter = JavaCodeGenerator.pullAccessor.getCurrentStateAccessorFor(ref, src.getResource()); String[] sideEffects = new String[] {""}; String refExp = refGetter.toImplementation(sideEffects); String refTypeName = ref.getResourceStateType().getInterfaceTypeName(); @@ -164,29 +164,29 @@ MethodDeclaration getter = getGetterMethod(dstType); if (getter.getBody() == null || getter.getBody().getStatements().size() == 0) { boolean isContainedPush = false; - HashMap inputIdentifierToStateAccessor = new HashMap<>(); + HashMap inputResourceToStateAccessor = new HashMap<>(); for (Edge eIn: dst.getInEdges()) { DataFlowEdge dIn = (DataFlowEdge) eIn; if (((PushPullAttribute) dIn.getAttribute()).getOptions().get(0) == PushPullValue.PUSH) { isContainedPush = true; - inputIdentifierToStateAccessor.put(((ResourceNode) dIn.getSource()).getIdentifierTemplate(), JavaCodeGenerator.pushAccessor); + inputResourceToStateAccessor.put(((ResourceNode) dIn.getSource()).getResource(), JavaCodeGenerator.pushAccessor); } else { - inputIdentifierToStateAccessor.put(((ResourceNode) dIn.getSource()).getIdentifierTemplate(), JavaCodeGenerator.pullAccessor); + inputResourceToStateAccessor.put(((ResourceNode) dIn.getSource()).getResource(), JavaCodeGenerator.pullAccessor); } } // for reference channel members - for (ChannelMember c: d.getChannelGenerator().getReferenceChannelMembers()) { - inputIdentifierToStateAccessor.put(c.getIdentifierTemplate(), JavaCodeGenerator.pullAccessor); // by pull data transfer + for (ChannelMember c: d.getChannel().getReferenceChannelMembers()) { + inputResourceToStateAccessor.put(c.getResource(), JavaCodeGenerator.pullAccessor); // by pull data transfer } String[] sideEffects = new String[] {""}; // generate a return statement. if (!isContainedPush) { // All incoming edges are in PULL style. - String curState = d.getChannelGenerator().deriveUpdateExpressionOf(out, JavaCodeGenerator.pullAccessor).toImplementation(sideEffects); + String curState = d.getChannel().deriveUpdateExpressionOf(out, JavaCodeGenerator.pullAccessor).toImplementation(sideEffects); getter.addStatement(sideEffects[0] + "return " + curState + ";"); } else { // At least one incoming edge is in PUSH style. - String curState = d.getChannelGenerator().deriveUpdateExpressionOf(out, JavaCodeGenerator.pullAccessor, inputIdentifierToStateAccessor).toImplementation(sideEffects); + String curState = d.getChannel().deriveUpdateExpressionOf(out, JavaCodeGenerator.pullAccessor, inputResourceToStateAccessor).toImplementation(sideEffects); getter.addStatement(sideEffects[0] + "return " + curState + ";"); } } @@ -199,13 +199,13 @@ TypeDeclaration mainType = typeMap.get(mainTypeName); for (Node n: graph.getNodes()) { ResourceNode resource = (ResourceNode) n; - String resourceName = resource.getIdentifierTemplate().getResourceName(); + String resourceName = resource.getResource().getResourceName(); TypeDeclaration type = typeMap.get(resourceName); if (type != null) { // getter method MethodDeclaration getter = getGetterMethod(type); if (getter.getBody() == null || getter.getBody().getStatements().size() == 0) { - Type resourceType = resource.getIdentifierTemplate().getResourceStateType(); + Type resourceType = resource.getResource().getResourceStateType(); if (model.isPrimitiveType(resourceType)) { getter.addStatement("return value;"); } else { @@ -224,8 +224,8 @@ } } // methods for input events - Map> ioChannelsAndMembers = getIOChannelsAndMembers(resource, model); - for (Map.Entry> entry: ioChannelsAndMembers.entrySet()) { + Map> ioChannelsAndMembers = getIOChannelsAndMembers(resource, model); + for (Map.Entry> entry: ioChannelsAndMembers.entrySet()) { Set outs = entry.getValue(); for (ChannelMember out: outs) { MethodDeclaration input = getInputMethod(type, out); @@ -293,13 +293,13 @@ return null; } - private static Map> getIOChannelsAndMembers(ResourceNode resource, DataTransferModel model) { - Map> ioChannelsAndMembers = new HashMap<>(); - for (ChannelGenerator c: model.getIOChannelGenerators()) { - DataTransferChannelGenerator ch = (DataTransferChannelGenerator) c; + private static Map> getIOChannelsAndMembers(ResourceNode resource, DataTransferModel model) { + Map> ioChannelsAndMembers = new HashMap<>(); + for (Channel c: model.getIOChannels()) { + DataTransferChannel ch = (DataTransferChannel) c; // I/O channel for (ChannelMember out: ch.getOutputChannelMembers()) { - if (out.getIdentifierTemplate().equals(resource.getIdentifierTemplate())) { + if (out.getResource().equals(resource.getResource())) { if (out.getStateTransition().getMessageExpression() instanceof Term || out.getStateTransition().getMessageExpression() instanceof Variable) { Set channelMembers = ioChannelsAndMembers.get(ch); if (channelMembers == null) { @@ -316,11 +316,11 @@ private static List getInputMethods(TypeDeclaration type, ResourceNode resource, DataTransferModel model) { List inputs = new ArrayList<>(); - for (ChannelGenerator c: model.getIOChannelGenerators()) { - DataTransferChannelGenerator channel = (DataTransferChannelGenerator) c; + for (Channel c: model.getIOChannels()) { + DataTransferChannel channel = (DataTransferChannel) c; // I/O channel for (ChannelMember out: channel.getOutputChannelMembers()) { - if (out.getIdentifierTemplate().equals(resource.getIdentifierTemplate())) { + if (out.getResource().equals(resource.getResource())) { MethodDeclaration input = getInputMethod(type, out); inputs.add(input); } diff --git a/AlgebraicDataflowArchitectureModel/src/generators/JavaSpecific.java b/AlgebraicDataflowArchitectureModel/src/generators/JavaSpecific.java new file mode 100644 index 0000000..b7c56ac --- /dev/null +++ b/AlgebraicDataflowArchitectureModel/src/generators/JavaSpecific.java @@ -0,0 +1,275 @@ +package generators; + +import java.util.ArrayList; +import java.util.List; + +import code.ast.CompilationUnit; +import code.ast.FieldDeclaration; +import code.ast.ImportDeclaration; +import code.ast.MethodDeclaration; +import code.ast.TypeDeclaration; +import code.ast.VariableDeclaration; +import models.algebra.Expression; +import models.algebra.Parameter; +import models.algebra.Term; +import models.algebra.Type; +import models.algebra.Variable; +import models.dataConstraintModel.DataConstraintModel; + +public class JavaSpecific implements ILanguageSpecific { + public static final Type typeVoid = new Type("Void", "void"); + public static final String self = "this"; + + @Override + public CompilationUnit newCompilationUnit(TypeDeclaration component) { + CompilationUnit cu = new CompilationUnit(component); + cu.addImport(new ImportDeclaration("java.util.*")); + return cu; + } + + @Override + public TypeDeclaration newTypeDeclaration(String typeName) { + return new TypeDeclaration(typeName); + } + + @Override + public VariableDeclaration newVariableDeclaration(Type type, String varName) { + return new VariableDeclaration(type, varName); + } + + @Override + public MethodDeclaration newMethodDeclaration(String methodName, Type returnType) { + if (returnType == null) { + returnType = typeVoid; + } + return new MethodDeclaration(methodName, returnType); + } + + @Override + public MethodDeclaration newMethodDeclaration(String methodName, boolean isConstructor, Type returnType, List parameters) { + if (returnType == null) { + returnType = typeVoid; + } + return new MethodDeclaration(methodName, isConstructor, returnType, parameters); + } + + @Override + public FieldDeclaration newFieldDeclaration(Type fieldType, String fieldName) { + return new FieldDeclaration(fieldType, fieldName); + } + + @Override + public FieldDeclaration newFieldDeclaration(Type fieldType, String fieldName, String fieldInitializer) { + return new FieldDeclaration(fieldType, fieldName, fieldInitializer); + } + + @Override + public Type newListType(String compTypeName) { + return new Type("List", "ArrayList<>", "List<" + compTypeName + ">", DataConstraintModel.typeList); + } + + @Override + public Type newMapType(Type keyType, String valueTypeName) { + return new Type("Map", "HashMap<>", "Map<" + keyType.getImplementationTypeName() + ", " + valueTypeName + ">", DataConstraintModel.typeMap); + } + + @Override + public Type newTupleType(List componentTypes) { + String implTypeName = "AbstractMap.SimpleEntry<>"; + String interfaceTypeName = "Map.Entry<$x>"; + if (componentTypes.size() >= 2) { + implTypeName = implTypeName.replace("$x", getImplementationTypeName(componentTypes.get(0)) + "$x"); + interfaceTypeName = interfaceTypeName.replace("$x", getInterfaceTypeName(componentTypes.get(0)) + "$x"); + for (Type argType : componentTypes.subList(1, componentTypes.size() - 1)) { + implTypeName = implTypeName.replace("$x", + ", AbstractMap.SimpleEntry<" + getImplementationTypeName(argType) + "$x>"); + interfaceTypeName = interfaceTypeName.replace("$x", + ", Map.Entry<" + getInterfaceTypeName(argType) + "$x>"); + } + implTypeName = implTypeName.replace("$x", + ", " + getImplementationTypeName(componentTypes.get(componentTypes.size() - 1))); + interfaceTypeName = interfaceTypeName.replace("$x", + ", " + getInterfaceTypeName(componentTypes.get(componentTypes.size() - 1))); + } + Type newTupleType = new Type("Tuple", implTypeName, interfaceTypeName, DataConstraintModel.typeTuple); + return newTupleType; + } + + @Override + public String getVariableDeclaration(String typeName, String varName) { + return typeName + " " + varName; + } + + @Override + public String getFieldInitializer(Type type, Expression initialValue) { + String initializer = null; + if (initialValue != null) { + initializer = initialValue.toImplementation(new String[] {""}); + } else { + if (DataConstraintModel.typeList.isAncestorOf(type)) { + initializer = "new " + type.getImplementationTypeName() + "()"; + } else if (DataConstraintModel.typeMap.isAncestorOf(type)) { + initializer = "new " + type.getImplementationTypeName() + "()"; + } + } + return initializer; + } + + @Override + public boolean declareField() { + return true; + } + + @Override + public String getFieldAccessor(String fieldName) { + return self + "." + fieldName; + } + + @Override + public String getMethodInvocation(String methodName) { + return self + "." + methodName + "()"; + } + + @Override + public String getMethodInvocation(String receiverName, String methodName) { + return receiverName + "." + methodName + "()"; + } + + @Override + public String getMethodInvocation(String receiverName, String methodName, List parameters) { + if (parameters == null) return getMethodInvocation(receiverName, methodName); + String invocation = receiverName + "." + methodName + "("; + if (parameters.size() > 0) { + for (int i = 0; i < parameters.size(); i++) { + if (i < parameters.size() - 1) { + invocation += parameters.get(i) + ", "; + } else { + invocation += parameters.get(i); + } + } + } + invocation += ")"; + return invocation; + } + + @Override + public String getConstructorInvocation(String componentName, List parameters) { + String invocation = "new " + componentName + "("; + if (parameters.size() > 0) { + for (int i = 0; i < parameters.size(); i++) { + if (i < parameters.size() - 1) { + invocation += parameters.get(i) + ", "; + } else { + invocation += parameters.get(i); + } + } + } + invocation += ")"; + return invocation; + } + + @Override + public String getReturnStatement(String returnValue) { + return "return " + returnValue; + } + + @Override + public String toComponentName(String name) { + return name.substring(0, 1).toUpperCase() + name.substring(1); + } + + @Override + public String toVariableName(String name) { + return name.substring(0, 1).toLowerCase() + name.substring(1); + } + + @Override + public String getMainComponentName() { + return "Main"; + } + + @Override + public String getAssignment() { + return " = "; + } + + @Override + public String getStatementDelimiter() { + return ";"; + } + + @Override + public String getStringDelimiter() { + return "\""; + } + + @Override + public String getTupleGet(String tupleExp, int idx, int length) { + Expression t = new Variable(tupleExp, DataConstraintModel.typeTuple); + for (int i = 0; i < idx; i++) { + Term next = new Term(DataConstraintModel.snd); + next.addChild(t); + t = next; + } + if (idx < length - 1) { + Term last = new Term(DataConstraintModel.fst); + last.addChild(t); + t = last; + } + return t.toImplementation(new String[]{}); + } + + @Override + public String getDecomposedTuple(String tupleExp, VariableDeclaration tupleVar, List vars) { + String statements = ""; + statements += getVariableDeclaration(tupleVar.getType().getInterfaceTypeName(), tupleVar.getName()) + + getAssignment() + tupleExp + getStatementDelimiter(); + for (int i = 0; i < vars.size(); i++) { + VariableDeclaration var = vars.get(i); + statements += "\n" + getVariableDeclaration(var.getType().getInterfaceTypeName(), var.getName()) + + getAssignment() + + getTupleGet(tupleVar.getName(), i, vars.size()) + + getStatementDelimiter(); + } + return statements; + } + + @Override + public boolean isValueType(Type type) { + if (type == DataConstraintModel.typeInt + || type == DataConstraintModel.typeLong + || type == DataConstraintModel.typeFloat + || type == DataConstraintModel.typeDouble + || type == DataConstraintModel.typeBoolean) { + return true; + } + return false; + } + + + @Override + public boolean isVoidType(Type type) { + if (type == typeVoid) { + return true; + } + return false; + } + + private String getImplementationTypeName(Type type) { + if (type == null) + return "Object"; + String wrapperType = DataConstraintModel.getWrapperType(type); + if (wrapperType != null) + return wrapperType; + return type.getImplementationTypeName(); + } + + private String getInterfaceTypeName(Type type) { + if (type == null) + return "Object"; + String wrapperType = DataConstraintModel.getWrapperType(type); + if (wrapperType != null) + return wrapperType; + return type.getInterfaceTypeName(); + } +} diff --git a/AlgebraicDataflowArchitectureModel/src/generators/JerseyCodeGenerator.java b/AlgebraicDataflowArchitectureModel/src/generators/JerseyCodeGenerator.java index dcbd48f..d191a18 100644 --- a/AlgebraicDataflowArchitectureModel/src/generators/JerseyCodeGenerator.java +++ b/AlgebraicDataflowArchitectureModel/src/generators/JerseyCodeGenerator.java @@ -21,13 +21,13 @@ import models.algebra.Term; import models.algebra.Type; import models.algebra.Variable; -import models.dataConstraintModel.ChannelGenerator; +import models.dataConstraintModel.Channel; import models.dataConstraintModel.ChannelMember; import models.dataConstraintModel.DataConstraintModel; -import models.dataConstraintModel.IdentifierTemplate; +import models.dataConstraintModel.ResourcePath; import models.dataFlowModel.DataTransferModel; -import models.dataFlowModel.DataTransferChannelGenerator; -import models.dataFlowModel.DataTransferChannelGenerator.IResourceStateAccessor; +import models.dataFlowModel.DataTransferChannel; +import models.dataFlowModel.DataTransferChannel.IResourceStateAccessor; import models.dataFlowModel.PushPullAttribute; import models.dataFlowModel.PushPullValue; import models.dataFlowModel.DataFlowEdge; @@ -66,13 +66,13 @@ for (Node n : resources) { ResourceNode rn = (ResourceNode) n; - String resourceName = rn.getIdentifierTemplate().getResourceName().substring(0, 1).toUpperCase() - + rn.getIdentifierTemplate().getResourceName().substring(1); + String resourceName = rn.getResource().getResourceName().substring(0, 1).toUpperCase() + + rn.getResource().getResourceName().substring(1); // Declare the field to refer each resource in the main type. TypeDeclaration type = new TypeDeclaration(resourceName); type.addAnnotation(new Annotation("Component")); - type.addAnnotation(new Annotation("Path", "\"/" + rn.getIdentifierTemplate().getResourceName() + "\"")); + type.addAnnotation(new Annotation("Path", "\"/" + rn.getResource().getResourceName() + "\"")); // Declare a client field and update methods from other resources. boolean bDeclareClientField = false; @@ -86,7 +86,7 @@ } for (Edge e : rn.getInEdges()) { DataFlowEdge re = (DataFlowEdge) e; - IdentifierTemplate srcRes = ((ResourceNode) re.getSource()).getIdentifierTemplate(); + ResourcePath srcRes = ((ResourceNode) re.getSource()).getResource(); String srcResName = srcRes.getResourceName().substring(0, 1).toUpperCase() + srcRes.getResourceName().substring(1); if (((PushPullAttribute) re.getAttribute()).getOptions().get(0) != PushPullValue.PUSH) { if (!bDeclareClientField) { @@ -102,16 +102,16 @@ VariableDeclaration param = new VariableDeclaration(srcType, srcName); param.addAnnotation(new Annotation("FormParam", "\"" + srcName + "\"")); vars.add(param); - for (IdentifierTemplate refRes: re.getChannelGenerator().getReferenceIdentifierTemplates()) { - if (refRes != rn.getIdentifierTemplate()) { + for (ResourcePath refRes: re.getChannel().getReferenceResources()) { + if (!refRes.equals(rn.getResource())) { param = new VariableDeclaration(refRes.getResourceStateType(), refRes.getResourceName()); param.addAnnotation(new Annotation("FormParam", "\"" + refRes.getResourceName() + "\"")); vars.add(param); } } MethodDeclaration update = new MethodDeclaration("update" + srcResName, false, typeVoid, vars); - for (ChannelMember cm: re.getChannelGenerator().getOutputChannelMembers()) { - if (cm.getIdentifierTemplate() == rn.getIdentifierTemplate()) { + for (ChannelMember cm: re.getChannel().getOutputChannelMembers()) { + if (cm.getResource().equals(rn.getResource())) { if (cm.getStateTransition().isRightUnary()) { update.addAnnotation(new Annotation("PUT")); } else { @@ -123,7 +123,7 @@ // For each source resource, a child resource is defined in the destination resource so that its state can be updated separately. update.addAnnotation(new Annotation("Path", "\"/" + srcName + "\"")); // Declare a field to cash the state of the source resource in the type of the destination resource. - IdentifierTemplate cashResId = ((ResourceNode) re.getSource()).getIdentifierTemplate(); + ResourcePath cashResId = ((ResourceNode) re.getSource()).getResource(); type.addField(new FieldDeclaration(cashResId.getResourceStateType(), srcName, getInitializer(cashResId))); } type.addMethod(update); @@ -149,11 +149,11 @@ // } // Declare input methods in resources. - for (ChannelGenerator cg : model.getIOChannelGenerators()) { - for (ChannelMember cm : ((DataTransferChannelGenerator) cg).getOutputChannelMembers()) { - if (cm.getIdentifierTemplate().equals(rn.getIdentifierTemplate())) { + for (Channel ch : model.getIOChannels()) { + for (ChannelMember cm : ((DataTransferChannel) ch).getOutputChannelMembers()) { + if (cm.getResource().equals(rn.getResource())) { Expression message = cm.getStateTransition().getMessageExpression(); - if (message.getClass() == Term.class) { + if (message instanceof Term) { ArrayList params = new ArrayList<>(); for (Variable var: message.getVariables().values()) { String paramName = var.getName(); @@ -170,7 +170,7 @@ input.addAnnotation(new Annotation("POST")); } type.addMethod(input); - } else if (message.getClass() == Variable.class) { + } else if (message instanceof Variable) { MethodDeclaration input = new MethodDeclaration( ((Variable) cm.getStateTransition().getMessageExpression()).getName(), false, typeVoid, null); @@ -187,12 +187,12 @@ // Declare the field to store the state in the type of each resource. if (((StoreAttribute) rn.getAttribute()).isStored()) { - IdentifierTemplate resId = rn.getIdentifierTemplate(); - type.addField(new FieldDeclaration(resId.getResourceStateType(), "value", getInitializer(resId))); + ResourcePath res = rn.getResource(); + type.addField(new FieldDeclaration(res.getResourceStateType(), "value", getInitializer(res))); } // Declare the getter method to obtain the state in the type of each resource. - MethodDeclaration getter = new MethodDeclaration("getValue", rn.getIdentifierTemplate().getResourceStateType()); + MethodDeclaration getter = new MethodDeclaration("getValue", rn.getResource().getResourceStateType()); getter.addAnnotation(new Annotation("Produces", "MediaType.APPLICATION_JSON")); getter.addAnnotation(new Annotation("GET")); type.addMethod(getter); @@ -214,7 +214,7 @@ for(Node n : resources) { ResourceNode rn = (ResourceNode) n; if(isCreatedPair) continue; - if(model.getType("Pair").isAncestorOf(rn.getIdentifierTemplate().getResourceStateType())) { + if(model.getType("Pair").isAncestorOf(rn.getResource().getResourceStateType())) { TypeDeclaration type = new TypeDeclaration("Pair"); type.addField(new FieldDeclaration(new Type("Double", "T"), "left")); type.addField(new FieldDeclaration(new Type("Double", "T"), "right")); @@ -254,7 +254,7 @@ return codes; } - private static String getInitializer(IdentifierTemplate resId) { + private static String getInitializer(ResourcePath resId) { Type stateType = resId.getResourceStateType(); String initializer = null; if (resId.getInitialValue() != null) { @@ -316,7 +316,7 @@ static public IResourceStateAccessor pushAccessor = new IResourceStateAccessor() { @Override - public Expression getCurrentStateAccessorFor(IdentifierTemplate target, IdentifierTemplate from) { + public Expression getCurrentStateAccessorFor(ResourcePath target, ResourcePath from) { if (target.equals(from)) { return new Field("value", target.getResourceStateType() != null ? target.getResourceStateType() @@ -326,7 +326,7 @@ } @Override - public Expression getNextStateAccessorFor(IdentifierTemplate target, IdentifierTemplate from) { + public Expression getNextStateAccessorFor(ResourcePath target, ResourcePath from) { return new Parameter(target.getResourceName(), target.getResourceStateType() != null ? target.getResourceStateType() : DataConstraintModel.typeInt); @@ -334,7 +334,7 @@ }; static public IResourceStateAccessor pullAccessor = new IResourceStateAccessor() { @Override - public Expression getCurrentStateAccessorFor(IdentifierTemplate target, IdentifierTemplate from) { + public Expression getCurrentStateAccessorFor(ResourcePath target, ResourcePath from) { if (target.equals(from)) { return new Field("value", target.getResourceStateType() != null ? target.getResourceStateType() @@ -347,7 +347,7 @@ } @Override - public Expression getNextStateAccessorFor(IdentifierTemplate target, IdentifierTemplate from) { + public Expression getNextStateAccessorFor(ResourcePath target, ResourcePath from) { return new Parameter(target.getResourceName(), target.getResourceStateType() != null ? target.getResourceStateType() : DataConstraintModel.typeInt); diff --git a/AlgebraicDataflowArchitectureModel/src/generators/JerseyMethodBodyGenerator.java b/AlgebraicDataflowArchitectureModel/src/generators/JerseyMethodBodyGenerator.java index 6fe0efd..9ad2995 100644 --- a/AlgebraicDataflowArchitectureModel/src/generators/JerseyMethodBodyGenerator.java +++ b/AlgebraicDataflowArchitectureModel/src/generators/JerseyMethodBodyGenerator.java @@ -24,12 +24,12 @@ import models.algebra.UnificationFailed; import models.algebra.ValueUndefined; import models.algebra.Variable; -import models.dataConstraintModel.ChannelGenerator; +import models.dataConstraintModel.Channel; import models.dataConstraintModel.ChannelMember; import models.dataConstraintModel.DataConstraintModel; -import models.dataConstraintModel.IdentifierTemplate; +import models.dataConstraintModel.ResourcePath; import models.dataFlowModel.DataTransferModel; -import models.dataFlowModel.DataTransferChannelGenerator; +import models.dataFlowModel.DataTransferChannel; import models.dataFlowModel.PushPullAttribute; import models.dataFlowModel.PushPullValue; import models.dataFlowModel.ResolvingMultipleDefinitionIsFutureWork; @@ -37,7 +37,7 @@ import models.dataFlowModel.DataFlowGraph; import models.dataFlowModel.ResourceNode; import models.dataFlowModel.StoreAttribute; -import models.dataFlowModel.DataTransferChannelGenerator.IResourceStateAccessor; +import models.dataFlowModel.DataTransferChannel.IResourceStateAccessor; public class JerseyMethodBodyGenerator { private static String baseURL = "http://localhost:8080"; @@ -54,37 +54,37 @@ // Generate the body of each update or getter method. try { Set chainedCalls = new HashSet<>(); - Map> referredResources = new HashMap<>(); + Map> referredResources = new HashMap<>(); for (Edge e: graph.getEdges()) { DataFlowEdge d = (DataFlowEdge) e; PushPullAttribute pushPull = (PushPullAttribute) d.getAttribute(); ResourceNode src = (ResourceNode) d.getSource(); ResourceNode dst = (ResourceNode) d.getDestination(); - String srcResourceName = src.getIdentifierTemplate().getResourceName(); - String dstResourceName = dst.getIdentifierTemplate().getResourceName(); + String srcResourceName = src.getResource().getResourceName(); + String dstResourceName = dst.getResource().getResourceName(); TypeDeclaration srcType = typeMap.get(srcResourceName); TypeDeclaration dstType = typeMap.get(dstResourceName); - for (ChannelMember out: d.getChannelGenerator().getOutputChannelMembers()) { - if (out.getIdentifierTemplate() == dst.getIdentifierTemplate()) { + for (ChannelMember out: d.getChannel().getOutputChannelMembers()) { + if (out.getResource().equals(dst.getResource())) { if (pushPull.getOptions().get(0) == PushPullValue.PUSH && srcType != null) { // for push data transfer MethodDeclaration update = getUpdateMethod(dstType, srcType); if (((StoreAttribute) dst.getAttribute()).isStored()) { // update stored state of dst side resource (when every incoming edge is in push style) Expression updateExp = null; - if (d.getChannelGenerator().getReferenceChannelMembers().size() == 0) { - updateExp = d.getChannelGenerator().deriveUpdateExpressionOf(out, JerseyCodeGenerator.pushAccessor); + if (d.getChannel().getReferenceChannelMembers().size() == 0) { + updateExp = d.getChannel().deriveUpdateExpressionOf(out, JerseyCodeGenerator.pushAccessor); } else { // if there exists one or more reference channel member. - HashMap inputIdentifierToStateAccessor = new HashMap<>(); + HashMap inputResourceToStateAccessor = new HashMap<>(); for (Edge eIn: dst.getInEdges()) { DataFlowEdge dIn = (DataFlowEdge) eIn; - inputIdentifierToStateAccessor.put(((ResourceNode) dIn.getSource()).getIdentifierTemplate(), JerseyCodeGenerator.pushAccessor); + inputResourceToStateAccessor.put(((ResourceNode) dIn.getSource()).getResource(), JerseyCodeGenerator.pushAccessor); } - for (ChannelMember c: d.getChannelGenerator().getReferenceChannelMembers()) { - inputIdentifierToStateAccessor.put(c.getIdentifierTemplate(), JerseyCodeGenerator.pullAccessor); + for (ChannelMember c: d.getChannel().getReferenceChannelMembers()) { + inputResourceToStateAccessor.put(c.getResource(), JerseyCodeGenerator.pullAccessor); } - updateExp = d.getChannelGenerator().deriveUpdateExpressionOf(out, JerseyCodeGenerator.pushAccessor, inputIdentifierToStateAccessor); + updateExp = d.getChannel().deriveUpdateExpressionOf(out, JerseyCodeGenerator.pushAccessor, inputResourceToStateAccessor); } String[] sideEffects = new String[] {""}; String curState = updateExp.toImplementation(sideEffects); @@ -187,16 +187,16 @@ for (MethodDeclaration srcUpdate: getUpdateMethods(srcType)) { if (srcUpdate != null) { List>> params = new ArrayList<>(); - Set referredSet = referredResources.get(srcUpdate); - if (d.getChannelGenerator().getReferenceChannelMembers().size() > 0) { - for (ChannelMember rc: d.getChannelGenerator().getReferenceChannelMembers()) { + Set referredSet = referredResources.get(srcUpdate); + if (d.getChannel().getReferenceChannelMembers().size() > 0) { + for (ChannelMember rc: d.getChannel().getReferenceChannelMembers()) { // For each reference channel member, get the current state of the reference side resource by pull data transfer. - IdentifierTemplate ref = rc.getIdentifierTemplate(); + ResourcePath ref = rc.getResource(); if (referredSet == null) { referredSet = new HashSet<>(); referredResources.put(srcUpdate, referredSet); } - if (ref != dst.getIdentifierTemplate()) { + if (!ref.equals(dst.getResource())) { String refResourceName = ref.getResourceName(); Type refResourceType = ref.getResourceStateType(); if (!referredSet.contains(ref)) { @@ -215,14 +215,14 @@ if (!chainedCalls.contains(srcUpdate)) { // The first call to an update method in this method // Value of the source side (input side) resource. - params.add(0, new AbstractMap.SimpleEntry<>(src.getIdentifierTemplate().getResourceStateType(), new AbstractMap.SimpleEntry<>(srcResourceName, "this.value"))); + params.add(0, new AbstractMap.SimpleEntry<>(src.getResource().getResourceStateType(), new AbstractMap.SimpleEntry<>(srcResourceName, "this.value"))); srcUpdate.addStatement(getHttpMethodParamsStatement(srcType.getTypeName(), params, true)); srcUpdate.addStatement("String result = " + getHttpMethodCallStatement(baseURL, dstResourceName, srcResName, httpMethod)); chainedCalls.add(srcUpdate); } else { // After the second time of call to update methods in this method // Value of the source side (input side) resource. - params.add(0, new AbstractMap.SimpleEntry<>(src.getIdentifierTemplate().getResourceStateType(), new AbstractMap.SimpleEntry<>(srcResourceName, "this.value"))); + params.add(0, new AbstractMap.SimpleEntry<>(src.getResource().getResourceStateType(), new AbstractMap.SimpleEntry<>(srcResourceName, "this.value"))); srcUpdate.addStatement(getHttpMethodParamsStatement(srcType.getTypeName(), params, false)); srcUpdate.addStatement("result = " + getHttpMethodCallStatement(baseURL, dstResourceName, srcResName, httpMethod)); } @@ -231,15 +231,15 @@ } for (MethodDeclaration srcInput: getInputMethods(srcType, src, model)) { List>> params = new ArrayList<>(); - Set referredSet = referredResources.get(srcInput); - for (ChannelMember rc: d.getChannelGenerator().getReferenceChannelMembers()) { + Set referredSet = referredResources.get(srcInput); + for (ChannelMember rc: d.getChannel().getReferenceChannelMembers()) { // For each reference channel member, get the current state of the reference side resource by pull data transfer. - IdentifierTemplate ref = rc.getIdentifierTemplate(); + ResourcePath ref = rc.getResource(); if (referredSet == null) { referredSet = new HashSet<>(); referredResources.put(srcInput, referredSet); } - if (ref != dst.getIdentifierTemplate()) { + if (!ref.equals(dst.getResource())) { String refResourceName = ref.getResourceName(); Type refResourceType = ref.getResourceStateType(); if (!referredSet.contains(ref)) { @@ -257,14 +257,14 @@ if (!chainedCalls.contains(srcInput)) { // First call to an update method in this method // Value of the source side (input side) resource. - params.add(0, new AbstractMap.SimpleEntry<>(src.getIdentifierTemplate().getResourceStateType(), new AbstractMap.SimpleEntry<>(srcResourceName, "this.value"))); + params.add(0, new AbstractMap.SimpleEntry<>(src.getResource().getResourceStateType(), new AbstractMap.SimpleEntry<>(srcResourceName, "this.value"))); srcInput.addStatement(getHttpMethodParamsStatement(srcType.getTypeName(), params, true)); srcInput.addStatement("String result = " + getHttpMethodCallStatement(baseURL, dstResourceName, srcResName, httpMethod)); chainedCalls.add(srcInput); } else { // After the second time of call to update methods in this method // Value of the source side (input side) resource. - params.add(0, new AbstractMap.SimpleEntry<>(src.getIdentifierTemplate().getResourceStateType(), new AbstractMap.SimpleEntry<>(srcResourceName, "this.value"))); + params.add(0, new AbstractMap.SimpleEntry<>(src.getResource().getResourceStateType(), new AbstractMap.SimpleEntry<>(srcResourceName, "this.value"))); srcInput.addStatement(getHttpMethodParamsStatement(srcType.getTypeName(), params, false)); srcInput.addStatement("result = " + getHttpMethodCallStatement(baseURL, dstResourceName, srcResName, httpMethod)); } @@ -276,17 +276,17 @@ if (getter.getBody() == null || getter.getBody().getStatements().size() == 0) { // generate a return statement. String[] sideEffects = new String[] {""}; - String curState = d.getChannelGenerator().deriveUpdateExpressionOf(out, JerseyCodeGenerator.pullAccessor).toImplementation(sideEffects); // no pull data transfer is included. + String curState = d.getChannel().deriveUpdateExpressionOf(out, JerseyCodeGenerator.pullAccessor).toImplementation(sideEffects); // no pull data transfer is included. getter.addStatement(sideEffects[0] + "return " + curState + ";"); // For each reference channel member, get the current state of the reference side resource by pull data transfer. - for (ChannelMember c: d.getChannelGenerator().getReferenceChannelMembers()) { - String refResourceName = c.getIdentifierTemplate().getResourceName(); - Type refResourceType = c.getIdentifierTemplate().getResourceStateType(); + for (ChannelMember c: d.getChannel().getReferenceChannelMembers()) { + String refResourceName = c.getResource().getResourceName(); + Type refResourceType = c.getResource().getResourceStateType(); generatePullDataTransfer(getter, refResourceName, refResourceType); } } // get src side resource state by pull data transfer. - Type srcResourceType = src.getIdentifierTemplate().getResourceStateType(); + Type srcResourceType = src.getResource().getResourceStateType(); generatePullDataTransfer(getter, srcResourceName, srcResourceType); } } @@ -295,7 +295,7 @@ // for source nodes for (Node n: graph.getNodes()) { ResourceNode resource = (ResourceNode) n; - String resourceName = resource.getIdentifierTemplate().getResourceName(); + String resourceName = resource.getResource().getResourceName(); TypeDeclaration type = typeMap.get(resourceName); if (type != null) { // getter method @@ -304,8 +304,8 @@ getter.addStatement("return value;"); } // methods for input events - Map> ioChannelsAndMembers = getIOChannelsAndMembers(resource, model); - for (Map.Entry> entry: ioChannelsAndMembers.entrySet()) { + Map> ioChannelsAndMembers = getIOChannelsAndMembers(resource, model); + for (Map.Entry> entry: ioChannelsAndMembers.entrySet()) { Set outs = entry.getValue(); for (ChannelMember out: outs) { MethodDeclaration input = getInputMethod(type, out); @@ -540,13 +540,13 @@ return null; } - private static Map> getIOChannelsAndMembers(ResourceNode resource, DataTransferModel model) { - Map> ioChannelsAndMembers = new HashMap<>(); - for (ChannelGenerator c: model.getIOChannelGenerators()) { - DataTransferChannelGenerator ch = (DataTransferChannelGenerator) c; + private static Map> getIOChannelsAndMembers(ResourceNode resource, DataTransferModel model) { + Map> ioChannelsAndMembers = new HashMap<>(); + for (Channel c: model.getIOChannels()) { + DataTransferChannel ch = (DataTransferChannel) c; // I/O channel for (ChannelMember out: ch.getOutputChannelMembers()) { - if (out.getIdentifierTemplate().equals(resource.getIdentifierTemplate())) { + if (out.getResource().equals(resource.getResource())) { if (out.getStateTransition().getMessageExpression() instanceof Term || out.getStateTransition().getMessageExpression() instanceof Variable) { Set channelMembers = ioChannelsAndMembers.get(ch); if (channelMembers == null) { @@ -563,11 +563,11 @@ private static List getInputMethods(TypeDeclaration type, ResourceNode resource, DataTransferModel model) { List inputs = new ArrayList<>(); - for (ChannelGenerator c: model.getIOChannelGenerators()) { - DataTransferChannelGenerator channel = (DataTransferChannelGenerator) c; + for (Channel c: model.getIOChannels()) { + DataTransferChannel channel = (DataTransferChannel) c; // I/O channel for (ChannelMember out: channel.getOutputChannelMembers()) { - if (out.getIdentifierTemplate().equals(resource.getIdentifierTemplate())) { + if (out.getResource().equals(resource.getResource())) { MethodDeclaration input = getInputMethod(type, out); inputs.add(input); } diff --git a/AlgebraicDataflowArchitectureModel/src/graphicalrefactor/actions/AbstractEditorAction.java b/AlgebraicDataflowArchitectureModel/src/graphicalrefactor/actions/AbstractEditorAction.java deleted file mode 100644 index c473f18..0000000 --- a/AlgebraicDataflowArchitectureModel/src/graphicalrefactor/actions/AbstractEditorAction.java +++ /dev/null @@ -1,23 +0,0 @@ -package graphicalrefactor.actions; - -import javax.swing.AbstractAction; -import javax.swing.Icon; - -import com.mxgraph.view.mxGraph; - -import graphicalrefactor.editor.Editor; - -public abstract class AbstractEditorAction extends AbstractAction { - - protected Editor editor; - - public AbstractEditorAction(String name, Editor editor) { - super(name); - this.editor = editor; - } - - public void setEditor(Editor editor) { - this.editor = editor; - } - -} \ No newline at end of file diff --git a/AlgebraicDataflowArchitectureModel/src/graphicalrefactor/actions/AbstractSystemAction.java b/AlgebraicDataflowArchitectureModel/src/graphicalrefactor/actions/AbstractSystemAction.java deleted file mode 100644 index e3f827d..0000000 --- a/AlgebraicDataflowArchitectureModel/src/graphicalrefactor/actions/AbstractSystemAction.java +++ /dev/null @@ -1,23 +0,0 @@ -package graphicalrefactor.actions; - -import java.awt.event.ActionEvent; - -import javax.swing.AbstractAction; - -import graphicalrefactor.editor.Editor; -import graphicalrefactor.views.GraphicalRefactor; - -public abstract class AbstractSystemAction extends AbstractAction { - - protected GraphicalRefactor frame; - - public AbstractSystemAction(String name, GraphicalRefactor frame) { - super(name); - this.frame = frame; - } - - public void setFrame(GraphicalRefactor frame) { - this.frame = frame; - } - -} diff --git a/AlgebraicDataflowArchitectureModel/src/graphicalrefactor/actions/AbstractViewerAction.java b/AlgebraicDataflowArchitectureModel/src/graphicalrefactor/actions/AbstractViewerAction.java deleted file mode 100644 index 13c4a07..0000000 --- a/AlgebraicDataflowArchitectureModel/src/graphicalrefactor/actions/AbstractViewerAction.java +++ /dev/null @@ -1,17 +0,0 @@ -package graphicalrefactor.actions; - -import java.awt.event.ActionEvent; - -import javax.swing.AbstractAction; - -import com.mxgraph.swing.mxGraphComponent; - -public abstract class AbstractViewerAction extends AbstractAction { - - protected mxGraphComponent graphComponent = null; - - public AbstractViewerAction(String name, mxGraphComponent graphComponent) { - super(name); - this.graphComponent = graphComponent; - } -} diff --git a/AlgebraicDataflowArchitectureModel/src/graphicalrefactor/actions/CircleLayoutAction.java b/AlgebraicDataflowArchitectureModel/src/graphicalrefactor/actions/CircleLayoutAction.java deleted file mode 100644 index 07f3b7b..0000000 --- a/AlgebraicDataflowArchitectureModel/src/graphicalrefactor/actions/CircleLayoutAction.java +++ /dev/null @@ -1,18 +0,0 @@ -package graphicalrefactor.actions; - -import java.awt.event.ActionEvent; - -import graphicalrefactor.editor.Editor; - -public class CircleLayoutAction extends AbstractEditorAction { - - public CircleLayoutAction(Editor editor) { - super("Circle Layout", editor); - } - - @Override - public void actionPerformed(ActionEvent e) { - editor.setCircleLayout(); - } - -} diff --git a/AlgebraicDataflowArchitectureModel/src/graphicalrefactor/actions/DAGLayoutAction.java b/AlgebraicDataflowArchitectureModel/src/graphicalrefactor/actions/DAGLayoutAction.java deleted file mode 100644 index db8bb5d..0000000 --- a/AlgebraicDataflowArchitectureModel/src/graphicalrefactor/actions/DAGLayoutAction.java +++ /dev/null @@ -1,17 +0,0 @@ -package graphicalrefactor.actions; - -import java.awt.event.ActionEvent; -import graphicalrefactor.editor.Editor; - -public class DAGLayoutAction extends AbstractEditorAction { - - public DAGLayoutAction(Editor editor) { - super("DAG Layout", editor); - } - - @Override - public void actionPerformed(ActionEvent e) { - editor.setDAGLayout(); - } - -} diff --git a/AlgebraicDataflowArchitectureModel/src/graphicalrefactor/actions/DeleteAction.java b/AlgebraicDataflowArchitectureModel/src/graphicalrefactor/actions/DeleteAction.java deleted file mode 100644 index 1ac8a47..0000000 --- a/AlgebraicDataflowArchitectureModel/src/graphicalrefactor/actions/DeleteAction.java +++ /dev/null @@ -1,23 +0,0 @@ -package graphicalrefactor.actions; - -import java.awt.event.ActionEvent; - -import graphicalrefactor.editor.Editor; - -public class DeleteAction extends AbstractEditorAction { - - /** - * - */ - private static final long serialVersionUID = -4410145389391154784L; - - public DeleteAction(Editor editor) { - super("Delete", editor); - } - - @Override - public void actionPerformed(ActionEvent e) { - editor.delete(); - } - -} diff --git a/AlgebraicDataflowArchitectureModel/src/graphicalrefactor/actions/ExitAction.java b/AlgebraicDataflowArchitectureModel/src/graphicalrefactor/actions/ExitAction.java deleted file mode 100644 index c18a6c5..0000000 --- a/AlgebraicDataflowArchitectureModel/src/graphicalrefactor/actions/ExitAction.java +++ /dev/null @@ -1,22 +0,0 @@ -package graphicalrefactor.actions; - -import java.awt.event.ActionEvent; - -import javax.swing.AbstractAction; - -public class ExitAction extends AbstractAction { - /** - * - */ - private static final long serialVersionUID = -8733766417378036850L; - - public ExitAction() { - super("Exit"); - } - - @Override - public void actionPerformed(ActionEvent e) { - System.exit(0); - } - -} diff --git a/AlgebraicDataflowArchitectureModel/src/graphicalrefactor/actions/JavaPrototypeGenerateAction.java b/AlgebraicDataflowArchitectureModel/src/graphicalrefactor/actions/JavaPrototypeGenerateAction.java deleted file mode 100644 index 60ca2f1..0000000 --- a/AlgebraicDataflowArchitectureModel/src/graphicalrefactor/actions/JavaPrototypeGenerateAction.java +++ /dev/null @@ -1,89 +0,0 @@ -package graphicalrefactor.actions; - -import java.awt.event.ActionEvent; -import java.io.BufferedReader; -import java.io.BufferedWriter; -import java.io.File; -import java.io.FileReader; -import java.io.FileWriter; -import java.io.IOException; - -import javax.swing.JFileChooser; - -import algorithms.*; -import code.ast.*; -import generators.DataTransferMethodAnalyzer; -import generators.JavaCodeGenerator; -import generators.JavaMethodBodyGenerator; -import graphicalrefactor.editor.Editor; -import models.dataConstraintModel.IdentifierTemplate; -import models.dataFlowModel.DataTransferModel; -import models.dataFlowModel.ModelExtension; -import models.dataFlowModel.DataFlowGraph; - -public class JavaPrototypeGenerateAction extends AbstractEditorAction { - /** - * - */ - private static final long serialVersionUID = -3694103632055735068L; - - private String lastDir = null; - - public JavaPrototypeGenerateAction(Editor editor) { - super("Generate Plain Java Prototype", editor); - } - - @Override - public void actionPerformed(ActionEvent e) { - DataFlowGraph graph = editor.getDataFlowGraph(); - if (graph != null) { - DataTransferModel model = editor.getModel(); - ModelExtension.extendModel(model); - TypeInference.infer(model); - DataTransferMethodAnalyzer.decideToStoreResourceStates(graph); - String fileName = editor.getCurFileName(); - if (fileName == null) fileName = "Main"; - String mainTypeName = fileName.split("\\.")[0]; - boolean exist = false; - for (IdentifierTemplate id: model.getIdentifierTemplates()) { - String resourceName = id.getResourceName().substring(0, 1).toUpperCase() + id.getResourceName().substring(1); - if (mainTypeName.equals(resourceName)) { - exist = true; - } - } - if (!exist) { - JavaCodeGenerator.setMainTypeName(mainTypeName); // use model's file name as the main type's name. - } else { - JavaCodeGenerator.resetMainTypeName(); // use the default main type's name. - } - editor.setCodes(JavaMethodBodyGenerator.doGenerate(graph, model, JavaCodeGenerator.doGenerate(graph, model))); - ModelExtension.recoverModel(model); - for (CompilationUnit file : editor.getCodes()) { - System.out.println(file); - } - - String wd = (lastDir != null) ? lastDir : System.getProperty("user.dir"); - JFileChooser fc = new JFileChooser(wd); - fc.setFileSelectionMode(JFileChooser.FILES_AND_DIRECTORIES); - int rc = fc.showSaveDialog(null); - if (rc == JFileChooser.APPROVE_OPTION) { - lastDir = fc.getSelectedFile().getPath(); - for (CompilationUnit cu : editor.getCodes()) { - save(fc.getSelectedFile(), cu); - } - } - } - } - - private void save(File dir, CompilationUnit cu) { - File javaFile = new File(dir.getPath(), cu.getFileName()); - try { - BufferedWriter writer = new BufferedWriter(new FileWriter(javaFile)); - writer.write(cu.toString()); - writer.close(); - } catch (IOException e) { - e.printStackTrace(); - } - } - -} diff --git a/AlgebraicDataflowArchitectureModel/src/graphicalrefactor/actions/JerseyPrototypeGenerateAction.java b/AlgebraicDataflowArchitectureModel/src/graphicalrefactor/actions/JerseyPrototypeGenerateAction.java deleted file mode 100644 index 083c690..0000000 --- a/AlgebraicDataflowArchitectureModel/src/graphicalrefactor/actions/JerseyPrototypeGenerateAction.java +++ /dev/null @@ -1,90 +0,0 @@ -package graphicalrefactor.actions; - -import java.awt.event.ActionEvent; -import java.io.BufferedReader; -import java.io.BufferedWriter; -import java.io.File; -import java.io.FileReader; -import java.io.FileWriter; -import java.io.IOException; - -import javax.swing.JFileChooser; - -import algorithms.*; -import code.ast.*; -import generators.DataTransferMethodAnalyzer; -import generators.JerseyCodeGenerator; -import generators.JerseyMethodBodyGenerator; -import graphicalrefactor.editor.Editor; -import models.algebra.Type; -import models.dataConstraintModel.IdentifierTemplate; -import models.dataFlowModel.DataTransferModel; -import models.dataFlowModel.ModelExtension; -import models.dataFlowModel.DataFlowGraph; - -public class JerseyPrototypeGenerateAction extends AbstractEditorAction { - /** - * - */ - private static final long serialVersionUID = 1117065654665887436L; - - private String lastDir = null; - - public JerseyPrototypeGenerateAction(Editor editor) { - super("Generate JAX-RS Prototype", editor); - } - - @Override - public void actionPerformed(ActionEvent e) { - DataFlowGraph graph = editor.getDataFlowGraph(); - if (graph != null) { - DataTransferModel model = editor.getModel(); - ModelExtension.extendModel(model); - TypeInference.infer(model); - DataTransferMethodAnalyzer.decideToStoreResourceStates(graph); - String fileName = editor.getCurFileName(); - if (fileName == null) fileName = "Main"; - String mainTypeName = fileName.split("\\.")[0]; - boolean exist = false; - for (IdentifierTemplate id: model.getIdentifierTemplates()) { - String resourceName = id.getResourceName().substring(0, 1).toUpperCase() + id.getResourceName().substring(1); - if (mainTypeName.equals(resourceName)) { - exist = true; - } - } - if (!exist) { - JerseyCodeGenerator.setMainTypeName(mainTypeName); // use model's file name as the main type's name. - } else { - JerseyCodeGenerator.resetMainTypeName(); // use the default main type's name. - } - editor.setCodes(JerseyMethodBodyGenerator.doGenerate(graph, model, JerseyCodeGenerator.doGenerate(graph, model))); - ModelExtension.recoverModel(model); - for (CompilationUnit file : editor.getCodes()) { - System.out.println(file); - } - - String wd = (lastDir != null) ? lastDir : System.getProperty("user.dir"); - JFileChooser fc = new JFileChooser(wd); - fc.setFileSelectionMode(JFileChooser.FILES_AND_DIRECTORIES); - int rc = fc.showSaveDialog(null); - if (rc == JFileChooser.APPROVE_OPTION) { - lastDir = fc.getSelectedFile().getPath(); - for (CompilationUnit cu : editor.getCodes()) { - save(fc.getSelectedFile(), cu); - } - } - } - } - - private void save(File dir, CompilationUnit cu) { - File javaFile = new File(dir.getPath(), cu.getFileName()); - try { - BufferedWriter writer = new BufferedWriter(new FileWriter(javaFile)); - writer.write(cu.toString()); - writer.close(); - } catch (IOException e) { - e.printStackTrace(); - } - } - -} diff --git a/AlgebraicDataflowArchitectureModel/src/graphicalrefactor/actions/NewChannelAction.java b/AlgebraicDataflowArchitectureModel/src/graphicalrefactor/actions/NewChannelAction.java deleted file mode 100644 index 9328f5f..0000000 --- a/AlgebraicDataflowArchitectureModel/src/graphicalrefactor/actions/NewChannelAction.java +++ /dev/null @@ -1,28 +0,0 @@ -package graphicalrefactor.actions; - -import java.awt.event.ActionEvent; - -import javax.swing.JOptionPane; - -import graphicalrefactor.editor.Editor; -import models.dataFlowModel.DataTransferChannelGenerator; - -public class NewChannelAction extends AbstractEditorAction { - - /** - * - */ - private static final long serialVersionUID = 5979007029473101802L; - - public NewChannelAction(Editor editor) { - super("Channel...", editor); - } - - @Override - public void actionPerformed(ActionEvent e) { - String channelName = JOptionPane.showInputDialog("Channel Name:"); - if (channelName == null) return; - editor.addChannelGenerator(new DataTransferChannelGenerator(channelName)); - } - -} diff --git a/AlgebraicDataflowArchitectureModel/src/graphicalrefactor/actions/NewFormulaChannelAction.java b/AlgebraicDataflowArchitectureModel/src/graphicalrefactor/actions/NewFormulaChannelAction.java deleted file mode 100644 index 7fb9299..0000000 --- a/AlgebraicDataflowArchitectureModel/src/graphicalrefactor/actions/NewFormulaChannelAction.java +++ /dev/null @@ -1,62 +0,0 @@ -package graphicalrefactor.actions; - -import java.awt.BorderLayout; -import java.awt.Container; -import java.awt.FlowLayout; -import java.awt.Frame; -import java.awt.GridLayout; -import java.awt.event.ActionEvent; -import java.awt.event.ActionListener; - -import javax.swing.BoxLayout; -import javax.swing.JButton; -import javax.swing.JDialog; -import javax.swing.JFrame; -import javax.swing.JLabel; -import javax.swing.JOptionPane; -import javax.swing.JPanel; -import javax.swing.JTextField; - -import graphicalrefactor.editor.Editor; -import graphicalrefactor.views.GraphicalRefactor; -import models.visualModel.FormulaChannelGenerator; - -public class NewFormulaChannelAction extends AbstractEditorAction implements ActionListener { - - /** - * - */ - private static final long serialVersionUID = 5345875219049178252L; - - public NewFormulaChannelAction(Editor editor) { - super("FormulaChannel...", editor); - } - - @Override - public void actionPerformed(ActionEvent e) { - JPanel panel = new JPanel(); - GridLayout layout = new GridLayout(2,2); - panel.setLayout(layout); - layout.setVgap(5); - layout.setHgap(20); - panel.add(new JLabel("Channel Name:")); - JTextField channelText = new JTextField(); - panel.add(channelText); - panel.add(new JLabel("Symbol:")); - JTextField symbolText = new JTextField(); - panel.add(symbolText); - - int r = JOptionPane.showConfirmDialog( - null, // �I�[�i�[�E�B���h�E - panel, // ���b�Z�[�W - "New Formula Channel", // �E�B���h�E�^�C�g�� - JOptionPane.OK_CANCEL_OPTION, // �I�v�V�����i�{�^���̎�ށj - JOptionPane.QUESTION_MESSAGE); // ���b�Z�[�W�^�C�v�i�A�C�R���̎�ށj - - String channelName = channelText.getText(); - String symbol = symbolText.getText(); - if(r == JOptionPane.OK_OPTION) { - editor.addFormulaChannelGenerator(new FormulaChannelGenerator(channelName, editor.getModel().getSymbol(symbol))); - } - } -} diff --git a/AlgebraicDataflowArchitectureModel/src/graphicalrefactor/actions/NewIOChannelAction.java b/AlgebraicDataflowArchitectureModel/src/graphicalrefactor/actions/NewIOChannelAction.java deleted file mode 100644 index 6b3bf66..0000000 --- a/AlgebraicDataflowArchitectureModel/src/graphicalrefactor/actions/NewIOChannelAction.java +++ /dev/null @@ -1,29 +0,0 @@ -package graphicalrefactor.actions; - -import java.awt.event.ActionEvent; - -import javax.swing.JOptionPane; - - -import graphicalrefactor.editor.Editor; -import models.dataFlowModel.DataTransferChannelGenerator; - -public class NewIOChannelAction extends AbstractEditorAction { - - /** - * - */ - private static final long serialVersionUID = -1657072017390171313L; - - public NewIOChannelAction(Editor editor) { - super("I/O Channel", editor); - } - - @Override - public void actionPerformed(ActionEvent e) { - String channelName = JOptionPane.showInputDialog("I/O Channel Name:"); - if (channelName == null) return; - editor.addIOChannelGenerator(new DataTransferChannelGenerator(channelName)); - } - -} diff --git a/AlgebraicDataflowArchitectureModel/src/graphicalrefactor/actions/NewModelAction.java b/AlgebraicDataflowArchitectureModel/src/graphicalrefactor/actions/NewModelAction.java deleted file mode 100644 index c79d868..0000000 --- a/AlgebraicDataflowArchitectureModel/src/graphicalrefactor/actions/NewModelAction.java +++ /dev/null @@ -1,24 +0,0 @@ -package graphicalrefactor.actions; - -import java.awt.event.ActionEvent; - -import graphicalrefactor.editor.Editor; -import graphicalrefactor.views.GraphicalRefactor; - -public class NewModelAction extends AbstractSystemAction { - /** - * - */ - private static final long serialVersionUID = 8484493203589724589L; - - public NewModelAction(GraphicalRefactor frame) { - super("Model", frame); - } - - @Override - public void actionPerformed(ActionEvent e) { - frame.getEditor().clear(); - frame.setTitle(frame.title); - } - -} diff --git a/AlgebraicDataflowArchitectureModel/src/graphicalrefactor/actions/NewResourceAction.java b/AlgebraicDataflowArchitectureModel/src/graphicalrefactor/actions/NewResourceAction.java deleted file mode 100644 index 600daf7..0000000 --- a/AlgebraicDataflowArchitectureModel/src/graphicalrefactor/actions/NewResourceAction.java +++ /dev/null @@ -1,28 +0,0 @@ -package graphicalrefactor.actions; - -import java.awt.event.ActionEvent; - -import javax.swing.JOptionPane; - -import graphicalrefactor.editor.Editor; -import models.dataConstraintModel.IdentifierTemplate; - -public class NewResourceAction extends AbstractEditorAction { - - /** - * - */ - private static final long serialVersionUID = -4439207504700741286L; - - public NewResourceAction(Editor editor) { - super("Resource...", editor); - } - - @Override - public void actionPerformed(ActionEvent e) { - String resName = JOptionPane.showInputDialog("Resourece Name:"); - if (resName == null) return; - editor.addIdentifierTemplate(new IdentifierTemplate(resName, 0)); - } - -} diff --git a/AlgebraicDataflowArchitectureModel/src/graphicalrefactor/actions/OpenAction.java b/AlgebraicDataflowArchitectureModel/src/graphicalrefactor/actions/OpenAction.java deleted file mode 100644 index 2fcfe73..0000000 --- a/AlgebraicDataflowArchitectureModel/src/graphicalrefactor/actions/OpenAction.java +++ /dev/null @@ -1,62 +0,0 @@ -package graphicalrefactor.actions; - -import java.awt.event.ActionEvent; -import java.io.File; - -import javax.swing.JFileChooser; -import javax.swing.filechooser.FileFilter; -import javax.swing.filechooser.FileNameExtensionFilter; - -import graphicalrefactor.editor.Editor; -import graphicalrefactor.views.GraphicalRefactor; - -public class OpenAction extends AbstractSystemAction { - /** - * - */ - private static final long serialVersionUID = -8290761032629599683L; - - private String lastDir = null; - - public OpenAction(GraphicalRefactor frame) { - super("Open...", frame); - } - - @Override - public void actionPerformed(ActionEvent e) { - Editor editor = frame.getEditor(); - if (editor != null) { - String wd = (lastDir != null) ? lastDir : System.getProperty("user.dir"); - - JFileChooser fc = new JFileChooser(wd); - - FileFilter model = new FileNameExtensionFilter("model","model"); - FileFilter dtram = new FileNameExtensionFilter("dtram", "dtram"); - - // Adds file filter for supported file format - FileFilter defaultFilter = new FileFilter() { - - public boolean accept(File file) { - String lcase = file.getName().toLowerCase(); - return lcase.endsWith(".model"); - } - - @Override - public String getDescription() { - return null; - } - }; - - fc.addChoosableFileFilter(defaultFilter); - fc.addChoosableFileFilter(model); - fc.addChoosableFileFilter(dtram); - int rc = fc.showDialog(null, "Open Model File"); - if (rc == JFileChooser.APPROVE_OPTION) { - lastDir = fc.getSelectedFile().getParent(); - editor.open(fc.getSelectedFile()); - frame.setTitle(frame.title + " - " + fc.getSelectedFile().getAbsolutePath()); - } - } - } - -} diff --git a/AlgebraicDataflowArchitectureModel/src/graphicalrefactor/actions/SaveAction.java b/AlgebraicDataflowArchitectureModel/src/graphicalrefactor/actions/SaveAction.java deleted file mode 100644 index 62f0609..0000000 --- a/AlgebraicDataflowArchitectureModel/src/graphicalrefactor/actions/SaveAction.java +++ /dev/null @@ -1,26 +0,0 @@ -package graphicalrefactor.actions; - -import java.awt.event.ActionEvent; - -import graphicalrefactor.editor.Editor; -import graphicalrefactor.views.GraphicalRefactor; - -public class SaveAction extends AbstractSystemAction { - /** - * - */ - private static final long serialVersionUID = 5660460585305281982L; - - public SaveAction(GraphicalRefactor frame) { - super("Save", frame); - } - - @Override - public void actionPerformed(ActionEvent e) { - Editor editor = frame.getEditor(); - if (editor != null && editor.getCurFileName() != null) { - editor.save(); - } - } - -} diff --git a/AlgebraicDataflowArchitectureModel/src/graphicalrefactor/actions/SaveAsAction.java b/AlgebraicDataflowArchitectureModel/src/graphicalrefactor/actions/SaveAsAction.java deleted file mode 100644 index d8ce78e..0000000 --- a/AlgebraicDataflowArchitectureModel/src/graphicalrefactor/actions/SaveAsAction.java +++ /dev/null @@ -1,79 +0,0 @@ -package graphicalrefactor.actions; - -import java.awt.event.ActionEvent; -import java.io.File; - -import javax.swing.AbstractAction; -import javax.swing.JFileChooser; -import javax.swing.filechooser.FileFilter; -import javax.swing.filechooser.FileNameExtensionFilter; - -import graphicalrefactor.editor.Editor; -import graphicalrefactor.views.GraphicalRefactor; - -public class SaveAsAction extends AbstractSystemAction { - /** - * - */ - private static final long serialVersionUID = -2599502783032684084L; - - private String lastDir = null; - - public SaveAsAction(GraphicalRefactor frame) { - super("Save As...", frame); - } - - @Override - public void actionPerformed(ActionEvent e) { - Editor editor = frame.getEditor(); - if (editor != null) { - String wd = (lastDir != null) ? lastDir : System.getProperty("user.dir"); - - JFileChooser fc = new JFileChooser(wd); - FileFilter model = new FileNameExtensionFilter("model","model"); - FileFilter dtram = new FileNameExtensionFilter("dtram", "dtram"); - - // Adds file filter for supported file format - FileFilter defaultFilter = new FileFilter() { - public boolean accept(File file) { - String lcase = file.getName().toLowerCase(); - return lcase.endsWith(".model"); - } - - @Override - public String getDescription() { - return null; - } - }; - - fc.addChoosableFileFilter(defaultFilter); - fc.addChoosableFileFilter(model); - fc.addChoosableFileFilter(dtram); - int rc = fc.showDialog(null, "Save Model File"); - - // choose a file extension from a dialog. - if (rc == JFileChooser.APPROVE_OPTION) { - - // if extension filter is filled, then attaching extension by choosing filter. - // but if it's not filled, then using default extension name. - String extension = ""; - if(fc.getFileFilter() instanceof FileNameExtensionFilter) { - FileNameExtensionFilter selectedFilter = (FileNameExtensionFilter)fc.getFileFilter(); - extension = "." + selectedFilter.getExtensions()[0].toString(); - } - - lastDir = fc.getSelectedFile().getParent(); - - String fileName = fc.getSelectedFile().getAbsolutePath() + extension; - - // checking file duplicates - if(! (fc.getSelectedFile().exists())) editor.setCurFilePath(fileName); - - // overwriting file - editor.save(); - frame.setTitle(GraphicalRefactor.title + " - " + fc.getSelectedFile().getAbsolutePath()); - } - } - } - -} diff --git a/AlgebraicDataflowArchitectureModel/src/graphicalrefactor/actions/TreeLayoutAction.java b/AlgebraicDataflowArchitectureModel/src/graphicalrefactor/actions/TreeLayoutAction.java deleted file mode 100644 index 1ce409f..0000000 --- a/AlgebraicDataflowArchitectureModel/src/graphicalrefactor/actions/TreeLayoutAction.java +++ /dev/null @@ -1,18 +0,0 @@ -package graphicalrefactor.actions; - -import java.awt.event.ActionEvent; - -import graphicalrefactor.editor.Editor; - -public class TreeLayoutAction extends AbstractEditorAction { - - public TreeLayoutAction(Editor editor) { - super("Tree Layout", editor); - } - - @Override - public void actionPerformed(ActionEvent e) { - editor.setTreeLayout(); - } - -} diff --git a/AlgebraicDataflowArchitectureModel/src/graphicalrefactor/actions/ZoomInAction.java b/AlgebraicDataflowArchitectureModel/src/graphicalrefactor/actions/ZoomInAction.java deleted file mode 100644 index e2d1549..0000000 --- a/AlgebraicDataflowArchitectureModel/src/graphicalrefactor/actions/ZoomInAction.java +++ /dev/null @@ -1,28 +0,0 @@ -package graphicalrefactor.actions; - -import java.awt.event.ActionEvent; - -import javax.swing.AbstractAction; -import javax.swing.JOptionPane; - -import com.mxgraph.swing.mxGraphComponent; -import com.mxgraph.util.mxResources; - -import graphicalrefactor.editor.Editor; - -public class ZoomInAction extends AbstractViewerAction { - /** - * - */ - private static final long serialVersionUID = 6758532166946195926L; - - public ZoomInAction(mxGraphComponent graphComponent) { - super("Zoom In", graphComponent); - } - - @Override - public void actionPerformed(ActionEvent e) { - graphComponent.zoomIn(); - } - -} diff --git a/AlgebraicDataflowArchitectureModel/src/graphicalrefactor/actions/ZoomOutAction.java b/AlgebraicDataflowArchitectureModel/src/graphicalrefactor/actions/ZoomOutAction.java deleted file mode 100644 index 7518f38..0000000 --- a/AlgebraicDataflowArchitectureModel/src/graphicalrefactor/actions/ZoomOutAction.java +++ /dev/null @@ -1,26 +0,0 @@ -package graphicalrefactor.actions; - -import java.awt.event.ActionEvent; - -import javax.swing.AbstractAction; - -import com.mxgraph.swing.mxGraphComponent; - -import graphicalrefactor.editor.Editor; - -public class ZoomOutAction extends AbstractViewerAction { - /** - * - */ - private static final long serialVersionUID = 8657530769383486605L; - - public ZoomOutAction(mxGraphComponent graphComponent) { - super("Zoom Out", graphComponent); - } - - @Override - public void actionPerformed(ActionEvent e) { - graphComponent.zoomOut(); - } - -} diff --git a/AlgebraicDataflowArchitectureModel/src/graphicalrefactor/editor/Editor.java b/AlgebraicDataflowArchitectureModel/src/graphicalrefactor/editor/Editor.java deleted file mode 100644 index bc27ce5..0000000 --- a/AlgebraicDataflowArchitectureModel/src/graphicalrefactor/editor/Editor.java +++ /dev/null @@ -1,667 +0,0 @@ -package graphicalrefactor.editor; - -import java.io.BufferedReader; -import java.io.File; -import java.io.FileNotFoundException; -import java.io.FileReader; -import java.io.FileWriter; -import java.io.IOException; -import java.util.ArrayList; -import java.util.Collection; -import java.util.HashMap; -import java.util.HashSet; -import java.util.List; -import java.util.Map; -import java.util.Set; - -import com.mxgraph.layout.mxCircleLayout; -import com.mxgraph.layout.mxCompactTreeLayout; -import com.mxgraph.model.mxCell; -import com.mxgraph.model.mxGeometry; -import com.mxgraph.model.mxGraphModel; -import com.mxgraph.model.mxIGraphModel; -import com.mxgraph.util.mxConstants; -import com.mxgraph.util.mxPoint; -import com.mxgraph.view.mxCellState; -import com.mxgraph.util.mxRectangle; -import com.mxgraph.view.mxGraph; -import com.mxgraph.view.mxGraphView; - -import algorithms.DataTransferModelAnalyzer; -import algorithms.Validation; -import code.ast.CompilationUnit; -import graphicalrefactor.layouts.*; -import models.Edge; -import models.EdgeAttribute; -import models.Node; -import models.dataConstraintModel.ChannelGenerator; -import models.dataConstraintModel.ChannelMember; -import models.dataConstraintModel.IdentifierTemplate; -import models.dataFlowModel.DataTransferModel; -import models.dataFlowModel.DataTransferChannelGenerator; -import models.dataFlowModel.PushPullAttribute; -import models.dataFlowModel.DataFlowEdge; -import models.dataFlowModel.DataFlowGraph; -import models.dataFlowModel.ResourceNode; -import models.visualModel.FormulaChannelGenerator; -import parser.Parser; -import parser.Parser.TokenStream; -import parser.exceptions.ExpectedAssignment; -import parser.exceptions.ExpectedChannel; -import parser.exceptions.ExpectedChannelName; -import parser.exceptions.ExpectedEquals; -import parser.exceptions.ExpectedFormulaChannel; -import parser.exceptions.ExpectedGeometry; -import parser.exceptions.ExpectedInOrOutOrRefKeyword; -import parser.exceptions.ExpectedIoChannel; -import parser.exceptions.ExpectedLeftCurlyBracket; -import parser.exceptions.ExpectedModel; -import parser.exceptions.ExpectedNode; -import parser.exceptions.ExpectedRHSExpression; -import parser.exceptions.ExpectedResource; -import parser.exceptions.ExpectedRightBracket; -import parser.exceptions.ExpectedStateTransition; -import parser.exceptions.WrongLHSExpression; -import parser.exceptions.WrongRHSExpression; -import parser.ParserDTRAM; - -public class Editor { - final int PORT_DIAMETER = 8; - final int PORT_RADIUS = PORT_DIAMETER / 2; - - protected String curFileName = null; - protected String curFilePath = null; - protected ArrayList codes = null; - - protected DataTransferModel model = null; - protected mxGraph graph = null; - - protected DataFlowGraph dataFlowGraph = null; - - - public Editor(mxGraph graph) { - this.graph = graph; - } - - public mxGraph getGraph() { - return graph; - } - - public void setGraph(mxGraph graph) { - this.graph = graph; - } - - public DataTransferModel getModel() { - if (model == null) { - model = new DataTransferModel(); - } - return model; - } - - public DataFlowGraph getDataFlowGraph() { - if (dataFlowGraph == null) { - analyzeDataTransferModel(getModel()); - } - return dataFlowGraph; - } - - public DataFlowGraph analyzeDataTransferModel(DataTransferModel model) { - DataFlowGraph flowGraph = DataTransferModelAnalyzer.createDataFlowGraphWithStateStoringAttribute(model); - dataFlowGraph = DataTransferModelAnalyzer.annotateWithSelectableDataTransferAttiribute(flowGraph); - updateEdgeAttiributes(dataFlowGraph); - return dataFlowGraph; - } - - public void resetDataFlowGraph() { - dataFlowGraph = null; - } - - public void setDataFlowGraph(DataFlowGraph dataFlowGraph) { - this.dataFlowGraph = dataFlowGraph; - } - - public ArrayList getCodes() { - return codes; - } - - public void setCodes(ArrayList codes) { - this.codes = codes; - } - - public String getCurFileName() { - return curFileName; - } - - public String getCurFilePath() { - return curFilePath; - } - - public void setCurFilePath(String curFilePath) { - this.curFilePath = curFilePath; - this.curFileName = new File(curFilePath).getName(); - } - - public void clear() { - model = null; - ((mxGraphModel) graph.getModel()).clear(); - dataFlowGraph = null; - curFilePath = null; - curFileName = null; - codes = null; - } - - /** - * Open a given file, parse the file, construct a DataFlowModel and a mxGraph - * @param file given file - * @return a constructed DataFlowModel - */ - public DataTransferModel open(File file) { - try { - - String extension =""; - if(file != null && file.exists()) { - // get a file's name - String name = file.getName(); - - // get a file's extension - extension = name.substring(name.lastIndexOf(".")); - } - if(extension.contains(".model")) { - openModel(file); - } else { - ParserDTRAM parserDTRAM = new ParserDTRAM(new BufferedReader(new FileReader(file))); - try { - model = parserDTRAM.doParseModel(); - graph = constructGraph(model); - parserDTRAM.doParseGeometry(graph); - curFilePath = file.getAbsolutePath(); - curFileName = file.getName(); - if (!Validation.checkUpdateConflict(model)) return null; - analyzeDataTransferModel(model); - return model; - } catch (ExpectedChannel | ExpectedChannelName | ExpectedLeftCurlyBracket | ExpectedInOrOutOrRefKeyword - | ExpectedStateTransition | ExpectedEquals | ExpectedRHSExpression | WrongLHSExpression - | WrongRHSExpression | ExpectedRightBracket | ExpectedAssignment | ExpectedModel | ExpectedGeometry | ExpectedNode | ExpectedResource | ExpectedFormulaChannel | ExpectedIoChannel e) { - e.printStackTrace(); - } - } - } catch (FileNotFoundException e) { - e.printStackTrace(); - } - - return null; - } - - public DataTransferModel openModel(File file) { - try { - - Parser parser = new Parser(new BufferedReader(new FileReader(file))); - - try { - model = parser.doParse(); - curFilePath = file.getAbsolutePath(); - curFileName = file.getName(); - if (!Validation.checkUpdateConflict(model)) return null; - graph = constructGraph(model); - analyzeDataTransferModel(model); - return model; - } catch (ExpectedChannel | ExpectedChannelName | ExpectedLeftCurlyBracket | ExpectedInOrOutOrRefKeyword - | ExpectedStateTransition | ExpectedEquals | ExpectedRHSExpression | WrongLHSExpression - | WrongRHSExpression | ExpectedRightBracket | ExpectedAssignment e) { - e.printStackTrace(); - } - } catch (FileNotFoundException e) { - e.printStackTrace(); - } - return null; - } - - /**-------------------------------------------------------------------------------- - * save - /**-------------------------------------------------------------------------------- - * - */ - public void save() { - if (curFilePath != null) { - try { - File file = new File(curFilePath); - String extension = ""; - if(file != null && file.exists()) { - // get a file's name - String name = file.getName(); - - // get a file's extension - extension = name.substring(name.lastIndexOf(".")); - } - if(extension.contains(".model")) { - saveModel(file); - } else { - FileWriter filewriter = new FileWriter(file); - filewriter.write(toOutputString()); - filewriter.close(); - } - } catch (IOException e) { - e.printStackTrace(); - } - } - } - - public void saveModel(File file) { - if (curFilePath != null) { - try { - FileWriter filewriter = new FileWriter(file); - filewriter.write(model.getSourceText()); - filewriter.close(); - } catch (IOException e) { - e.printStackTrace(); - } - } - } - - /**-------------------------------------------------------------------------------- - * get writing texts "dtram" file information is written. - * - * @return formatted "dtram" info texts. - */ - protected String toOutputString() { - String fileString = ""; - - fileString += "model {\n"; - fileString += this.model.getSourceText(); - fileString += "}\n"; - - fileString += "geometry {\n"; - - Object root = graph.getDefaultParent(); - for (int i = 0; i < graph.getModel().getChildCount(root); i++) { - Object cell = graph.getModel().getChildAt(root, i); - if (graph.getModel().isVertex(cell)) { - mxGraphView view = graph.getView(); - mxCellState state = view.getState(cell); - int x = (int) state.getX(); - int y = (int) state.getY(); - int w = (int) state.getWidth(); - int h = (int) state.getHeight(); - - for(ChannelGenerator ch: model.getChannelGenerators()) { - if(ch instanceof FormulaChannelGenerator && state.getLabel().equals(ch.getChannelName())) { - fileString += "\tnode fc " + state.getLabel() + ":" + x + "," + y + "," + w + "," + h+"\n"; - } else if(ch instanceof ChannelGenerator && state.getLabel().equals(ch.getChannelName())) { - fileString +="\tnode c " + state.getLabel() + ":" + x + "," + y + "," + w + "," + h+"\n"; - } - } - - for (IdentifierTemplate res: model.getIdentifierTemplates()){ - if(res instanceof IdentifierTemplate && state.getLabel().equals(res.getResourceName())) - fileString += "\tnode r " + state.getLabel() + ":" + x + "," + y + "," + w + "," + h + "\n"; - } - - for (ChannelGenerator ioC: model.getIOChannelGenerators()) { - if(ioC instanceof ChannelGenerator && state.getLabel().equals(ioC.getChannelName())) { - fileString += "\tnode ioc " + state.getLabel() + ":" + x + "," + y + "," + w + "," + h + "\n"; - } - } - } - } - fileString += "}\n"; - - return fileString; - } - - /** - * Construct a mxGraph from DataFlowModel and DataFlowModel - * @param model - * @param dataFlowGraph - * @return constructed mxGraph - */ - public mxGraph constructGraph(DataTransferModel model) { - ((mxGraphModel) graph.getModel()).clear(); - Object parent = graph.getDefaultParent(); - graph.getModel().beginUpdate(); - try { - mxGeometry geo1 = new mxGeometry(0, 0.5, PORT_DIAMETER, PORT_DIAMETER); - geo1.setOffset(new mxPoint(-PORT_RADIUS, -PORT_RADIUS)); - geo1.setRelative(true); - - mxGeometry geo2 = new mxGeometry(1.0, 0.5, PORT_DIAMETER, PORT_DIAMETER); - geo2.setOffset(new mxPoint(-PORT_RADIUS, -PORT_RADIUS)); - geo2.setRelative(true); - - Map channelsIn = new HashMap<>(); - Map channelsOut = new HashMap<>(); - Map resources = new HashMap<>(); - - // create channel vertices - for (ChannelGenerator c: model.getChannelGenerators()) { - DataTransferChannelGenerator channelGen = (DataTransferChannelGenerator) c; - if (channelsIn.get(channelGen) == null || channelsOut.get(channelGen) == null) { - Object channel = graph.insertVertex(parent, null, channelGen.getChannelName(), 150, 20, 30, 30); // insert a channel as a vertex - mxCell port_in = new mxCell(null, geo1, "shape=ellipse;perimter=ellipsePerimeter"); - port_in.setVertex(true); - graph.addCell(port_in, channel); // insert the input port of a channel - mxCell port_out = new mxCell(null, geo2, "shape=ellipse;perimter=ellipsePerimeter"); - port_out.setVertex(true); - graph.addCell(port_out, channel); // insert the output port of a channel - channelsIn.put(channelGen, port_in); - channelsOut.put(channelGen, port_out); - } - } - - // create resource vertices - for (IdentifierTemplate res: model.getIdentifierTemplates()) { - Object resource = graph.insertVertex(parent, null, - res.getResourceName(), 20, 20, 80, 30, - "shape=ellipse;perimeter=ellipsePerimeter"); // insert a resource as a vertex - resources.put(res, resource); - } - - // add input, output and reference edges - for (ChannelGenerator ch: model.getChannelGenerators()) { - DataTransferChannelGenerator channelGen = (DataTransferChannelGenerator) ch; - // input edge - for (IdentifierTemplate srcRes: channelGen.getInputIdentifierTemplates()) { - graph.insertEdge(parent, null, new SrcDstAttribute(srcRes, channelGen), resources.get(srcRes), channelsIn.get(channelGen), "movable=false"); - } - // output edge - for (IdentifierTemplate dstRes: channelGen.getOutputIdentifierTemplates()) { - graph.insertEdge(parent, null, new SrcDstAttribute(channelGen, dstRes), channelsOut.get(channelGen), resources.get(dstRes), "movable=false"); - } - // reference edges - for (IdentifierTemplate refRes: channelGen.getReferenceIdentifierTemplates()) { - graph.insertEdge(parent, null, null, resources.get(refRes), channelsIn.get(channelGen), "dashed=true;movable=false"); - } - } - - for (ChannelGenerator ioChannelGen: model.getIOChannelGenerators()) { - if (channelsOut.get(ioChannelGen) == null) { - Object channel = graph.insertVertex(parent, null, ioChannelGen.getChannelName(), 150, 20, 30, 30); // insert an I/O channel as a vertex - mxCell port_out = new mxCell(null, geo2, "shape=ellipse;perimter=ellipsePerimeter"); - port_out.setVertex(true); - graph.addCell(port_out, channel); // insert the output port of a channel - channelsOut.put((DataTransferChannelGenerator) ioChannelGen, port_out); - for (IdentifierTemplate outRes: ((DataTransferChannelGenerator) ioChannelGen).getOutputIdentifierTemplates()) { - graph.insertEdge(parent, null, null, port_out, resources.get(outRes), "movable=false"); - } - } - } - } finally { - graph.getModel().endUpdate(); - } - setTreeLayout(); - - return graph; - } - - public void setDAGLayout() { - Object parent = graph.getDefaultParent(); - graph.getModel().beginUpdate(); - try { - DAGLayout ctl = new DAGLayout(graph); - ctl.execute(parent); - } finally { - graph.getModel().endUpdate(); - } - } - - public void updateEdgeAttiributes(DataFlowGraph dataFlowGraph) { - Object parent = graph.getDefaultParent(); - graph.getModel().beginUpdate(); - try { - // add input, output and reference edges - for (Edge e : dataFlowGraph.getEdges()) { - if (e instanceof DataFlowEdge) { - DataFlowEdge dataFlow = (DataFlowEdge) e; - DataTransferChannelGenerator channelGen = dataFlow.getChannelGenerator(); - ResourceNode srcRes = (ResourceNode) dataFlow.getSource(); - // input edge - for (Object edge: graph.getChildEdges(parent)) { - mxCell edgeCell = (mxCell) edge; - if (edgeCell.getValue() instanceof SrcDstAttribute) { - SrcDstAttribute edgeAttr = (SrcDstAttribute) edgeCell.getValue(); - if (edgeAttr.getSrouce() == srcRes.getIdentifierTemplate() && edgeAttr.getDestination() == channelGen) { - edgeCell.setValue(dataFlow.getAttribute()); - break; - } - } - } - } - } - } finally { - graph.getModel().endUpdate(); - } - graph.refresh(); - } - - public void setTreeLayout() { - Object parent = graph.getDefaultParent(); - graph.getModel().beginUpdate(); - try { - mxCompactTreeLayout ctl = new mxCompactTreeLayout(graph); - ctl.setLevelDistance(100); - // ctl.setHorizontal(false); - ctl.setEdgeRouting(false); - ctl.execute(parent); - } finally { - graph.getModel().endUpdate(); - } - } - - public void setCircleLayout() { - Object parent = graph.getDefaultParent(); - graph.getModel().beginUpdate(); - try { - mxCircleLayout ctl = new mxCircleLayout(graph); - ctl.execute(parent); - } finally { - graph.getModel().endUpdate(); - } - } - - public void addIdentifierTemplate(IdentifierTemplate res) { - getModel().addIdentifierTemplate(res); - resetDataFlowGraph(); - graph.getModel().beginUpdate(); - Object parent = graph.getDefaultParent(); - try { - graph.insertVertex(parent, null, res.getResourceName(), 20, 20, 80, 30, - "shape=ellipse;perimeter=ellipsePerimeter"); // insert a resource as a vertex - } finally { - graph.getModel().endUpdate(); - } - } - - public void addChannelGenerator(DataTransferChannelGenerator channelGen) { - getModel().addChannelGenerator(channelGen); - resetDataFlowGraph(); - graph.getModel().beginUpdate(); - Object parent = graph.getDefaultParent(); - try { - mxGeometry geo1 = new mxGeometry(0, 0.5, PORT_DIAMETER, PORT_DIAMETER); - geo1.setOffset(new mxPoint(-PORT_RADIUS, -PORT_RADIUS)); - geo1.setRelative(true); - - mxGeometry geo2 = new mxGeometry(1.0, 0.5, PORT_DIAMETER, PORT_DIAMETER); - geo2.setOffset(new mxPoint(-PORT_RADIUS, -PORT_RADIUS)); - geo2.setRelative(true); - - Object channel = graph.insertVertex(parent, null, channelGen.getChannelName(), 150, 20, 30, 30); // insert a channel as a vertex - mxCell port_in = new mxCell(null, geo1, "shape=ellipse;perimter=ellipsePerimeter"); - port_in.setVertex(true); - graph.addCell(port_in, channel); // insert the input port of a channel - mxCell port_out = new mxCell(null, geo2, "shape=ellipse;perimter=ellipsePerimeter"); - port_out.setVertex(true); - graph.addCell(port_out, channel); // insert the output port of a channel - } finally { - graph.getModel().endUpdate(); - } - } - - public void addIOChannelGenerator(DataTransferChannelGenerator ioChannelGen) { - getModel().addIOChannelGenerator(ioChannelGen); - resetDataFlowGraph(); - graph.getModel().beginUpdate(); - Object parent = graph.getDefaultParent(); - try { - mxGeometry geo2 = new mxGeometry(1.0, 0.5, PORT_DIAMETER, PORT_DIAMETER); - geo2.setOffset(new mxPoint(-PORT_RADIUS, -PORT_RADIUS)); - geo2.setRelative(true); - - Object channel = graph.insertVertex(parent, null, ioChannelGen.getChannelName(), 150, 20, 30, 30); // insert an I/O channel as a vertex - mxCell port_out = new mxCell(null, geo2, "shape=ellipse;perimter=ellipsePerimeter"); - port_out.setVertex(true); - graph.addCell(port_out, channel); // insert the output port of a channel - } finally { - graph.getModel().endUpdate(); - } - } - - public void addFormulaChannelGenerator(FormulaChannelGenerator formulaChannelGen) { - getModel().addChannelGenerator(formulaChannelGen); - resetDataFlowGraph(); - graph.getModel().beginUpdate(); - Object parent = graph.getDefaultParent(); - try { - mxGeometry geo1 = new mxGeometry(0, 0.5, PORT_DIAMETER, PORT_DIAMETER); - geo1.setOffset(new mxPoint(-PORT_RADIUS, -PORT_RADIUS)); - geo1.setRelative(true); - - mxGeometry geo2 = new mxGeometry(1.0, 0.5, PORT_DIAMETER, PORT_DIAMETER); - geo2.setOffset(new mxPoint(-PORT_RADIUS, -PORT_RADIUS)); - geo2.setRelative(true); - - Object channel = graph.insertVertex(parent, null, formulaChannelGen.getChannelName(), 150, 20, 30, 30); // insert a channel as a vertex - mxCell port_in = new mxCell(null, geo1, "shape=ellipse;perimter=ellipsePerimeter"); - port_in.setVertex(true); - graph.addCell(port_in, channel); // insert the input port of a channel - mxCell port_out = new mxCell(null, geo2, "shape=ellipse;perimter=ellipsePerimeter"); - port_out.setVertex(true); - graph.addCell(port_out, channel); // insert the output port of a channel - } finally { - graph.getModel().endUpdate(); - } - } - - public boolean connectEdge(mxCell edge, mxCell src, mxCell dst) { - DataTransferModel model = getModel(); - ChannelGenerator srcCh = model.getChannelGenerator((String) src.getValue()); - if (srcCh == null) { - srcCh = model.getIOChannelGenerator((String) src.getValue()); - if (srcCh == null) { - IdentifierTemplate srcRes = model.getIdentifierTemplate((String) src.getValue()); - ChannelGenerator dstCh = model.getChannelGenerator((String) dst.getValue()); - if (srcRes == null || dstCh == null) return false; - // resource to channel edge - ChannelMember srcCm = new ChannelMember(srcRes); - ((DataTransferChannelGenerator ) dstCh).addChannelMemberAsInput(srcCm); - edge.setValue(new SrcDstAttribute(srcRes, dstCh)); - resetDataFlowGraph(); - return true; - } - } - IdentifierTemplate dstRes = model.getIdentifierTemplate((String) dst.getValue()); - if (dstRes == null) return false; - // channel to resource edge - ChannelMember dstCm = new ChannelMember(dstRes); - ((DataTransferChannelGenerator) srcCh).addChannelMemberAsOutput(dstCm); - edge.setValue(new SrcDstAttribute(srcCh, dstRes)); - resetDataFlowGraph(); - return true; - } - - public void delete() { - for (Object obj: graph.getSelectionCells()) { - mxCell cell = (mxCell) obj; - if (cell.isEdge()) { - String srcName = (String) cell.getSource().getValue(); - String dstName = (String) cell.getTarget().getValue(); - if (model.getIdentifierTemplate(srcName) != null) { - // resource to channel edge - ChannelGenerator ch = model.getChannelGenerator(dstName); - ch.removeChannelMember(model.getIdentifierTemplate(srcName)); - } else if (model.getIdentifierTemplate(dstName) != null) { - // channel to resource edge - ChannelGenerator ch = model.getChannelGenerator(srcName); - if (ch == null) { - ch = model.getIOChannelGenerator(srcName); - } - ch.removeChannelMember(model.getIdentifierTemplate(dstName)); - } - } else if (cell.isVertex()) { - String name = (String) cell.getValue(); - if (model.getChannelGenerator(name) != null) { - model.removeChannelGenerator(name); - } else if (model.getIOChannelGenerator(name) != null) { - model.removeIOChannelGenerator(name); - } else if (model.getIdentifierTemplate(name) != null) { - model.removeIdentifierTemplate(name); - } - } - } - graph.removeCells(graph.getSelectionCells()); - resetDataFlowGraph(); - } - - public void setChannelCode(DataTransferChannelGenerator ch, String code) { - ch.setSourceText(code); - TokenStream stream = new Parser.TokenStream(); - Parser parser = new Parser(stream); - - for (String line: code.split("\n")) { - stream.addLine(line); - } - try { - DataTransferChannelGenerator ch2 = parser.parseChannel(getModel()); - for (ChannelMember chm2: ch2.getInputChannelMembers()) { - for (ChannelMember chm: ch.getInputChannelMembers()) { - if (chm2.getIdentifierTemplate() == chm.getIdentifierTemplate()) { - chm.setStateTransition(chm2.getStateTransition()); - break; - } - } - } - for (ChannelMember chm2: ch2.getOutputChannelMembers()) { - for (ChannelMember chm: ch.getOutputChannelMembers()) { - if (chm2.getIdentifierTemplate() == chm.getIdentifierTemplate()) { - chm.setStateTransition(chm2.getStateTransition()); - break; - } - } - } - for (ChannelMember chm2: ch2.getReferenceChannelMembers()) { - for (ChannelMember chm: ch.getReferenceChannelMembers()) { - if (chm2.getIdentifierTemplate() == chm.getIdentifierTemplate()) { - chm.setStateTransition(chm2.getStateTransition()); - break; - } - } - } - resetDataFlowGraph(); - } catch (ExpectedRightBracket | ExpectedChannel | ExpectedChannelName | ExpectedLeftCurlyBracket - | ExpectedInOrOutOrRefKeyword | ExpectedStateTransition | ExpectedEquals | ExpectedRHSExpression - | WrongLHSExpression | WrongRHSExpression | ExpectedAssignment e) { - e.printStackTrace(); - } - } - - private class SrcDstAttribute extends EdgeAttribute { - private Object src; - private Object dst; - - public SrcDstAttribute(Object src, Object dst) { - this.src = src; - this.dst = dst; - } - - public Object getSrouce() { - return src; - } - - public Object getDestination() { - return dst; - } - - public String toString() { - return ""; - } - } -} diff --git a/AlgebraicDataflowArchitectureModel/src/graphicalrefactor/layouts/DAGLayout.java b/AlgebraicDataflowArchitectureModel/src/graphicalrefactor/layouts/DAGLayout.java deleted file mode 100644 index 2665efe..0000000 --- a/AlgebraicDataflowArchitectureModel/src/graphicalrefactor/layouts/DAGLayout.java +++ /dev/null @@ -1,150 +0,0 @@ -package graphicalrefactor.layouts; - -import java.util.ArrayList; -import java.util.Arrays; -import java.util.Collections; -import java.util.List; - -import com.mxgraph.layout.mxGraphLayout; -import com.mxgraph.model.mxCell; -import com.mxgraph.model.mxGeometry; -import com.mxgraph.model.mxICell; -import com.mxgraph.model.mxIGraphModel; -import com.mxgraph.util.mxRectangle; -import com.mxgraph.view.mxCellState; -import com.mxgraph.view.mxGraph; -import com.mxgraph.view.mxGraphView; - -import models.dataConstraintModel.ChannelGenerator; -import models.dataConstraintModel.IdentifierTemplate; - -public class DAGLayout extends mxGraphLayout { - - public DAGLayout(mxGraph arg0) { - super(arg0); - } - - public void execute(Object parent) { - mxIGraphModel model = graph.getModel(); - - model.beginUpdate(); - try { - List> map = new ArrayList>(); - List moved = new ArrayList<>(); - - for (int i = 0; i < model.getChildCount(parent); i++) { - - mxCell cell = (mxCell) model.getChildAt(parent, i); - - if (model.isVertex(cell)) { - mxGraphView view = graph.getView(); - mxCellState state = view.getState(cell); - - if (!"ellipse".equals(state.getStyle().get("shape")) && (cell.getEdgeCount() == 1) && !"true".equals(state.getStyle().get("dashed"))) { - List newline = new ArrayList(); - map.add(newline); - lines(map, cell); - } - } - } - - // ���בւ� - sort(map, 0, false); - - // layout - int count; - int skip = 0; - mxGraphView view = graph.getView(); - for (int i = 0; i < map.size(); i++) { - count = 0; - for (int j = 0; j < map.get(i).size(); j++) { - mxGeometry geom = (mxGeometry) map.get(i).get(j).getGeometry().clone(); - mxCellState state = view.getState(map.get(i).get(j)); - if (checkmoved(moved, map.get(i).get(j))) { - if ("ellipse".equals(state.getStyle().get("shape"))){ - geom.setX(50 + j*200); - } else { - geom.setX(100 + j*200); - } - geom.setY(100 + (i-skip)*100); - model.setGeometry(map.get(i).get(j), geom); - moved.add(map.get(i).get(j).getId()); - } else if (geom.getX() < 100 + j*150) { - if ("ellipse".equals(state.getStyle().get("shape"))){ - geom.setX(50 + j*200); - } else { - geom.setX(100 + j*200); - } - geom.setY(100 + (i-skip)*100); - model.setGeometry(map.get(i).get(j), geom); - } else { - count++; - } - } - if (count >= map.get(i).size())skip++; - } - - } finally { - model.endUpdate(); - } - } - - - public void lines(List> mapping, mxCell next) { - mapping.get(mapping.size()-1).add(next); - int tagcount = 0; - mxCell edge; - mxGraphView view = graph.getView(); - for (int i = 0; i < next.getEdgeCount(); i++) { - edge = (mxCell) next.getEdgeAt(i); - mxCellState state = view.getState(edge); - if (next != (mxCell) edge.getTarget() && ((mxCell) edge.getTarget() != null) && !"true".equals(state.getStyle().get("dashed"))) { - tagcount++; - if (tagcount > 1) { - List newline = new ArrayList(mapping.get(mapping.size()-1)); - while (newline.get(newline.size()-1).getId() != next.getId()) { - newline.remove(newline.size()-1); - } - mapping.add(newline); - lines(mapping, (mxCell) edge.getTarget()); - - } else { - lines(mapping, (mxCell) edge.getTarget()); - } - } - } - } - - public boolean checkmoved(List list, mxCell cell) { - for (int i = 0; i < list.size(); i++) { - if (list.get(i).equals(cell.getId()))return false; - } - return true; - } - - public void sort(List> map, int n, boolean check) { - int msize = -1; - int mnum = -1; - if (check) { - for (int i = n; i < map.size(); i++) { - if (map.get(i).size() > msize && (map.get(n-1).get(0).getId().equals(map.get(i).get(0).getId()))) { - mnum = i; - } - } - } else { - for (int i = n; i < map.size(); i++) { - if (map.get(i).size() > msize) { - mnum = i; - } - } - } - if (mnum >= 0) { - Collections.swap(map, n, mnum); - sort(map, n+1, true); - } else if(n < map.size()) { - sort(map, n+1, false); - } - } - - -} \ No newline at end of file diff --git a/AlgebraicDataflowArchitectureModel/src/graphicalrefactor/views/GraphicalRefactor.java b/AlgebraicDataflowArchitectureModel/src/graphicalrefactor/views/GraphicalRefactor.java deleted file mode 100644 index ab035a5..0000000 --- a/AlgebraicDataflowArchitectureModel/src/graphicalrefactor/views/GraphicalRefactor.java +++ /dev/null @@ -1,98 +0,0 @@ -package graphicalrefactor.views; - -import java.util.ArrayList; -import java.util.List; - -import javax.swing.JFrame; - -import com.mxgraph.model.mxCell; -import com.mxgraph.model.mxGeometry; -import com.mxgraph.model.mxGraphModel; -import com.mxgraph.swing.mxGraphComponent; -import com.mxgraph.swing.handler.mxRubberband; -import com.mxgraph.swing.view.mxICellEditor; -import com.mxgraph.util.mxEvent; -import com.mxgraph.util.mxEventObject; -import com.mxgraph.util.mxEventSource.mxIEventListener; -import com.mxgraph.view.mxGraph; - -import graphicalrefactor.editor.Editor; - -public class GraphicalRefactor extends JFrame { - private static final long serialVersionUID = -8690140317781055614L; - public static final String title = "Visual Modeling Tool"; - - private Editor editor; - private mxGraph graph; - private GraphicalRefactorMenuBar menuBar; - private mxGraphComponent graphComponent; - - public GraphicalRefactor() { - setTitle(title); - setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); - - graph = new mxGraph() { - public boolean isPort(Object cell) { - mxGeometry geo = getCellGeometry(cell); - - return (geo != null) ? geo.isRelative() : false; - } - - public boolean isCellFoldable(Object cell, boolean collapse) { - return false; - } - }; - - editor = new Editor(graph); - - graphComponent = new mxGraphComponent(graph) { - protected mxICellEditor createCellEditor() { - return new GraphicalRefactorCellEditor(this, editor); - } - }; - graph.getModel().addListener(mxEvent.CHANGE, new mxIEventListener() { - public void invoke(Object sender, mxEventObject evt) { - List terminals = new ArrayList<>(); - mxCell cell = null; - for (Object change: ((List) evt.getProperties().get("changes"))) { - if (change instanceof mxGraphModel.mxTerminalChange) { - mxGraphModel.mxTerminalChange terminalChange = (mxGraphModel.mxTerminalChange) change; - cell = (mxCell) terminalChange.getCell(); - mxCell terminal = (mxCell) terminalChange.getTerminal(); - terminals.add(terminal); - } - } - if (terminals.size() == 2) { - if (!editor.connectEdge(cell, terminals.get(0), terminals.get(1))) { - graph.removeCells(new mxCell[] {cell}); - } - } - } - }); - getContentPane().add(graphComponent); - new mxRubberband(graphComponent); - graph.setAllowDanglingEdges(false); - graph.setCellsDisconnectable(true); - - menuBar = new GraphicalRefactorMenuBar(this); - setJMenuBar(menuBar); - setSize(870, 640); - } - - public mxGraph getGraph() { - return graph; - } - - public mxGraphComponent getGraphComponent() { - return graphComponent; - } - - public Editor getEditor() { - return editor; - } - - public void setEditor(Editor editor) { - this.editor = editor; - } - -} diff --git a/AlgebraicDataflowArchitectureModel/src/graphicalrefactor/views/GraphicalRefactorCellEditor.java b/AlgebraicDataflowArchitectureModel/src/graphicalrefactor/views/GraphicalRefactorCellEditor.java deleted file mode 100644 index 606c7e4..0000000 --- a/AlgebraicDataflowArchitectureModel/src/graphicalrefactor/views/GraphicalRefactorCellEditor.java +++ /dev/null @@ -1,249 +0,0 @@ -package graphicalrefactor.views; - -import java.awt.GridBagConstraints; -import java.awt.GridBagLayout; -import java.awt.Rectangle; -import java.util.EventObject; -import java.util.List; - -import javax.swing.BorderFactory; -import javax.swing.JComboBox; -import javax.swing.JLabel; -import javax.swing.JOptionPane; -import javax.swing.JPanel; -import javax.swing.JTextArea; -import javax.swing.JTextField; - -import com.mxgraph.model.mxCell; -import com.mxgraph.model.mxIGraphModel; -import com.mxgraph.swing.mxGraphComponent; -import com.mxgraph.swing.view.mxICellEditor; -import com.mxgraph.util.mxConstants; -import com.mxgraph.util.mxUtils; -import com.mxgraph.view.mxCellState; - -import graphicalrefactor.editor.Editor; -import models.algebra.Expression; -import models.dataFlowModel.DataTransferModel; -import models.dataFlowModel.DataTransferChannelGenerator; -import models.dataFlowModel.PushPullAttribute; -import models.dataFlowModel.PushPullValue; -import models.visualModel.FormulaChannelGenerator; -import parser.Parser; -import parser.Parser.TokenStream; -import parser.exceptions.ExpectedRightBracket; - -public class GraphicalRefactorCellEditor implements mxICellEditor { - public int DEFAULT_MIN_WIDTH = 70; - public int DEFAULT_MIN_HEIGHT = 30; - public double DEFAULT_MINIMUM_EDITOR_SCALE = 1; - - protected double minimumEditorScale = DEFAULT_MINIMUM_EDITOR_SCALE; - protected int minimumWidth = DEFAULT_MIN_WIDTH; - protected int minimumHeight = DEFAULT_MIN_HEIGHT; - - private Object editingCell; - private EventObject trigger; - private JComboBox comboBox; - private mxGraphComponent graphComponent; - private Editor editor; - - public GraphicalRefactorCellEditor(mxGraphComponent graphComponent, Editor editor) { - this.graphComponent = graphComponent; - this.editor = editor; - } - - @Override - public Object getEditingCell() { - return editingCell; - } - - @Override - public void startEditing(Object cell, EventObject evt) { - if (editingCell != null) { - stopEditing(true); - } - - if (!graphComponent.getGraph().getModel().isEdge(cell)) { - DataTransferModel model = editor.getModel(); - DataTransferChannelGenerator ch = (DataTransferChannelGenerator) model.getChannelGenerator((String) ((mxCell) cell).getValue()); - if (ch == null) { - ch = (DataTransferChannelGenerator) model.getIOChannelGenerator((String) ((mxCell) cell).getValue()); - if(ch == null) { - //resource - return; - } - } - - if(ch instanceof FormulaChannelGenerator) { - - JPanel panel = new JPanel(); - JLabel label1 = new JLabel("Formula: "); - JLabel label2 = new JLabel("Source: "); - GridBagLayout layout = new GridBagLayout(); - panel.setLayout(layout); - GridBagConstraints gbc = new GridBagConstraints(); - - gbc.gridx = 0; - gbc.gridy = 0; - layout.setConstraints(label1, gbc); - panel.add(label1); - - gbc.gridx = 1; - gbc.gridy = 0; - JTextField formulaText = new JTextField(((FormulaChannelGenerator) ch).getFormula(),15); - layout.setConstraints(formulaText, gbc); - panel.add(formulaText); - - gbc.gridx = 0; - gbc.gridy = 1; - layout.setConstraints(label2, gbc); - panel.add(label2); - - gbc.gridx = 1; - gbc.gridy = 1; - JTextArea textArea = new JTextArea(ch.getSourceText(),7,15); - textArea.setEditable(false); - layout.setConstraints(textArea, gbc); - panel.add(textArea); - - int r = JOptionPane.showConfirmDialog( - null, // owner window - panel, // message - "Edit Formula Channel", // window's title - JOptionPane.OK_CANCEL_OPTION, // option (button types) - JOptionPane.QUESTION_MESSAGE); // message type (icon types) - if(r == JOptionPane.OK_OPTION) { - TokenStream stream = new Parser.TokenStream(); - Parser parser = new Parser(stream); - - String formula = formulaText.getText(); - stream.addLine(formula.split(Parser.EQUALS)[1]); - - try { - Expression exp = parser.parseTerm(stream, editor.getModel()); - ((FormulaChannelGenerator) ch).setFormula(formula); - ((FormulaChannelGenerator) ch).setFormulaTerm(exp); - } catch (ExpectedRightBracket e) { - e.printStackTrace(); - } - } - }else { - JPanel panel = new JPanel(); - JTextArea textArea = new JTextArea(ch.getSourceText(), 10, 20); - panel.add(textArea); - // JEditorPane panel = new JEditorPane("text/plain", ch.toString()); - // panel.setEditable(true); - int ret = JOptionPane.showConfirmDialog(null, panel, "Channel Code", JOptionPane.OK_CANCEL_OPTION); - if (ret == JOptionPane.OK_OPTION) { - editor.setChannelCode(ch, textArea.getText()); - } - } - return; - } - - mxCellState state = graphComponent.getGraph().getView().getState(cell); - if (state != null && state.getLabel() != null && !state.getLabel().equals("")) { - editingCell = cell; - trigger = evt; - - double scale = Math.max(minimumEditorScale, graphComponent.getGraph().getView().getScale()); - Object value = graphComponent.getGraph().getModel().getValue(cell); - if (value != null && value instanceof PushPullAttribute) { - PushPullAttribute attr = (PushPullAttribute) value; - comboBox = new JComboBox<>(attr.getOptionStrings()); - comboBox.setBorder(BorderFactory.createEmptyBorder()); - comboBox.setOpaque(false); - comboBox.setBounds(getEditorBounds(state, scale)); - comboBox.setVisible(true); - graphComponent.getGraphControl().add(comboBox, 0); - comboBox.updateUI(); - } - } - } - - @Override - public void stopEditing(boolean cancel) { - if (editingCell != null) { - comboBox.transferFocusUpCycle(); - Object cell = editingCell; - editingCell = null; - if (!cancel) { - EventObject trig = trigger; - trigger = null; - Object value = graphComponent.getGraph().getModel().getValue(cell); - if (value != null && value instanceof PushPullAttribute) { - PushPullAttribute attr = (PushPullAttribute) value; - List options = attr.getOptions(); - PushPullValue selected = null; - for (PushPullValue option: options) { - if (option.toString().equals(getCurrentValue())) { - selected = option; - break; - } - } - if (selected != null) { - options.remove(selected); - options.add(0, selected); - } - graphComponent.labelChanged(cell, attr, trig); - } - } else { - mxCellState state = graphComponent.getGraph().getView().getState(cell); - graphComponent.redraw(state); - } - - if (comboBox.getParent() != null) { - comboBox.setVisible(false); - comboBox.getParent().remove(comboBox); - } - - graphComponent.requestFocusInWindow(); - } - } - - public String getCurrentValue() { - return (String) comboBox.getSelectedItem(); - } - - /** - * Returns the bounds to be used for the editor. - */ - public Rectangle getEditorBounds(mxCellState state, double scale) { - mxIGraphModel model = state.getView().getGraph().getModel(); - Rectangle bounds = null; - - bounds = state.getLabelBounds().getRectangle(); - bounds.height += 10; - - // Applies the horizontal and vertical label positions - if (model.isVertex(state.getCell())) { - String horizontal = mxUtils.getString(state.getStyle(), mxConstants.STYLE_LABEL_POSITION, mxConstants.ALIGN_CENTER); - - if (horizontal.equals(mxConstants.ALIGN_LEFT)) { - bounds.x -= state.getWidth(); - } else if (horizontal.equals(mxConstants.ALIGN_RIGHT)) { - bounds.x += state.getWidth(); - } - - String vertical = mxUtils.getString(state.getStyle(), - mxConstants.STYLE_VERTICAL_LABEL_POSITION, - mxConstants.ALIGN_MIDDLE); - - if (vertical.equals(mxConstants.ALIGN_TOP)) { - bounds.y -= state.getHeight(); - } else if (vertical.equals(mxConstants.ALIGN_BOTTOM)) { - bounds.y += state.getHeight(); - } - } - - bounds.setSize( - (int) Math.max(bounds.getWidth(), - Math.round(minimumWidth * scale)), - (int) Math.max(bounds.getHeight(), - Math.round(minimumHeight * scale))); - - return bounds; - } - -} diff --git a/AlgebraicDataflowArchitectureModel/src/graphicalrefactor/views/GraphicalRefactorMenuBar.java b/AlgebraicDataflowArchitectureModel/src/graphicalrefactor/views/GraphicalRefactorMenuBar.java deleted file mode 100644 index 7c0d477..0000000 --- a/AlgebraicDataflowArchitectureModel/src/graphicalrefactor/views/GraphicalRefactorMenuBar.java +++ /dev/null @@ -1,93 +0,0 @@ -package graphicalrefactor.views; - -import javax.swing.JMenu; -import javax.swing.JMenuBar; - -import graphicalrefactor.actions.CircleLayoutAction; -import graphicalrefactor.actions.DAGLayoutAction; -import graphicalrefactor.actions.DeleteAction; -import graphicalrefactor.actions.ExitAction; -import graphicalrefactor.actions.JavaPrototypeGenerateAction; -import graphicalrefactor.actions.JerseyPrototypeGenerateAction; -import graphicalrefactor.actions.NewChannelAction; -import graphicalrefactor.actions.NewFormulaChannelAction; -import graphicalrefactor.actions.NewIOChannelAction; -import graphicalrefactor.actions.NewModelAction; -import graphicalrefactor.actions.NewResourceAction; -import graphicalrefactor.actions.OpenAction; -import graphicalrefactor.actions.SaveAction; -import graphicalrefactor.actions.SaveAsAction; -import graphicalrefactor.actions.TreeLayoutAction; -import graphicalrefactor.actions.ZoomInAction; -import graphicalrefactor.actions.ZoomOutAction; -import graphicalrefactor.editor.Editor; - -public class GraphicalRefactorMenuBar extends JMenuBar { - private static final long serialVersionUID = 4811536194182272888L; - - private GraphicalRefactor graphicalModelRefactor = null; - private NewResourceAction newResourceAction = null; - private NewChannelAction newChannelAction = null; - private NewIOChannelAction newIOChannelAction = null; - private NewFormulaChannelAction newFormulaChannelAction = null; - private DeleteAction deleteAction = null; - private JavaPrototypeGenerateAction javaPrototypeGenerateAction = null; - private JerseyPrototypeGenerateAction jerseyPrototypeGenerateAction = null; - private DAGLayoutAction dagLayoutAction = null; - private TreeLayoutAction treeLayoutAction = null; - private CircleLayoutAction circleLayoutAction = null; - - public GraphicalRefactorMenuBar(GraphicalRefactor graphicalModelRefactor) { - this.graphicalModelRefactor = graphicalModelRefactor; - JMenu newMenu = new JMenu("New"); - - newMenu.add(new NewModelAction(graphicalModelRefactor)); - - newMenu.add(newResourceAction = new NewResourceAction(graphicalModelRefactor.getEditor())); - newMenu.add(newChannelAction = new NewChannelAction(graphicalModelRefactor.getEditor())); - newMenu.add(newIOChannelAction = new NewIOChannelAction(graphicalModelRefactor.getEditor())); - newMenu.add(newFormulaChannelAction = new NewFormulaChannelAction(graphicalModelRefactor.getEditor())); - - JMenu menu = null; - menu = add(new JMenu("File")); - menu.add(newMenu); - menu.add(new OpenAction(graphicalModelRefactor)); - menu.addSeparator(); - menu.add(new SaveAction(graphicalModelRefactor)); - menu.add(new SaveAsAction(graphicalModelRefactor)); - menu.addSeparator(); - menu.add(new ExitAction()); - - menu = add(new JMenu("Edit")); - menu.add(deleteAction = new DeleteAction(graphicalModelRefactor.getEditor())); - - - menu = add(new JMenu("Layout")); - menu.add(dagLayoutAction = new DAGLayoutAction(graphicalModelRefactor.getEditor())); - menu.add(treeLayoutAction = new TreeLayoutAction(graphicalModelRefactor.getEditor())); - menu.add(circleLayoutAction = new CircleLayoutAction(graphicalModelRefactor.getEditor())); - - menu = add(new JMenu("View")); - menu.add(new ZoomInAction(graphicalModelRefactor.getGraphComponent())); - menu.add(new ZoomOutAction(graphicalModelRefactor.getGraphComponent())); - - menu = add(new JMenu("Generate")); - menu.add(javaPrototypeGenerateAction = new JavaPrototypeGenerateAction(graphicalModelRefactor.getEditor())); - menu.add(jerseyPrototypeGenerateAction = new JerseyPrototypeGenerateAction(graphicalModelRefactor.getEditor())); - } - - public Editor getEditor() { - return graphicalModelRefactor.getEditor(); - } - - public void setEditor(Editor editor) { - newResourceAction.setEditor(editor); - newChannelAction.setEditor(editor); - newIOChannelAction.setEditor(editor); - deleteAction.setEditor(editor); - javaPrototypeGenerateAction.setEditor(editor); - jerseyPrototypeGenerateAction.setEditor(editor); - treeLayoutAction.setEditor(editor); - circleLayoutAction.setEditor(editor); - } -} diff --git a/AlgebraicDataflowArchitectureModel/src/models/DirectedGraph.java b/AlgebraicDataflowArchitectureModel/src/models/DirectedGraph.java index 3b9d1d3..d76545d 100644 --- a/AlgebraicDataflowArchitectureModel/src/models/DirectedGraph.java +++ b/AlgebraicDataflowArchitectureModel/src/models/DirectedGraph.java @@ -1,9 +1,10 @@ package models; +import java.io.Serializable; import java.util.HashSet; import java.util.Set; -public class DirectedGraph { +public class DirectedGraph implements Serializable{ private Set nodes = null; private Set edges = null; @@ -64,4 +65,8 @@ edge.getSource().removeOutEdge(edge); edge.getDestination().removeInEdge(edge); } + + protected void simpleAddEdge(Edge edge) { + edges.add(edge); + } } diff --git a/AlgebraicDataflowArchitectureModel/src/models/Edge.java b/AlgebraicDataflowArchitectureModel/src/models/Edge.java index 9ea2037..71ab977 100644 --- a/AlgebraicDataflowArchitectureModel/src/models/Edge.java +++ b/AlgebraicDataflowArchitectureModel/src/models/Edge.java @@ -1,6 +1,8 @@ package models; -public class Edge { +import java.io.Serializable; + +public class Edge implements Serializable { protected Node source; protected Node destination; private EdgeAttribute attribute; diff --git a/AlgebraicDataflowArchitectureModel/src/models/EdgeAttribute.java b/AlgebraicDataflowArchitectureModel/src/models/EdgeAttribute.java index ea6cdec..4be3197 100644 --- a/AlgebraicDataflowArchitectureModel/src/models/EdgeAttribute.java +++ b/AlgebraicDataflowArchitectureModel/src/models/EdgeAttribute.java @@ -1,5 +1,7 @@ package models; -public class EdgeAttribute { +import java.io.Serializable; + +public class EdgeAttribute implements Serializable{ } diff --git a/AlgebraicDataflowArchitectureModel/src/models/Node.java b/AlgebraicDataflowArchitectureModel/src/models/Node.java index 3fa1e28..589cc4f 100644 --- a/AlgebraicDataflowArchitectureModel/src/models/Node.java +++ b/AlgebraicDataflowArchitectureModel/src/models/Node.java @@ -1,11 +1,14 @@ package models; +import java.io.Serializable; +import java.util.ArrayList; +import java.util.Collection; import java.util.HashSet; import java.util.Set; -public class Node implements Cloneable { - private Set inEdges = null; - private Set outEdges = null; +public class Node implements Cloneable, Serializable { + protected Collection inEdges = null; + protected Collection outEdges = null; private NodeAttribute attribute; public Node() { @@ -13,19 +16,19 @@ outEdges = new HashSet<>(); } - public Set getInEdges() { + public Collection getInEdges() { return inEdges; } - public void setInEdges(Set inEdges) { + public void setInEdges(Collection inEdges) { this.inEdges = inEdges; } - public Set getOutEdges() { + public Collection getOutEdges() { return outEdges; } - public void setOutEdges(Set outEdges) { + public void setOutEdges(Collection outEdges) { this.outEdges = outEdges; } @@ -61,16 +64,16 @@ return outEdges.size(); } - public Set getPredecessors() { - Set predecessors = new HashSet(); + public Collection getPredecessors() { + Collection predecessors = new ArrayList(); for (Edge edge: inEdges) { predecessors.add(edge.getSource()); } return predecessors; } - public Set getSuccessors() { - Set successors = new HashSet(); + public Collection getSuccessors() { + Collection successors = new ArrayList(); for (Edge edge: outEdges) { successors.add(edge.getDestination()); } diff --git a/AlgebraicDataflowArchitectureModel/src/models/NodeAttribute.java b/AlgebraicDataflowArchitectureModel/src/models/NodeAttribute.java index 7d1ded2..6b38a9f 100644 --- a/AlgebraicDataflowArchitectureModel/src/models/NodeAttribute.java +++ b/AlgebraicDataflowArchitectureModel/src/models/NodeAttribute.java @@ -1,5 +1,7 @@ package models; -public class NodeAttribute { +import java.io.Serializable; + +public class NodeAttribute implements Serializable{ } diff --git a/AlgebraicDataflowArchitectureModel/src/models/algebra/Constant.java b/AlgebraicDataflowArchitectureModel/src/models/algebra/Constant.java index 440145e..cc1ffee 100644 --- a/AlgebraicDataflowArchitectureModel/src/models/algebra/Constant.java +++ b/AlgebraicDataflowArchitectureModel/src/models/algebra/Constant.java @@ -36,7 +36,7 @@ public String toImplementation(String[] sideEffects) { if (symbol.isImplGenerative()) { - String exp = symbol.generate(getType(), new String[] {}, new String[] {}, sideEffects); + String exp = symbol.generate(getType(), new String[] {}, new String[] {}, sideEffects); return exp; } return symbol.getImplName(); diff --git a/AlgebraicDataflowArchitectureModel/src/models/algebra/Expression.java b/AlgebraicDataflowArchitectureModel/src/models/algebra/Expression.java index f0aeadb..20ebbc4 100644 --- a/AlgebraicDataflowArchitectureModel/src/models/algebra/Expression.java +++ b/AlgebraicDataflowArchitectureModel/src/models/algebra/Expression.java @@ -1,10 +1,22 @@ package models.algebra; +import java.io.Serializable; import java.util.HashMap; -public abstract class Expression implements Cloneable { +public abstract class Expression implements Cloneable, Serializable { public abstract Expression getSubTerm(Position pos); + /** + * Get the unification between this expression and another expression. + * @param another another expression + * @return unified expression + */ public abstract Expression unify(Expression another); + /** + * Get the inverse map to obtain a sub-term of a given output value back from the output value itself. + * @param outputValue an output value (usually a term) + * @param targetPos a position in outputValue + * @return inverse map + */ public abstract Expression getInverseMap(Expression outputValue, Position targetPos); public abstract boolean contains(Expression exp); public abstract Object clone(); diff --git a/AlgebraicDataflowArchitectureModel/src/models/algebra/LambdaAbstraction.java b/AlgebraicDataflowArchitectureModel/src/models/algebra/LambdaAbstraction.java new file mode 100644 index 0000000..00a2981 --- /dev/null +++ b/AlgebraicDataflowArchitectureModel/src/models/algebra/LambdaAbstraction.java @@ -0,0 +1,30 @@ +package models.algebra; + +import java.util.ArrayList; +import java.util.List; + +public class LambdaAbstraction extends Symbol { + private List variables = null; + private Term term = null; + + public LambdaAbstraction(Variable variable, Term term) { + super("($" + variable.getName() + ")->" + term.toString(), 1, Type.LAMBDA); + this.variables = new ArrayList<>(); + this.variables.add(variable); + this.term = term; + } + + public LambdaAbstraction(List variables, Term term) { + super("($" + variables + ")->" + term.toString(), variables.size(), Type.LAMBDA); + this.variables = variables; + this.term = term; + } + + public List getVariables() { + return variables; + } + + public Term getTerm() { + return term; + } +} diff --git a/AlgebraicDataflowArchitectureModel/src/models/algebra/Position.java b/AlgebraicDataflowArchitectureModel/src/models/algebra/Position.java index a11aa71..034e231 100644 --- a/AlgebraicDataflowArchitectureModel/src/models/algebra/Position.java +++ b/AlgebraicDataflowArchitectureModel/src/models/algebra/Position.java @@ -1,11 +1,10 @@ package models.algebra; +import java.io.Serializable; import java.util.ArrayList; import java.util.List; -import models.dataConstraintModel.IdentifierTemplate; - -public class Position implements Cloneable { +public class Position implements Cloneable, Serializable { private ArrayList orders = new ArrayList(); public Position() { @@ -30,6 +29,14 @@ public boolean isEmpty() { return (orders == null || orders.size() == 0); } + + public boolean isAncestorOf(Position another) { + if (another.orders.size() < this.orders.size()) return false; + for (int i = 0; i < orders.size(); i++) { + if (this.orders.get(i) != another.orders.get(i)) return false; + } + return true; + } public Object clone() { return new Position((ArrayList) orders.clone()); diff --git a/AlgebraicDataflowArchitectureModel/src/models/algebra/Symbol.java b/AlgebraicDataflowArchitectureModel/src/models/algebra/Symbol.java index 5a06873..8c8c974 100644 --- a/AlgebraicDataflowArchitectureModel/src/models/algebra/Symbol.java +++ b/AlgebraicDataflowArchitectureModel/src/models/algebra/Symbol.java @@ -1,15 +1,17 @@ package models.algebra; -public class Symbol { - private String name; - private String implName; - private int arity = 0; // -1: variable number - private Type operatorType = Type.PREFIX; - private Type implOperatorType = Type.PREFIX; - private Symbol[] inverses = null; - private models.algebra.Type[] signature = null; - private int[] implParamOrder = null; - private IImplGenerator generator = null; +import java.io.Serializable; + +public class Symbol implements Serializable{ + protected String name; + protected String implName; + protected int arity = 0; // -1: variable number + protected Type operatorType = Type.PREFIX; + protected Type implOperatorType = Type.PREFIX; + protected Symbol[] inverses = null; + protected models.algebra.Type[] signature = null; + protected int[] implParamOrder = null; + protected IImplGenerator generator = null; public Symbol(String name) { this.name = name; @@ -89,6 +91,10 @@ public boolean isMethod() { return (operatorType == Type.METHOD || operatorType == Type.METHOD_WITH_SIDE_EFFECT); } + + public boolean isLambda() { + return (operatorType == Type.LAMBDA); + } public Symbol[] getInverses() { return inverses; diff --git a/AlgebraicDataflowArchitectureModel/src/models/algebra/Term.java b/AlgebraicDataflowArchitectureModel/src/models/algebra/Term.java index b7cad09..3c15d21 100644 --- a/AlgebraicDataflowArchitectureModel/src/models/algebra/Term.java +++ b/AlgebraicDataflowArchitectureModel/src/models/algebra/Term.java @@ -1,12 +1,14 @@ package models.algebra; import java.util.ArrayList; +import java.util.Arrays; import java.util.HashMap; +import java.util.List; import java.util.Map.Entry; public class Term extends Expression { protected Symbol symbol = null; - protected ArrayList children = new ArrayList<>(); + protected List children = new ArrayList<>(); protected Type type = null; public Term(Symbol symbol) { @@ -14,12 +16,18 @@ this.symbol = symbol; } - public Term(Symbol symbol, ArrayList children) { + public Term(Symbol symbol, List children) { super(); this.symbol = symbol; this.children = children; } + public Term(Symbol symbol, Expression[] children) { + super(); + this.symbol = symbol; + this.children = new ArrayList<>(Arrays.asList(children)); + } + public Symbol getSymbol() { return symbol; } @@ -55,7 +63,7 @@ return children.get(n); } - public ArrayList getChildren() { + public List getChildren() { return children; } @@ -123,6 +131,55 @@ } } + public Expression reduce() { + if (symbol.isLambda()) { + // Lambda beta-reduction + LambdaAbstraction newSymbol = ((LambdaAbstraction) symbol); + Term newTerm = newSymbol.getTerm(); + List newVariables = newSymbol.getVariables(); + List newChildren = children; + while (newVariables.size() > 0 && newChildren.size() > 0) { + newTerm = newTerm.substitute(newVariables.get(0), newChildren.get(0)); + newVariables = newVariables.subList(1, newVariables.size()); + newChildren = newChildren.subList(1, newChildren.size()); + newSymbol = new LambdaAbstraction(newVariables, newTerm); + } + if (newSymbol.arity == 0 && newChildren.size() == 0) { + return newTerm; + } else { + return new Term(newSymbol, newChildren); + } + } else { + // Calculate inverse map + List newChildren = new ArrayList<>(); + boolean bReduced = false; + for (Expression child: children) { + if (child instanceof Term && !(child instanceof Constant)) { + child = ((Term) (child)).reduce(); + bReduced = true; + } + newChildren.add(child); + } + if (symbol.arity == 1 && newChildren.size() == 1) { + Expression child = newChildren.get(0); + if (child instanceof Term && !(child instanceof Constant)) { + Symbol childSymbol = ((Term) child).getSymbol(); + if (childSymbol.getInverses() != null) { + for (int i = 0; i < childSymbol.getInverses().length; i++) { + if (symbol.equals(childSymbol.getInverses()[i])) { + return ((Term) child).getChild(i); + } + } + } + } + } + if (!bReduced) return this; + Term newTerm = new Term(symbol, newChildren); + newTerm.setType(type); + return newTerm; + } + } + @Override public Expression getInverseMap(Expression outputValue, Position targetPos) { if (targetPos.isEmpty()) return outputValue; @@ -185,7 +242,7 @@ if (getArity() == 2 && symbol.isInfix()) { return "(" + children.get(0) + symbol.toString() + children.get(1) + ")"; } - if (getArity() >= 1 && symbol.isMethod()) { + if ((getArity() >= 1 || getArity() == -1) && symbol.isMethod()) { String exp = children.get(0).toString() + "." + symbol.toString() + "("; String delimiter = ""; for (int i = 1; i < children.size(); i++) { @@ -268,9 +325,14 @@ return "(" + children.get(implParamOrder[0]).toImplementation(sideEffects) + symbol.toImplementation() + children.get(implParamOrder[1]).toImplementation(sideEffects) + ")"; } } - if (getArity() >= 1 && symbol.isImplMethod()) { + if ((getArity() >= 1 || getArity() == -1) && symbol.isImplMethod()) { if (implParamOrder == null) { - String exp = children.get(0).toImplementation(sideEffects) + "." + symbol.toImplementation() + "("; + String exp = null; + if (children.get(0) != null) { + exp = children.get(0).toImplementation(sideEffects) + "." + symbol.toImplementation() + "("; + } else { + exp = symbol.toImplementation() + "("; + } String delimiter = ""; for (int i = 1; i < children.size(); i++) { Expression e = children.get(i); @@ -280,7 +342,11 @@ exp += ")"; if (symbol.isImplWithSideEffect()) { sideEffects[0] = sideEffects[0] + exp + ";\n"; - exp = children.get(0).toImplementation(new String[] {""}); + if (children.get(0) != null) { + exp = children.get(0).toImplementation(new String[] {""}); + } else { + exp = ""; + } } return exp; } else { diff --git a/AlgebraicDataflowArchitectureModel/src/models/algebra/Type.java b/AlgebraicDataflowArchitectureModel/src/models/algebra/Type.java index 50b0285..060e74d 100644 --- a/AlgebraicDataflowArchitectureModel/src/models/algebra/Type.java +++ b/AlgebraicDataflowArchitectureModel/src/models/algebra/Type.java @@ -1,36 +1,37 @@ package models.algebra; +import java.io.Serializable; import java.util.ArrayList; import java.util.List; -public class Type { +public class Type implements Serializable{ private String typeName; private String implementationTypeName; private String interfaceTypeName; private List parentTypes = new ArrayList<>(); - public Type(String typeName, String implementastionTypeName) { + public Type(String typeName, String implementationTypeName) { this.typeName = typeName; - this.implementationTypeName = implementastionTypeName; - this.interfaceTypeName = implementastionTypeName; + this.implementationTypeName = implementationTypeName; + this.interfaceTypeName = implementationTypeName; } - public Type(String typeName, String implementastionTypeName, String interfaceTypeName) { + public Type(String typeName, String implementationTypeName, String interfaceTypeName) { this.typeName = typeName; - this.implementationTypeName = implementastionTypeName; + this.implementationTypeName = implementationTypeName; this.interfaceTypeName = interfaceTypeName; } - public Type(String typeName, String implementastionTypeName, Type parentType) { + public Type(String typeName, String implementationTypeName, Type parentType) { this.typeName = typeName; - this.implementationTypeName = implementastionTypeName; - this.interfaceTypeName = implementastionTypeName; + this.implementationTypeName = implementationTypeName; + this.interfaceTypeName = implementationTypeName; this.parentTypes.add(parentType); } - public Type(String typeName, String implementastionTypeName, String interfaceTypeName, Type parentType) { + public Type(String typeName, String implementationTypeName, String interfaceTypeName, Type parentType) { this.typeName = typeName; - this.implementationTypeName = implementastionTypeName; + this.implementationTypeName = implementationTypeName; this.interfaceTypeName = interfaceTypeName; this.parentTypes.add(parentType); } diff --git a/AlgebraicDataflowArchitectureModel/src/models/algebra/UnificationFailed.java b/AlgebraicDataflowArchitectureModel/src/models/algebra/UnificationFailed.java index b0de344..a3227b6 100644 --- a/AlgebraicDataflowArchitectureModel/src/models/algebra/UnificationFailed.java +++ b/AlgebraicDataflowArchitectureModel/src/models/algebra/UnificationFailed.java @@ -1,5 +1,7 @@ package models.algebra; -public class UnificationFailed extends Exception { +import java.io.Serializable; + +public class UnificationFailed extends Exception implements Serializable { } diff --git a/AlgebraicDataflowArchitectureModel/src/models/algebra/ValueUndefined.java b/AlgebraicDataflowArchitectureModel/src/models/algebra/ValueUndefined.java index 4c6de4c..d23dfa7 100644 --- a/AlgebraicDataflowArchitectureModel/src/models/algebra/ValueUndefined.java +++ b/AlgebraicDataflowArchitectureModel/src/models/algebra/ValueUndefined.java @@ -1,5 +1,7 @@ package models.algebra; -public class ValueUndefined extends Exception { +import java.io.Serializable; + +public class ValueUndefined extends Exception implements Serializable{ } diff --git a/AlgebraicDataflowArchitectureModel/src/models/controlFlowModel/CallEdge.java b/AlgebraicDataflowArchitectureModel/src/models/controlFlowModel/CallEdge.java new file mode 100644 index 0000000..e19986e --- /dev/null +++ b/AlgebraicDataflowArchitectureModel/src/models/controlFlowModel/CallEdge.java @@ -0,0 +1,17 @@ +package models.controlFlowModel; + +import models.Edge; +import models.dataFlowModel.PushPullValue; + +public class CallEdge extends Edge { + private PushPullValue selectedOption = PushPullValue.PUSHorPULL; + + public CallEdge(ObjectNode src, ObjectNode dst, PushPullValue selectedOption) { + super(src, dst); + this.selectedOption = selectedOption; + } + + public PushPullValue getSelectedOption() { + return this.selectedOption; + } +} diff --git a/AlgebraicDataflowArchitectureModel/src/models/controlFlowModel/CallEdgeAttribute.java b/AlgebraicDataflowArchitectureModel/src/models/controlFlowModel/CallEdgeAttribute.java new file mode 100644 index 0000000..2658597 --- /dev/null +++ b/AlgebraicDataflowArchitectureModel/src/models/controlFlowModel/CallEdgeAttribute.java @@ -0,0 +1,98 @@ +package models.controlFlowModel; + +import com.mxgraph.model.mxCell; + +import models.EdgeAttribute; +import models.dataFlowModel.PushPullValue; + +/************************************************************* + * Information of connection status of the call edge among nodes type of "Object-Node". + */ +public class CallEdgeAttribute extends EdgeAttribute { + private CallEdge callEdge = null; + private ObjectNode orginalSrcObjNode = null; + private mxCell srcCell = null; + private mxCell dstCell = null; + + /************************************************************* + * [ *constructor ] + /************************************************************* + * + */ + public CallEdgeAttribute(CallEdge callEdge, ObjectNode originalSrcObjNode, final mxCell srcCell, final mxCell dstCell) { + this.callEdge = callEdge; + this.callEdge.setAttribute(this); + + this.orginalSrcObjNode = originalSrcObjNode; + + this.srcCell = srcCell; + this.dstCell = dstCell; + } + + /************************************************************* + * + */ + public CallEdgeAttribute(CallEdge callEdge, final mxCell srcCell, final mxCell dstCell) { + this.callEdge = callEdge; + this.callEdge.setAttribute(this); + + this.srcCell = srcCell; + this.dstCell = dstCell; + } + + + /************************************************************* + * [ *public ] + /************************************************************* + * [ getter ] + /*************************************************************/ + public CallEdge getCallEdge() { + return callEdge; + } + + public ObjectNode getOriginalSourceObjectNode() { + return orginalSrcObjNode; + } + + public PushPullValue getSelectedOption() { + return callEdge.getSelectedOption(); + } + + public ObjectNode getSourceObjectNode() { + if( !(callEdge.getSource() instanceof ObjectNode) ) throw new ClassCastException("sourceNode isn't type of "); + return (ObjectNode)callEdge.getSource(); + } + + public ObjectNode getDestinationObjectNode() { + if( !(callEdge.getDestination() instanceof ObjectNode) ) throw new ClassCastException("destinationNode isn't type of "); + return (ObjectNode)callEdge.getDestination(); + } + + public mxCell getSourceCell() { + return srcCell; + } + + public mxCell getDestinationCell() { + return dstCell; + } + + public void setDestinationCell(final mxCell dstCell) { + this.dstCell = dstCell; + } + + /************************************************************* + * + */ + @Override + public String toString() { + String value = ""; + + if(2 <= callEdge.getSource().getOutEdges( ).size()) { + int order = (((ObjectNode)callEdge.getSource()).getOutEdgeCallOrder(callEdge)+ 1); + value += "[" + order + "]"; + } + + return value; + } + +} diff --git a/AlgebraicDataflowArchitectureModel/src/models/controlFlowModel/CallGraph.java b/AlgebraicDataflowArchitectureModel/src/models/controlFlowModel/CallGraph.java new file mode 100644 index 0000000..685cc85 --- /dev/null +++ b/AlgebraicDataflowArchitectureModel/src/models/controlFlowModel/CallGraph.java @@ -0,0 +1,66 @@ +package models.controlFlowModel; + +import java.util.HashMap; +import java.util.HashSet; +import java.util.Map; +import java.util.Set; + +import models.DirectedGraph; +import models.Node; +import models.dataFlowModel.PushPullValue; +import models.dataFlowModel.ResourceNode; + +public class CallGraph extends DirectedGraph { + protected Map statefulObjMap = null; + + public CallGraph() { + statefulObjMap = new HashMap<>(); + } + + public void addNode(Node node) { + if (node instanceof ResourceNode) { + ResourceNode resNode = (ResourceNode) node; + StatefulObjectNode objNode = statefulObjMap.get(resNode); + if (objNode == null) { + objNode = new StatefulObjectNode(resNode); + statefulObjMap.put(resNode, objNode); + super.addNode(objNode); + } + } else if (node instanceof StatefulObjectNode) { + StatefulObjectNode objNode = (StatefulObjectNode) node; + if (statefulObjMap.get(objNode.getResource()) == null) { + statefulObjMap.put(objNode.getResource(), objNode); + super.addNode(objNode); + } + } else { + super.addNode(node); + } + } + + public void addEdge(ResourceNode srcResNode, ResourceNode dstResNode, PushPullValue selectedOption) { + addNode(srcResNode); + addNode(dstResNode); + addEdge(new CallEdge(getStatefulObjectNode(srcResNode), getStatefulObjectNode(dstResNode), selectedOption)); + } + + public void insertEdge(ObjectNode srcObjNode, ObjectNode dstObjNode, PushPullValue selectedOption, int n) { + CallEdge edge = new CallEdge(srcObjNode, dstObjNode, selectedOption); + simpleAddEdge(edge); + addNode(srcObjNode); + addNode(dstObjNode); + srcObjNode.insertOutEdge(edge, n); + dstObjNode.addInEdge(edge); + } + + public StatefulObjectNode getStatefulObjectNode(ResourceNode resNode) { + return statefulObjMap.get(resNode); + } + + public Set getRootNodes() { + Set roots = new HashSet<>(getNodes()); + for (Node n: getNodes()) { + roots.removeAll(n.getSuccessors()); + } + return roots; + } +} diff --git a/AlgebraicDataflowArchitectureModel/src/models/controlFlowModel/CompositeCallEdgeAttribute.java b/AlgebraicDataflowArchitectureModel/src/models/controlFlowModel/CompositeCallEdgeAttribute.java new file mode 100644 index 0000000..389be85 --- /dev/null +++ b/AlgebraicDataflowArchitectureModel/src/models/controlFlowModel/CompositeCallEdgeAttribute.java @@ -0,0 +1,36 @@ +package models.controlFlowModel; + +import java.util.ArrayList; +import java.util.List; + +public class CompositeCallEdgeAttribute extends CallEdgeAttribute { + private CallEdgeAttribute currentEdgeAttr = null; + private List mergedCallEdgeAttrs = null; + + /************************************************************* + * [ *constructor ] + /************************************************************* + * + */ + public CompositeCallEdgeAttribute(final CallEdgeAttribute callEdgeAttr) { + super(callEdgeAttr.getCallEdge(), + callEdgeAttr.getOriginalSourceObjectNode(), + callEdgeAttr.getSourceCell(), callEdgeAttr.getDestinationCell() + ); + + this.currentEdgeAttr = (this.currentEdgeAttr == null) + ? callEdgeAttr : null; + } + + /************************************************************* + * [ *public ] + /************************************************************* + * + */ + public void mergeCallEdgeAttribute(final CallEdgeAttribute mergedCallEdgeAttr) { + if(this.currentEdgeAttr == null) return; + if(this.mergedCallEdgeAttrs == null) this.mergedCallEdgeAttrs = new ArrayList(); + this.mergedCallEdgeAttrs.add(mergedCallEdgeAttr); + } + +} diff --git a/AlgebraicDataflowArchitectureModel/src/models/controlFlowModel/ControlFlowDelegator.java b/AlgebraicDataflowArchitectureModel/src/models/controlFlowModel/ControlFlowDelegator.java new file mode 100644 index 0000000..01fca86 --- /dev/null +++ b/AlgebraicDataflowArchitectureModel/src/models/controlFlowModel/ControlFlowDelegator.java @@ -0,0 +1,227 @@ +package models.controlFlowModel; + +import java.util.ArrayList; +import java.util.List; + +import models.Edge; +import models.dataFlowModel.PushPullValue; + +/************************************************************* + * it has Delegation of Control-Flow algorithm. + */ +public class ControlFlowDelegator { + + private ControlFlowGraph controlFlowGraph = null; + + /************************************************************* + * [ *constructor ] + /************************************************************* + * + */ + public ControlFlowDelegator(final ControlFlowGraph controlFlowGraph) { + this.controlFlowGraph = controlFlowGraph; + } + + /************************************************************* + * [ *public ] + /************************************************************* + * + *@param callEdge + */ + public List searchDelegatableNodes(final CallEdge callEdge){ + List nodes = new ArrayList<>(); + + // 1. adding parentNode + ObjectNode delegatingNode = (ObjectNode) callEdge.getDestination(); + ObjectNode parentNode = (ObjectNode) callEdge.getSource(); + + if(parentNode == null || delegatingNode == null) + throw new NullPointerException("parentNode is null."); + if( !(parentNode instanceof ObjectNode && delegatingNode instanceof ObjectNode)) + throw new ClassCastException("callEdge.getSource() is not ObjectNode"); + + // if the relation of "delegatingNode" to "parentNode" is 1 : 1 ? + // then return an empty list. + if( isRootNode(parentNode) && ! hasChildrenNode(parentNode) ) return nodes; + + // 2. collecting for each transfer method has nodes in the common area. + collectCommonTransferNodes(nodes, parentNode, delegatingNode); + + // 3. if the transfer method is PUSH-style, + // then search delegatable area. + collectParentNodesOnPushTransfer(nodes, delegatingNode, parentNode); + + + // switch objects by transfer type + return nodes; + } + + + /************************************************************* + * + *@param callEdge + */ + public List searchDependentableMediatorNodes(final CallEdge callEdge){ + List nodes = new ArrayList<>(); + + // If the transfer method is PULL-style, + // then search dependable mediator object. + collectDependableObjectNodeOnPullTransfer(nodes, callEdge); + + return nodes; + } + + /************************************************************* + * + */ + public void delegateCallEdge(CallEdge delegatingEdge, final ObjectNode dstObjNode) { + ObjectNode srcObjNode = (ObjectNode)delegatingEdge.getDestination(); + if(srcObjNode == null) throw new ClassCastException(); + + delegatingEdge.getSource().removeOutEdge(delegatingEdge); + srcObjNode.removeInEdge(delegatingEdge); + + // Reconnecting the edge to the new source object. + delegatingEdge.setDestination(srcObjNode); + delegatingEdge.setSource(dstObjNode); + + srcObjNode.addInEdge(delegatingEdge); + dstObjNode.addOutEdge(delegatingEdge); + } + + /************************************************************* + * [* private ] + /************************************************************* + * [ search ] + /************************************************************* + * Collecting nodes in the "nodes" parameter for each transfer method has nodes in the common area. + * @param nodes + * @param curObjNode + * @param delegatingObjNode + * @param selectedOption + */ + private void collectCommonTransferNodes(List nodes, ObjectNode curObjNode, final ObjectNode delegatingObjNode){ + if( !hasChildrenNode(curObjNode)) return; + + for(Edge e : curObjNode.getOutEdges()) { + ObjectNode foundNode = (ObjectNode)e.getDestination(); + + if( foundNode.equals(delegatingObjNode)) continue; + + nodes.add(foundNode); + collectCommonTransferNodes(nodes, foundNode, delegatingObjNode); + } + } + + /************************************************************* + * Collecting nodes in the "nodes" parameter for node of the area of PUSH-style transfer method. + * @param result in "nodes" parameter. + * @param curObjNode + */ + private void collectParentNodesOnPushTransfer(List nodes, ObjectNode curObjNode, final ObjectNode parentDelegatingNode) { + if( isRootNode(curObjNode) ) return; + if( isInEdgesConversingToNode(curObjNode) ) return; + + ObjectNode parentObjNode = (ObjectNode)curObjNode.getInEdge(0).getSource(); + if(parentObjNode == null) return; + + if( !parentDelegatingNode.equals(parentObjNode) ) + nodes.add(parentObjNode); + + int inEdgeCallOrder = parentObjNode.getOutEdgeCallOrder(curObjNode.getInEdge(0)); + for(Edge edge : parentObjNode.getOutEdges()) { + if( !(edge instanceof CallEdge)) continue; + + int callOrder = parentObjNode.getOutEdgeCallOrder((CallEdge)edge); + if(inEdgeCallOrder < callOrder) collectChildNodesOnPushTransfer(nodes, (CallEdge)edge); + } + + collectParentNodesOnPushTransfer(nodes, parentObjNode, parentDelegatingNode); + } + + /************************************************************* + * + * @param node + */ + private void collectChildNodesOnPushTransfer(List nodes, CallEdge callEdge) { + ObjectNode dstObjNode = (ObjectNode)callEdge.getDestination(); + if(dstObjNode == null) return; + + nodes.add(dstObjNode); + + if(!hasChildrenNode(dstObjNode)) return; + + for(Edge e : dstObjNode.getOutEdges()) { + CallEdge edge = (CallEdge)e; + if(edge == null) continue; + + ObjectNode foundNode = (ObjectNode)e.getDestination(); + if(foundNode == null) continue; + if(nodes.contains(foundNode))continue; + + collectChildNodesOnPushTransfer(nodes, edge); + } + } + + /************************************************************* + * + * + */ + private void collectDependableObjectNodeOnPullTransfer(List nodes, CallEdge callEdge) { + if(callEdge.getSelectedOption() != PushPullValue.PULL) return; + + // Are Both Source and Destination Stateful-Object? + StatefulObjectNode srcObjNode = (callEdge.getSource() instanceof StatefulObjectNode) + ? (StatefulObjectNode)callEdge.getSource() + : null; + + StatefulObjectNode dstObjNode = (callEdge.getDestination() instanceof StatefulObjectNode) + ? (StatefulObjectNode)callEdge.getDestination() + : null; + + if(srcObjNode == null || dstObjNode == null) return; + + // Has a destination connected with an object of a mediator? + for(Edge inEdge : dstObjNode.getInEdges()) { + CallEdge inCallEdge = (CallEdge)inEdge; + if(inCallEdge == null) continue; + + // It is a stateless object? (It is a mediator object?) + ObjectNode inSrcObjNode = (inCallEdge.getSource() instanceof ObjectNode) + ? (ObjectNode)inCallEdge.getSource() + : null; + if(inSrcObjNode == null) continue; + + if(inSrcObjNode instanceof StatefulObjectNode) continue; + if(inSrcObjNode instanceof EntryPointObjectNode) continue; + + nodes.add(inSrcObjNode); + } + } + + + /************************************************************* + * + * @param node + */ + private boolean isRootNode(final ObjectNode node) { + return node.getInEdges().isEmpty(); + } + + /************************************************************* + * + * @param node + */ + private boolean hasChildrenNode(final ObjectNode node) { + if(node.getOutEdges().size() < 1) return false; + return true; + } + + /************************************************************* + * + * @param node + */ + private boolean isInEdgesConversingToNode(final ObjectNode node) { + return ( 1 < node.getInEdges().size() ); + } +} diff --git a/AlgebraicDataflowArchitectureModel/src/models/controlFlowModel/ControlFlowGraph.java b/AlgebraicDataflowArchitectureModel/src/models/controlFlowModel/ControlFlowGraph.java new file mode 100644 index 0000000..c2f9477 --- /dev/null +++ b/AlgebraicDataflowArchitectureModel/src/models/controlFlowModel/ControlFlowGraph.java @@ -0,0 +1,141 @@ +package models.controlFlowModel; + +import java.util.Collection; +import java.util.HashMap; +import java.util.HashSet; +import java.util.Map; +import java.util.Set; + +import models.Edge; +import models.Node; +import models.algebra.Expression; +import models.algebra.Term; +import models.algebra.Variable; +import models.dataConstraintModel.Channel; +import models.dataConstraintModel.ChannelMember; +import models.dataFlowModel.DataFlowEdge; +import models.dataFlowModel.DataFlowGraph; +import models.dataFlowModel.DataTransferChannel; +import models.dataFlowModel.DataTransferModel; +import models.dataFlowModel.IFlowGraph; +import models.dataFlowModel.PushPullAttribute; +import models.dataFlowModel.PushPullValue; +import models.dataFlowModel.ResourceNode; + +public class ControlFlowGraph implements IFlowGraph { + private DataFlowGraph dataFlowGraph; + private CallGraph pushCallGraph; + private CallGraph pullCallGraph; + + public ControlFlowGraph(DataFlowGraph dataFlowGraph, DataTransferModel model) { + this.dataFlowGraph = dataFlowGraph; + this.pushCallGraph = new CallGraph(); + this.pullCallGraph = new CallGraph(); + for (Edge e: dataFlowGraph.getEdges()) { + PushPullAttribute pushPull = ((PushPullAttribute) ((DataFlowEdge) e).getAttribute()); + ResourceNode srcNode = (ResourceNode) e.getSource(); + ResourceNode dstNode = (ResourceNode) e.getDestination(); + if (pushPull.getOptions().get(0) == PushPullValue.PUSH) { + // same direction as the data flow + pushCallGraph.addEdge(srcNode, dstNode, PushPullValue.PUSH); + } else { + // reverse direction to the data flow + pullCallGraph.addEdge(dstNode, srcNode, PushPullValue.PULL); + } + } + for (Channel ch: model.getIOChannels()) { + DataTransferChannel cio = (DataTransferChannel) ch; + EntryPointObjectNode srcNode = new EntryPointObjectNode(cio); + for (ChannelMember cm: cio.getChannelMembers()) { + if (srcNode.getName() == null) { + Expression exp = cm.getStateTransition().getMessageExpression(); + if (exp instanceof Term) { + srcNode.setName(((Term) exp).getSymbol().getName()); + } else if (exp instanceof Variable) { + srcNode.setName(((Variable) exp).getName()); + } + } + ResourceNode dstResNode = dataFlowGraph.getResouceNode(cm.getResource()); + StatefulObjectNode dstNode = pushCallGraph.getStatefulObjectNode(dstResNode); + if (dstNode == null) { + pushCallGraph.addNode(dstResNode); + dstNode = pushCallGraph.getStatefulObjectNode(dstResNode); + } + // from an I/O channel to a resource + pushCallGraph.insertEdge(srcNode, dstNode, PushPullValue.PUSH, 0); + } + } + } + + public ControlFlowGraph(DataFlowGraph dataFlowGraph, PushPullValue priority) { + this.dataFlowGraph = dataFlowGraph; + this.pushCallGraph = new CallGraph(); + this.pullCallGraph = new CallGraph(); + if (priority == PushPullValue.PUSH) { + // push-first + for (Edge e: dataFlowGraph.getEdges()) { + ResourceNode srcNode = (ResourceNode) e.getSource(); + ResourceNode dstNode = (ResourceNode) e.getDestination(); + // same direction as the data flow + pushCallGraph.addEdge(srcNode, dstNode, PushPullValue.PUSH); + } + } else { + // pull-first + for (Edge e: dataFlowGraph.getEdges()) { + ResourceNode srcNode = (ResourceNode) e.getSource(); + ResourceNode dstNode = (ResourceNode) e.getDestination(); + PushPullAttribute pushPull = ((PushPullAttribute) ((DataFlowEdge) e).getAttribute()); + if (pushPull.getOptions().contains(PushPullValue.PULL)) { + // Pull style is selectable + // reverse direction to the data flow + pullCallGraph.addEdge(dstNode, srcNode, PushPullValue.PULL); + } else { + // Pull style is not selectable + // same direction as the data flow + pushCallGraph.addEdge(srcNode, dstNode, PushPullValue.PUSH); + } + } + } + } + + public DataFlowGraph getDataFlowGraph() { + return dataFlowGraph; + } + + public CallGraph getPushCallGraph() { + return pushCallGraph; + } + + public CallGraph getPullCallGraph() { + return pullCallGraph; + } + + @Override + public Map> getAllNodes() { + Map> allNodeSets = new HashMap<>(); + for (Node n: pushCallGraph.getNodes()) { + Set nodeSet = new HashSet<>(); + nodeSet.add(n); + allNodeSets.put(n, nodeSet); + } + for (Node n: pullCallGraph.getNodes()) { + if (n instanceof StatefulObjectNode) { + ResourceNode resNode = ((StatefulObjectNode) n).getResource(); + Set nodeSet = null; + if (pushCallGraph.getStatefulObjectNode(resNode) != null) { + // Merge a stateful object node in the push call graph and that in the pull call graph. + nodeSet = allNodeSets.get(pushCallGraph.getStatefulObjectNode(resNode)); + } else { + nodeSet = new HashSet<>(); + } + nodeSet.add(n); + allNodeSets.put(n, nodeSet); + } else { + Set nodeSet = new HashSet<>(); + nodeSet.add(n); + allNodeSets.put(n, nodeSet); + } + } + return allNodeSets; + } +} diff --git a/AlgebraicDataflowArchitectureModel/src/models/controlFlowModel/EntryPointObjectNode.java b/AlgebraicDataflowArchitectureModel/src/models/controlFlowModel/EntryPointObjectNode.java new file mode 100644 index 0000000..8100090 --- /dev/null +++ b/AlgebraicDataflowArchitectureModel/src/models/controlFlowModel/EntryPointObjectNode.java @@ -0,0 +1,40 @@ +package models.controlFlowModel; + +import models.dataFlowModel.DataTransferChannel; + +/************************************************************* + * An object is mapped to I/O channel. + * ToDo: Fecthing name from in Data-Flow-Graph + */ +public class EntryPointObjectNode extends ObjectNode { + DataTransferChannel ioChannel = null; + + /************************************************************* + * [ *constructor ] + /************************************************************* + * + */ + public EntryPointObjectNode(DataTransferChannel ioChannel) { + super(null); + this.ioChannel = ioChannel; + } + + public EntryPointObjectNode(String name, DataTransferChannel ioChannel) { + super(name); + this.ioChannel = ioChannel; + } + + /************************************************************* + * [ *public ] + /************************************************************* + * + */ + public DataTransferChannel getIOChannel() { + return ioChannel; + } + + public void setIOChannel(DataTransferChannel ioChannel) { + this.ioChannel = ioChannel; + } + +} diff --git a/AlgebraicDataflowArchitectureModel/src/models/controlFlowModel/ObjectNode.java b/AlgebraicDataflowArchitectureModel/src/models/controlFlowModel/ObjectNode.java new file mode 100644 index 0000000..9303eb3 --- /dev/null +++ b/AlgebraicDataflowArchitectureModel/src/models/controlFlowModel/ObjectNode.java @@ -0,0 +1,90 @@ +package models.controlFlowModel; + +import java.util.ArrayList; +import java.util.List; + +import models.Edge; +import models.Node; + +/************************************************************* +* +*/ +public class ObjectNode extends Node { + protected String name = ""; + + /************************************************************* + * [ *constructor] + /************************************************************* + */ + public ObjectNode(String name) { + inEdges = new ArrayList<>(); + outEdges = new ArrayList<>(); + + this.name = name; + } + + /************************************************************* + * [ *public ] + /************************************************************* + * + */ + public String getName() { + return name; + } + + public void setName(String name) { + this.name = name; + } + + public CallEdge getInEdge(int i) { + return (CallEdge) ((List) inEdges).get(i); + } + + public CallEdge getOutEdge(int i) { + return (CallEdge) ((List) outEdges).get(i); + } + + public CallEdge findEdgeInInEdges(final CallEdge edge) { + for(Edge e : inEdges) { + if( e instanceof CallEdge) return (CallEdge)e; + } + return null; + } + + public void insertOutEdge(CallEdge edge, int n) { + ((List) outEdges).add(n, edge); + } + + public CallEdge findEdgeInOutEdges(final CallEdge edge) { + for(Edge e : outEdges) { + if( e instanceof CallEdge) return (CallEdge)e; + } + return null; + } + + public int getChildrenNum() { + return outEdges.size(); + } + + public int getOutEdgeCallOrder(final CallEdge callEdge) { + for(int i = 0; i < outEdges.size(); i++) { + if(callEdge.equals(getOutEdge(i))) return i; + } + return -1; + } + + public ObjectNode getChildren(int i) { + return (ObjectNode) ((List) outEdges).get(i).getDestination(); + } + + /************************************************************* + * + */ + public void sortOutEdgesByCallOrder(final int curOrder, final int callOrder) { + ArrayList edges = ((ArrayList)outEdges); + Edge edge = ((List)outEdges).get(curOrder); + + edges.remove(curOrder); + edges.add(callOrder-1, edge); + } +} diff --git a/AlgebraicDataflowArchitectureModel/src/models/controlFlowModel/ObjectNodeAttribute.java b/AlgebraicDataflowArchitectureModel/src/models/controlFlowModel/ObjectNodeAttribute.java new file mode 100644 index 0000000..5ac52e2 --- /dev/null +++ b/AlgebraicDataflowArchitectureModel/src/models/controlFlowModel/ObjectNodeAttribute.java @@ -0,0 +1,112 @@ +package models.controlFlowModel; + +import models.NodeAttribute; + +/************************************************************* + * + * @author k-fujii + * + */ +public class ObjectNodeAttribute extends NodeAttribute { + private ObjectNode objectNode = null; + private String shapeStyle = ""; + + /************************************************************* + * [ *constructor ] + /************************************************************* + * + */ + public ObjectNodeAttribute(final ObjectNode objectNode) { + this.objectNode = objectNode; + this.objectNode.setAttribute(this); + + // Setting a shape style of cell + if(objectNode instanceof StatefulObjectNode) { + shapeStyle = "shape=ellipse;perimeter=ellipsePerimeter;"; + } + else if(objectNode instanceof EntryPointObjectNode) { + shapeStyle = "shape=rectangle;perimeter=rectanglePerimeter;"; + } + else { + shapeStyle = "shape=hexagon;perimeter=hexagonPerimeter;"; + } + + // Setting a name of cell + if(objectNode.name != null) return; + if(objectNode.name.isEmpty()) return; + + if( objectNode instanceof StatefulObjectNode ) { + objectNode.name = objectNode.getName(); + } + else if(objectNode instanceof EntryPointObjectNode){ + objectNode.name = "entryPoint"; + } + } + + /************************************************************* + * [ *public ] + /************************************************************* + * [ getter ] + /************************************************************* + * + * @return + */ + public ObjectNode getObjectNode() { + return objectNode; + } + + /************************************************************* + * + */ + public String getDefaultStyle() { + String style = ";"; + + return objectNode instanceof StatefulObjectNode + ? shapeStyle + style + : shapeStyle + style; + } + + /************************************************************* + * + */ + public String getEnableStyle() { + String style = "fillColor=#7fffd4;"; + style += "strokeColor=#66cdaa;"; + style += "strokeWidth=2;"; + + return objectNode instanceof StatefulObjectNode + ? shapeStyle + style + : shapeStyle + style; + } + + /************************************************************* + * + */ + public String getDisableStyle() { + String style = "fillColor=#999999"; + + return objectNode instanceof StatefulObjectNode + ? shapeStyle + style + : shapeStyle + style; + } + + /************************************************************* + * + */ + public String getDelegatingStyle() { + String style = "strokeWidth=4;"; + style += "strokeColor=#4169e;"; + + return shapeStyle + style; + } + + /************************************************************* + * showing label of mxCell + */ + @Override + public String toString() { + return objectNode instanceof StatefulObjectNode + ? ((StatefulObjectNode) objectNode).getResource().getResource().getResourceName() + : objectNode.getName(); + } +} diff --git a/AlgebraicDataflowArchitectureModel/src/models/controlFlowModel/StatefulObjectNode.java b/AlgebraicDataflowArchitectureModel/src/models/controlFlowModel/StatefulObjectNode.java new file mode 100644 index 0000000..b627259 --- /dev/null +++ b/AlgebraicDataflowArchitectureModel/src/models/controlFlowModel/StatefulObjectNode.java @@ -0,0 +1,17 @@ +package models.controlFlowModel; + +import models.dataFlowModel.ResourceNode; + +public class StatefulObjectNode extends ObjectNode { + private ResourceNode resource; + + public StatefulObjectNode(ResourceNode resource) { + super(resource.getResource().getResourceName()); + this.resource = resource; + } + + public ResourceNode getResource() { + return resource; + } + +} diff --git a/AlgebraicDataflowArchitectureModel/src/models/dataConstraintModel/Channel.java b/AlgebraicDataflowArchitectureModel/src/models/dataConstraintModel/Channel.java new file mode 100644 index 0000000..4ef7058 --- /dev/null +++ b/AlgebraicDataflowArchitectureModel/src/models/dataConstraintModel/Channel.java @@ -0,0 +1,97 @@ +package models.dataConstraintModel; + +import java.io.Serializable; +import java.util.HashSet; +import java.util.Set; + +import models.algebra.Variable; + +public class Channel implements Serializable { + protected String channelName; + protected Set selectors = null; + protected Set channelMembers = null; + protected String sourceText = null; + + public Channel(String channelName) { + this.channelName = channelName; + selectors = new HashSet<>(); + channelMembers = new HashSet<>(); + } + + public Channel(String channelName, Set variables) { + this.channelName = channelName; + selectors = new HashSet<>(); + for (Variable var: variables) { + selectors.add(new Selector(var)); + } + channelMembers = new HashSet<>(); + } + + public String getChannelName() { + return channelName; + } + + public Set getChannelSelectors() { + return selectors; + } + + public void setChannelSelectors(Set selectors) { + this.selectors = selectors; + } + + public void addSelector(Selector selector) { + selectors.add(selector); + } + + public Set getChannelMembers() { + return channelMembers; + } + + public void setChannelMembers(Set channelMembers) { + this.channelMembers = channelMembers; + for (ChannelMember channelMember: channelMembers) { + for (Selector selector: channelMember.getSelectors()) { + addSelector(selector); + } + } + } + + public void addChannelMember(ChannelMember channelMember) { + channelMembers.add(channelMember); + for (Selector selector: channelMember.getSelectors()) { + addSelector(selector); + } + } + + public void removeChannelMember(ResourcePath id) { + for (ChannelMember cm: channelMembers) { + if (cm.getResource() == id) { + channelMembers.remove(cm); + break; + } + } + } + + public Set getResources() { + Set resources = new HashSet<>(); + for (ChannelMember member: channelMembers) { + resources.add(member.getResource()); + } + return resources; + } + + public String toString() { + return channelName; + } + + public void setSourceText(String sourceText) { + this.sourceText = sourceText; + } + + public String getSourceText() { + if (sourceText == null) { + return toString(); + } + return sourceText; + } +} diff --git a/AlgebraicDataflowArchitectureModel/src/models/dataConstraintModel/ChannelGenerator.java b/AlgebraicDataflowArchitectureModel/src/models/dataConstraintModel/ChannelGenerator.java deleted file mode 100644 index 8a9bd1f..0000000 --- a/AlgebraicDataflowArchitectureModel/src/models/dataConstraintModel/ChannelGenerator.java +++ /dev/null @@ -1,107 +0,0 @@ -package models.dataConstraintModel; - -import java.util.HashSet; -import java.util.Set; - -public class ChannelGenerator { - protected String channelName; - protected Set groupSelectors = null; - protected Set channelSelectors = null; - protected Set channelMembers = null; - protected String sourceText = null; - - public ChannelGenerator(String channelName) { - this.channelName = channelName; - groupSelectors = new HashSet<>(); - channelSelectors = new HashSet<>(); - channelMembers = new HashSet<>(); - } - - public String getChannelName() { - return channelName; - } - - public Set getGroupSelectors() { - return groupSelectors; - } - - public void setGroupSelectors(Set groupSelectors) { - this.groupSelectors = groupSelectors; - } - - public void addGroupSelector(GroupSelector groupSelector) { - groupSelectors.add(groupSelector); - } - - public Set getChannelSelectors() { - return channelSelectors; - } - - public void setChannelSelectors(Set channelSelectors) { - this.channelSelectors = channelSelectors; - } - - public void addChannelSelector(ChannelSelector channelSelector) { - channelSelectors.add(channelSelector); - } - - public void addSelector(Selector selector) { - if (selector instanceof GroupSelector) { - groupSelectors.add((GroupSelector)selector); - } else if (selector instanceof ChannelSelector) { - channelSelectors.add((ChannelSelector)selector); - } - } - - public Set getChannelMembers() { - return channelMembers; - } - - public void setChannelMembers(Set channelMembers) { - this.channelMembers = channelMembers; - for (ChannelMember channelMember: channelMembers) { - for (Selector selector: channelMember.getSelectors()) { - addSelector(selector); - } - } - } - - public void addChannelMember(ChannelMember channelMember) { - channelMembers.add(channelMember); - for (Selector selector: channelMember.getSelectors()) { - addSelector(selector); - } - } - - public void removeChannelMember(IdentifierTemplate id) { - for (ChannelMember cm: channelMembers) { - if (cm.getIdentifierTemplate() == id) { - channelMembers.remove(cm); - break; - } - } - } - - public Set getIdentifierTemplates() { - Set identifierTemplates = new HashSet<>(); - for (ChannelMember member: channelMembers) { - identifierTemplates.add(member.getIdentifierTemplate()); - } - return identifierTemplates; - } - - public String toString() { - return channelName; - } - - public void setSourceText(String sourceText) { - this.sourceText = sourceText; - } - - public String getSourceText() { - if (sourceText == null) { - return toString(); - } - return sourceText; - } -} diff --git a/AlgebraicDataflowArchitectureModel/src/models/dataConstraintModel/ChannelMember.java b/AlgebraicDataflowArchitectureModel/src/models/dataConstraintModel/ChannelMember.java index 8c2f210..4e99cfb 100644 --- a/AlgebraicDataflowArchitectureModel/src/models/dataConstraintModel/ChannelMember.java +++ b/AlgebraicDataflowArchitectureModel/src/models/dataConstraintModel/ChannelMember.java @@ -1,25 +1,26 @@ package models.dataConstraintModel; +import java.io.Serializable; import java.util.ArrayList; import java.util.List; -public class ChannelMember { - private IdentifierTemplate identifierTemplate = null; +public class ChannelMember implements Serializable { + private ResourcePath resourcePath = null; private List selectors = null; private StateTransition stateTransition = null; - public ChannelMember(IdentifierTemplate identifierTemplate) { - this.identifierTemplate = identifierTemplate; + public ChannelMember(ResourcePath resourcePath) { + this.resourcePath = resourcePath; selectors = new ArrayList<>(); stateTransition = new StateTransition(); } - public IdentifierTemplate getIdentifierTemplate() { - return identifierTemplate; + public ResourcePath getResource() { + return resourcePath; } - public void setIdentifierTemplate(IdentifierTemplate identifierTemplate) { - this.identifierTemplate = identifierTemplate; + public void setResource(ResourcePath resourcePath) { + this.resourcePath = resourcePath; } public List getSelectors() { @@ -46,11 +47,11 @@ @Override public String toString() { if (stateTransition.getNextStateExpression() == null) { - return identifierTemplate.getResourceName() + "(" + return resourcePath.getResourceName() + "(" + stateTransition.getCurStateExpression() + "," + stateTransition.getMessageExpression() + ")"; } - return identifierTemplate.getResourceName() + "(" + return resourcePath.getResourceName() + "(" + stateTransition.getCurStateExpression() + "," + stateTransition.getMessageExpression() + ")" + " == " + stateTransition.getNextStateExpression(); diff --git a/AlgebraicDataflowArchitectureModel/src/models/dataConstraintModel/ChannelSelector.java b/AlgebraicDataflowArchitectureModel/src/models/dataConstraintModel/ChannelSelector.java deleted file mode 100644 index daa5ec5..0000000 --- a/AlgebraicDataflowArchitectureModel/src/models/dataConstraintModel/ChannelSelector.java +++ /dev/null @@ -1,5 +0,0 @@ -package models.dataConstraintModel; - -public class ChannelSelector extends Selector { - -} diff --git a/AlgebraicDataflowArchitectureModel/src/models/dataConstraintModel/DataConstraintModel.java b/AlgebraicDataflowArchitectureModel/src/models/dataConstraintModel/DataConstraintModel.java index c6fb2ea..35972a5 100644 --- a/AlgebraicDataflowArchitectureModel/src/models/dataConstraintModel/DataConstraintModel.java +++ b/AlgebraicDataflowArchitectureModel/src/models/dataConstraintModel/DataConstraintModel.java @@ -1,16 +1,21 @@ package models.dataConstraintModel; +import java.io.Serializable; import java.util.Collection; import java.util.HashMap; +import models.algebra.Expression; +import models.algebra.LambdaAbstraction; import models.algebra.Symbol; +import models.algebra.Term; import models.algebra.Type; +import models.algebra.Variable; import parser.Parser; -public class DataConstraintModel { - protected HashMap identifierTemplates = null; - protected HashMap channelGenerators = null; - protected HashMap ioChannelGenerators = null; +public class DataConstraintModel implements Serializable { + protected HashMap resourcePaths = null; + protected HashMap channels = null; + protected HashMap ioChannels = null; protected HashMap types = null; protected HashMap symbols = null; public static final Type typeInt = new Type("Int", "int"); @@ -27,9 +32,10 @@ public static final Type typePairInt = new Type("Pair", "Pair", "Pair", typePair); public static final Type typePairStr = new Type("Pair", "Pair", "Pair", typePair); public static final Type typePairDouble = new Type("Pair", "Pair", "Pair", typePair); - public static final Type typeMap = new Type("Map", "HashMap", "Map"); + public static final Type typeMap = new Type("Map", "HashMap<>", "Map"); + public static final JsonType typeJson = new JsonType("Json", "HashMap<>", "Map"); public static final Symbol add = new Symbol(Parser.ADD, 2, Symbol.Type.INFIX); - public static final Symbol mul = new Symbol(Parser.MUL, 2, Symbol.Type.INFIX);; + public static final Symbol mul = new Symbol(Parser.MUL, 2, Symbol.Type.INFIX); public static final Symbol sub = new Symbol(Parser.SUB, 2, Symbol.Type.INFIX); public static final Symbol div = new Symbol(Parser.DIV, 2, Symbol.Type.INFIX); public static final Symbol minus = new Symbol(Parser.MINUS, 1); @@ -45,6 +51,7 @@ public String generate(Type type, String[] children, String[] childrenSideEffects, String[] sideEffect) { String compType = ""; if (type != null) { + String temp = "temp_nil"; String interfaceType = type.getInterfaceTypeName(); if (interfaceType.contains("<")) { compType = interfaceType.substring(interfaceType.indexOf("<") + 1, interfaceType.lastIndexOf(">")); @@ -53,7 +60,8 @@ if (implType.indexOf('<') >= 0) { implType = implType.substring(0, implType.indexOf('<')); } - return "new " + implType + "<" + compType + ">()"; + sideEffect[0] = interfaceType + " " + temp + " = " + "new " + implType + "<" + compType + ">();\n"; + return temp; } return "new ArrayList<" + compType + ">()"; } @@ -125,7 +133,6 @@ public static final Symbol left = new Symbol("left", 1, Symbol.Type.PREFIX, "getLeft", Symbol.Type.METHOD); public static final Symbol right = new Symbol("right", 1, Symbol.Type.PREFIX, "getRight", Symbol.Type.METHOD); public static final Symbol insert = new Symbol("insert", 3, Symbol.Type.PREFIX, "put", Symbol.Type.METHOD_WITH_SIDE_EFFECT); -// public static final Symbol lookup = new Symbol("lookup", 2, Symbol.Type.PREFIX, "get", Symbol.Type.METHOD); public static final Symbol lookup = new Symbol("lookup", 2, Symbol.Type.PREFIX, new Symbol.IImplGenerator() { final int count[] = {0}; @Override @@ -137,12 +144,28 @@ impl += "\t" + temp + " = " + childrenImpl[0] + ".get(" + childrenImpl[1] + ");\n"; impl += "} else {\n"; impl += "\t" + temp + " = " + getDefaultValue(type) + ";\n"; - impl += "}\n"; + impl += "}"; sideEffect[0] = impl; count[0]++; return temp; } }); + public static final Symbol addMember = new Symbol("addMember", 3, Symbol.Type.PREFIX, "put", Symbol.Type.METHOD_WITH_SIDE_EFFECT); + public static final Symbol dot = new Symbol(Parser.DOT, 2, Symbol.Type.INFIX, "get", Symbol.Type.METHOD); + public static final Symbol dotParam = new Symbol(Parser.DOT, 2, Symbol.Type.INFIX, "get", Symbol.Type.METHOD); + public static final Symbol pi = new Symbol("PI", 0, Symbol.Type.PREFIX, "Math.PI", Symbol.Type.PREFIX); + public static final Symbol E = new Symbol("E", 0, Symbol.Type.PREFIX, "Math.E", Symbol.Type.PREFIX); + public static final Symbol sqrt = new Symbol("sqrt", 1, Symbol.Type.PREFIX, "Math.sqrt", Symbol.Type.PREFIX); + public static final Symbol sin = new Symbol("sin", 1, Symbol.Type.PREFIX, "Math.sin", Symbol.Type.PREFIX); + public static final Symbol cos = new Symbol("cos", 1, Symbol.Type.PREFIX, "Math.cos", Symbol.Type.PREFIX); + public static final Symbol tan = new Symbol("tan", 1, Symbol.Type.PREFIX, "Math.tan", Symbol.Type.PREFIX); + public static final Symbol asin = new Symbol("asin", 1, Symbol.Type.PREFIX, "Math.asin", Symbol.Type.PREFIX); + public static final Symbol acos = new Symbol("acos", 1, Symbol.Type.PREFIX, "Math.acos", Symbol.Type.PREFIX); + public static final Symbol atan = new Symbol("atan", 1, Symbol.Type.PREFIX, "Math.atan", Symbol.Type.PREFIX); + public static final Symbol pow = new Symbol("pow", 2, Symbol.Type.PREFIX, "Math.pow", Symbol.Type.PREFIX); + public static final Symbol exp = new Symbol("exp", 1, Symbol.Type.PREFIX, "Math.exp", Symbol.Type.PREFIX); + public static final Symbol log = new Symbol("log", 1, Symbol.Type.PREFIX, "Math.log", Symbol.Type.PREFIX); + public static final Symbol abs = new Symbol("abs", 1, Symbol.Type.PREFIX, "Math.abs", Symbol.Type.PREFIX); static { add.setInverses(new Symbol[] {sub, sub}); @@ -176,15 +199,38 @@ tuple.setSignature(new Type[] {typeTuple, null, null}); tuple.setInverses(new Symbol[] {fst, snd}); fst.setSignature(new Type[] {null, typeTuple}); + fst.setInverses(new Symbol[] {new LambdaAbstraction(new Variable("x"), new Term(tuple, new Expression[] {new Variable("x"), new Variable("y")}))}); snd.setSignature(new Type[] {null, typeTuple}); + snd.setInverses(new Symbol[] {new LambdaAbstraction(new Variable("y"), new Term(tuple, new Expression[] {new Variable("x"), new Variable("y")}))}); insert.setSignature(new Type[] {typeMap, typeMap, null, null}); lookup.setSignature(new Type[] {null, typeMap, null}); + addMember.setSignature(new Type[] {typeJson, typeJson, typeString, null}); + dot.setSignature(new Type[] {null, typeJson, typeString}); + dotParam.setSignature(new Type[] {null, null, null}); + pi.setSignature(new Type[] {typeDouble}); + E.setSignature(new Type[] {typeDouble}); + sqrt.setSignature(new Type[] {typeDouble, typeDouble}); + sin.setSignature(new Type[] {typeDouble, typeDouble}); + cos.setSignature(new Type[] {typeDouble, typeDouble}); + tan.setSignature(new Type[] {typeDouble, typeDouble}); + asin.setSignature(new Type[] {typeDouble, typeDouble}); + asin.setInverses(new Symbol[] {sin}); + acos.setSignature(new Type[] {typeDouble, typeDouble}); + acos.setInverses(new Symbol[] {cos}); + atan.setSignature(new Type[] {typeDouble, typeDouble}); + atan.setInverses(new Symbol[] {tan}); + pow.setSignature(new Type[] {typeDouble, typeDouble, typeDouble}); + exp.setSignature(new Type[] {typeDouble, typeDouble}); + exp.setInverses(new Symbol[] {log}); + log.setSignature(new Type[] {typeDouble, typeDouble}); + log.setInverses(new Symbol[] {exp}); + abs.setSignature(new Type[] {typeDouble, typeDouble}); } public DataConstraintModel() { - identifierTemplates = new HashMap<>(); - channelGenerators = new HashMap<>(); - ioChannelGenerators = new HashMap<>(); + resourcePaths = new HashMap<>(); + channels = new HashMap<>(); + ioChannels = new HashMap<>(); types = new HashMap<>(); addType(typeInt); addType(typeLong); @@ -196,6 +242,7 @@ addType(typePair); addType(typeTuple); addType(typeMap); + addType(typeJson); symbols = new HashMap<>(); addSymbol(add); addSymbol(mul); @@ -232,89 +279,105 @@ addSymbol(snd); addSymbol(insert); addSymbol(lookup); + addSymbol(addMember); + addSymbol(dot); + addSymbol(dotParam); + addSymbol(pi); + addSymbol(E); + addSymbol(sqrt); + addSymbol(sin); + addSymbol(cos); + addSymbol(tan); + addSymbol(asin); + addSymbol(acos); + addSymbol(atan); + addSymbol(pow); + addSymbol(exp); + addSymbol(log); + addSymbol(abs); } - public Collection getIdentifierTemplates() { - return identifierTemplates.values(); + public Collection getResourcePaths() { + return resourcePaths.values(); } - public IdentifierTemplate getIdentifierTemplate(String resourceName) { - return identifierTemplates.get(resourceName); + public ResourcePath getResourcePath(String resourceName) { + return resourcePaths.get(resourceName); } - public void addIdentifierTemplate(IdentifierTemplate identifierTemplate) { - identifierTemplates.put(identifierTemplate.getResourceName(), identifierTemplate); + public void addResourcePath(ResourcePath resourcePath) { + resourcePaths.put(resourcePath.getResourceName(), resourcePath); } - public void setIdentifierTemplates(HashMap identifierTemplates) { - this.identifierTemplates = identifierTemplates; + public void setResourcePaths(HashMap resourcePaths) { + this.resourcePaths = resourcePaths; } - public void removeIdentifierTemplate(String resourceName) { - IdentifierTemplate id = identifierTemplates.get(resourceName); - identifierTemplates.remove(resourceName); - for (ChannelGenerator ch: channelGenerators.values()) { + public void removeResourcePath(String resourceName) { + ResourcePath id = resourcePaths.get(resourceName); + resourcePaths.remove(resourceName); + for (Channel ch: channels.values()) { ch.removeChannelMember(id); } - for (ChannelGenerator ch: ioChannelGenerators.values()) { + for (Channel ch: ioChannels.values()) { ch.removeChannelMember(id); } } - public Collection getChannelGenerators() { - return channelGenerators.values(); + public Collection getChannels() { + return channels.values(); } - public ChannelGenerator getChannelGenerator(String channelName) { - return channelGenerators.get(channelName); + public Channel getChannel(String channelName) { + return channels.get(channelName); } - public void setChannelGenerators(HashMap channelGenerators) { - this.channelGenerators = channelGenerators; - for (ChannelGenerator g: channelGenerators.values()) { - for (IdentifierTemplate id: g.getIdentifierTemplates()) { - identifierTemplates.put(id.getResourceName(), id); + public void setChannels(HashMap channels) { + this.channels = channels; + for (Channel g: channels.values()) { + for (ResourcePath id: g.getResources()) { + resourcePaths.put(id.getResourceName(), id); } } } - public void addChannelGenerator(ChannelGenerator channelGenerator) { - channelGenerators.put(channelGenerator.getChannelName(), channelGenerator); - for (IdentifierTemplate id: channelGenerator.getIdentifierTemplates()) { - identifierTemplates.put(id.getResourceName(), id); + public void addChannel(Channel channel) { + channels.put(channel.getChannelName(), channel); + for (ResourcePath id: channel.getResources()) { + resourcePaths.put(id.getResourceName(), id); } } - public void removeChannelGenerator(String channelName) { - channelGenerators.remove(channelName); + public void removeChannel(String channelName) { + channels.remove(channelName); } - public Collection getIOChannelGenerators() { - return ioChannelGenerators.values(); + public Collection getIOChannels() { + return ioChannels.values(); } - public ChannelGenerator getIOChannelGenerator(String channelName) { - return ioChannelGenerators.get(channelName); + public Channel getIOChannel(String channelName) { + return ioChannels.get(channelName); } - public void setIOChannelGenerators(HashMap ioChannelGenerators) { - this.ioChannelGenerators = ioChannelGenerators; - for (ChannelGenerator g: ioChannelGenerators.values()) { - for (IdentifierTemplate id: g.getIdentifierTemplates()) { - identifierTemplates.put(id.getResourceName(), id); + public void setIOChannels(HashMap ioChannels) { + this.ioChannels = ioChannels; + for (Channel g: ioChannels.values()) { + for (ResourcePath id: g.getResources()) { + resourcePaths.put(id.getResourceName(), id); } } } - public void addIOChannelGenerator(ChannelGenerator ioChannelGenerator) { - ioChannelGenerators.put(ioChannelGenerator.getChannelName(), ioChannelGenerator); - for (IdentifierTemplate id: ioChannelGenerator.getIdentifierTemplates()) { - identifierTemplates.put(id.getResourceName(), id); + public void addIOChannel(Channel ioChannel) { + ioChannels.put(ioChannel.getChannelName(), ioChannel); + for (ResourcePath id: ioChannel.getResources()) { + resourcePaths.put(id.getResourceName(), id); } } - public void removeIOChannelGenerator(String ioChannelName) { - ioChannelGenerators.remove(ioChannelName); + public void removeIOChannel(String ioChannelName) { + ioChannels.remove(ioChannelName); } public void addType(Type type) { @@ -383,11 +446,11 @@ @Override public String toString() { String out = ""; - for (ChannelGenerator channelGenerator: ioChannelGenerators.values()) { - out += channelGenerator.toString(); + for (Channel channel: ioChannels.values()) { + out += channel.toString(); } - for (ChannelGenerator channelGenerator: channelGenerators.values()) { - out += channelGenerator.toString(); + for (Channel channel: channels.values()) { + out += channel.toString(); } return out; } @@ -395,8 +458,8 @@ public String getSourceText() { String out = ""; String init = ""; - for (IdentifierTemplate identifierTemplate: identifierTemplates.values()) { - String initializer = identifierTemplate.getInitText(); + for (ResourcePath resource: resourcePaths.values()) { + String initializer = resource.getInitText(); if (initializer != null) { init += initializer; } @@ -404,11 +467,11 @@ if (init.length() > 0) { out += "init {\n" + init + "}\n"; } - for (ChannelGenerator channelGenerator: ioChannelGenerators.values()) { - out += channelGenerator.getSourceText(); + for (Channel channel: ioChannels.values()) { + out += channel.getSourceText(); } - for (ChannelGenerator channelGenerator: channelGenerators.values()) { - out += channelGenerator.getSourceText(); + for (Channel channel: channels.values()) { + out += channel.getSourceText(); } return out; } diff --git a/AlgebraicDataflowArchitectureModel/src/models/dataConstraintModel/GroupSelector.java b/AlgebraicDataflowArchitectureModel/src/models/dataConstraintModel/GroupSelector.java deleted file mode 100644 index 66e5731..0000000 --- a/AlgebraicDataflowArchitectureModel/src/models/dataConstraintModel/GroupSelector.java +++ /dev/null @@ -1,5 +0,0 @@ -package models.dataConstraintModel; - -public class GroupSelector extends Selector { - -} diff --git a/AlgebraicDataflowArchitectureModel/src/models/dataConstraintModel/IdentifierTemplate.java b/AlgebraicDataflowArchitectureModel/src/models/dataConstraintModel/IdentifierTemplate.java deleted file mode 100644 index d91355c..0000000 --- a/AlgebraicDataflowArchitectureModel/src/models/dataConstraintModel/IdentifierTemplate.java +++ /dev/null @@ -1,70 +0,0 @@ -package models.dataConstraintModel; - -import models.algebra.Expression; -import models.algebra.Term; -import models.algebra.Type; - -public class IdentifierTemplate { - private String resourceName = null; - private Type resourceStateType = null; - private int numParameters = 0; - private Expression initialValue = null; - protected String initText = null; - - public IdentifierTemplate(String resourceName, int numParameters) { - this.resourceName = resourceName; - this.numParameters =numParameters; - } - - public IdentifierTemplate(String resourceName, Type resourceStateType, int numParameters) { - this.resourceName = resourceName; - this.resourceStateType = resourceStateType; - this.numParameters = numParameters; - } - - public String getResourceName() { - return resourceName; - } - - public int getNumberOfParameters() { - return numParameters; - } - - public Type getResourceStateType() { - return resourceStateType; - } - - public void setResourceStateType(Type resourceStateType) { - this.resourceStateType = resourceStateType; - if (initialValue != null) { - if (initialValue instanceof Term) { - ((Term) initialValue).setType(resourceStateType); - } - } - } - - public Expression getInitialValue() { - return initialValue; - } - - public void setInitialValue(Expression initialValue) { - this.initialValue = initialValue; - } - - public void setInitText(String initText) { - this.initText = initText; - } - - public String getInitText() { - return initText; - } - - public boolean equals(Object another) { - if (!(another instanceof IdentifierTemplate)) return false; - return resourceName.equals(((IdentifierTemplate) another).resourceName); - } - - public int hashCode() { - return resourceName.hashCode(); - } -} diff --git a/AlgebraicDataflowArchitectureModel/src/models/dataConstraintModel/JsonAccessor.java b/AlgebraicDataflowArchitectureModel/src/models/dataConstraintModel/JsonAccessor.java new file mode 100644 index 0000000..5d9c4fb --- /dev/null +++ b/AlgebraicDataflowArchitectureModel/src/models/dataConstraintModel/JsonAccessor.java @@ -0,0 +1,153 @@ +package models.dataConstraintModel; + +import java.util.HashMap; +import java.util.HashSet; +import java.util.List; +import java.util.Map; +import java.util.Set; + +import models.algebra.Constant; +import models.algebra.Expression; +import models.algebra.LambdaAbstraction; +import models.algebra.Position; +import models.algebra.Symbol; +import models.algebra.Term; +import models.algebra.Type; +import models.algebra.Variable; + +public class JsonAccessor extends Term { + + public JsonAccessor(Symbol symbol) { + super(symbol); + } + + public Type getType() { + if (symbol.equals(DataConstraintModel.dotParam)) { + Type valueType = null; + if (getChild(1) instanceof Term) { + valueType = ((Term) getChild(1)).getType(); + } else if (getChild(1) instanceof Variable) { + valueType = ((Variable) getChild(1)).getType(); + } + if (valueType != null) return valueType; + } + return super.getType(); + } + + + @Override + public Expression getInverseMap(Expression outputValue, Position targetPos) { + if (targetPos.isEmpty()) return outputValue; + targetPos = (Position) targetPos.clone(); + int i = targetPos.removeHeadOrder(); + Symbol[] inverseSymbols = symbol.getInverses(); + if (i == 0) { + if (symbol.equals(DataConstraintModel.dot) && getChildren().size() >= 2) { + // this term is `json.key`. + Expression expJson = getChild(0); + Expression expKey = getChild(1); + JsonType jsonType = null; + if (expJson instanceof Variable) { + jsonType = (JsonType) ((Variable) expJson).getType(); + } else if (expJson instanceof Term) { + jsonType = (JsonType) ((Term) expJson).getType(); + } + String keyName = null; + if (expKey instanceof Constant) { + keyName = ((Constant) expKey).getSymbol().getName(); + Term jsonTerm = new Constant(DataConstraintModel.nil); + jsonTerm.setType(DataConstraintModel.typeJson); + int v = 1; + Map vars = new HashMap<>(); + Set keySet = new HashSet<>(); + if (jsonType == null || jsonType == DataConstraintModel.typeJson) { + keySet.add(keyName); + } else { + keySet.addAll(jsonType.getKeys()); + } + for (String key: keySet) { + Term addMemberTerm = new Term(DataConstraintModel.addMember); // addMember(jsonTerm, key, v) + addMemberTerm.addChild(jsonTerm); + addMemberTerm.addChild(new Constant(key)); + Variable var = new Variable("v" + v); + addMemberTerm.addChild(var); + vars.put(key, var); + jsonTerm = addMemberTerm; + v++; + } + Variable var = vars.get(keyName); + LambdaAbstraction lambdaAbstraction = new LambdaAbstraction(var, jsonTerm); // v -> addMember(jsonTerm, key, v) + inverseSymbols = new Symbol[] { lambdaAbstraction }; + } + } else if (symbol.equals(DataConstraintModel.dotParam) && getChildren().size() >= 2) { + // this term is `json.{param}`. + Expression expListOrMap = getChild(0); + Expression expKey = getChild(1); + JsonType jsonType = null; + if (expListOrMap instanceof Variable) { + jsonType = (JsonType) ((Variable) expListOrMap).getType(); + } else if (expListOrMap instanceof Term) { + jsonType = (JsonType) ((Term) expListOrMap).getType(); + } + Type keyType = null; + if (expKey instanceof Variable) { + keyType = (JsonType) ((Variable) expKey).getType(); + } else if (expKey instanceof Term) { + keyType = (JsonType) ((Term) expKey).getType(); + } + if (jsonType != null && keyType != null) { + if (DataConstraintModel.typeList.isAncestorOf(jsonType) || keyType.equals(DataConstraintModel.typeInt)) { + Term setElementTerm = new Term(DataConstraintModel.set); // set(list, idx, v) + setElementTerm.addChild(new Constant(DataConstraintModel.nil)); + setElementTerm.addChild(expKey); + Variable var = new Variable("v"); + setElementTerm.addChild(var); + LambdaAbstraction lambdaAbstraction = new LambdaAbstraction(var, setElementTerm); // v -> set(list, idx, v) + inverseSymbols = new Symbol[] { lambdaAbstraction }; + } else if (DataConstraintModel.typeMap.isAncestorOf(jsonType) || keyType.equals(DataConstraintModel.typeString)) { + Term insertEntryTerm = new Term(DataConstraintModel.insert); // insert(map, key, v) + insertEntryTerm.addChild(new Constant(DataConstraintModel.nil)); + insertEntryTerm.addChild(expKey); + Variable var = new Variable("v"); + insertEntryTerm.addChild(var); + LambdaAbstraction lambdaAbstraction = new LambdaAbstraction(var, insertEntryTerm); // v -> insert(map, key, v) + inverseSymbols = new Symbol[] { lambdaAbstraction }; + } + } + } + } + if (inverseSymbols == null || i >= inverseSymbols.length || inverseSymbols[i] == null) return null; + Term inverseMap = new Term(inverseSymbols[i]); + inverseMap.addChild(outputValue); + for (int n = 0; n < inverseSymbols[i].getArity(); n++) { + if (n != i) { + inverseMap.addChild(children.get(n)); + } + } + return children.get(i).getInverseMap(inverseMap, targetPos); + } + + public String toString() { + if (symbol.equals(DataConstraintModel.dotParam)) { + return children.get(0).toString() + symbol.toString() + "{" + children.get(1).toString() + "}"; + } + return super.toString(); + } + + public String toImplementation(String[] sideEffects) { + if (symbol.equals(DataConstraintModel.dotParam)) { + return children.get(0).toImplementation(sideEffects) + symbol.toImplementation() + "{" + children.get(1).toImplementation(sideEffects) + "}"; + } + return super.toImplementation(sideEffects); + } + + @Override + public Object clone() { + JsonAccessor newTerm = new JsonAccessor(symbol); + for (Expression e: children) { + newTerm.addChild((Expression) e.clone()); + } + newTerm.type = type; + return newTerm; + } +} diff --git a/AlgebraicDataflowArchitectureModel/src/models/dataConstraintModel/JsonType.java b/AlgebraicDataflowArchitectureModel/src/models/dataConstraintModel/JsonType.java new file mode 100644 index 0000000..9f9e835 --- /dev/null +++ b/AlgebraicDataflowArchitectureModel/src/models/dataConstraintModel/JsonType.java @@ -0,0 +1,65 @@ +package models.dataConstraintModel; + +import java.util.HashMap; +import java.util.Map; +import java.util.Set; + +import models.algebra.Type; + +public class JsonType extends Type { + protected boolean isListOrMap = false; + protected Map memberTypes = null; + protected Type listOrMapElementType = null; + + public JsonType(String typeName, String implementationTypeName) { + super(typeName, implementationTypeName); + memberTypes = new HashMap<>(); + } + + public JsonType(String typeName, String implementationTypeName, String interfaceTypeName) { + super(typeName, implementationTypeName, interfaceTypeName); + memberTypes = new HashMap<>(); + } + + public JsonType(String typeName, String implementationTypeName, Type parentType) { + super(typeName, implementationTypeName, parentType); + memberTypes = new HashMap<>(); + } + + public JsonType(String typeName, String implementationTypeName, String interfaceTypeName, Type parentType) { + super(typeName, implementationTypeName, interfaceTypeName, parentType); + memberTypes = new HashMap<>(); + } + + public Map getMemberTypes() { + return memberTypes; + } + + public Type getMemberType(String key) { + return memberTypes.get(key); + } + + public Set getKeys() { + return memberTypes.keySet(); + } + + public void addMemberType(String key, Type valueType) { + memberTypes.put(key, valueType); + } + +// public boolean isListOrMap() { +// return isListOrMap; +// } +// +// public void setListOrMap(boolean isListOrMap) { +// this.isListOrMap = isListOrMap; +// } + + public Type getElementType() { + return listOrMapElementType; + } + + public void setElementType(Type listElementType) { + this.listOrMapElementType = listElementType; + } +} diff --git a/AlgebraicDataflowArchitectureModel/src/models/dataConstraintModel/ResourcePath.java b/AlgebraicDataflowArchitectureModel/src/models/dataConstraintModel/ResourcePath.java new file mode 100644 index 0000000..fb2e80b --- /dev/null +++ b/AlgebraicDataflowArchitectureModel/src/models/dataConstraintModel/ResourcePath.java @@ -0,0 +1,72 @@ +package models.dataConstraintModel; + +import java.io.Serializable; + +import models.algebra.Expression; +import models.algebra.Term; +import models.algebra.Type; + +public class ResourcePath implements Serializable { + private String resourceName = null; + private Type resourceStateType = null; + private int numParameters = 0; + private Expression initialValue = null; + protected String initText = null; + + public ResourcePath(String resourceName, int numParameters) { + this.resourceName = resourceName; + this.numParameters = numParameters; + } + + public ResourcePath(String resourceName, Type resourceStateType, int numParameters) { + this.resourceName = resourceName; + this.resourceStateType = resourceStateType; + this.numParameters = numParameters; + } + + public String getResourceName() { + return resourceName; + } + + public int getNumberOfParameters() { + return numParameters; + } + + public Type getResourceStateType() { + return resourceStateType; + } + + public void setResourceStateType(Type resourceStateType) { + this.resourceStateType = resourceStateType; + if (initialValue != null) { + if (initialValue instanceof Term) { + ((Term) initialValue).setType(resourceStateType); + } + } + } + + public Expression getInitialValue() { + return initialValue; + } + + public void setInitialValue(Expression initialValue) { + this.initialValue = initialValue; + } + + public void setInitText(String initText) { + this.initText = initText; + } + + public String getInitText() { + return initText; + } + + public boolean equals(Object another) { + if (!(another instanceof ResourcePath)) return false; + return resourceName.equals(((ResourcePath) another).resourceName); + } + + public int hashCode() { + return resourceName.hashCode(); + } +} diff --git a/AlgebraicDataflowArchitectureModel/src/models/dataConstraintModel/Selector.java b/AlgebraicDataflowArchitectureModel/src/models/dataConstraintModel/Selector.java index 1794428..f7439b2 100644 --- a/AlgebraicDataflowArchitectureModel/src/models/dataConstraintModel/Selector.java +++ b/AlgebraicDataflowArchitectureModel/src/models/dataConstraintModel/Selector.java @@ -1,5 +1,21 @@ package models.dataConstraintModel; -abstract public class Selector { +import java.io.Serializable; +import models.algebra.Variable; + +public class Selector implements Serializable { + private Variable variable = null; + + public Selector(Variable variable) { + this.setVariable(variable); + } + + public Variable getVariable() { + return variable; + } + + public void setVariable(Variable variable) { + this.variable = variable; + } } diff --git a/AlgebraicDataflowArchitectureModel/src/models/dataConstraintModel/StateTransition.java b/AlgebraicDataflowArchitectureModel/src/models/dataConstraintModel/StateTransition.java index 011045a..25b47be 100644 --- a/AlgebraicDataflowArchitectureModel/src/models/dataConstraintModel/StateTransition.java +++ b/AlgebraicDataflowArchitectureModel/src/models/dataConstraintModel/StateTransition.java @@ -1,9 +1,11 @@ package models.dataConstraintModel; +import java.io.Serializable; import java.util.ArrayList; import java.util.HashMap; import java.util.Map.Entry; +import models.algebra.Constant; import models.algebra.Expression; import models.algebra.InvalidMessage; import models.algebra.Position; @@ -12,7 +14,7 @@ import models.algebra.Variable; import models.dataFlowModel.ResolvingMultipleDefinitionIsFutureWork; -public class StateTransition { +public class StateTransition implements Serializable { private Expression curStateExpression = null; private Expression nextStateExpression = null; private Expression messageExpression = null; @@ -58,6 +60,9 @@ Position varPos = curStateVarEnt.getKey(); Expression valueCalc = curStateTerm.getInverseMap(curStateValue, varPos); if (valueCalc != null) { + if (valueCalc instanceof Term && !(valueCalc instanceof Constant)) { + valueCalc = ((Term) valueCalc).reduce(); + } ArrayList values = bindings.get(var); if (values == null) { values = new ArrayList(); @@ -87,6 +92,9 @@ Position varPos = nextStateVarEnt.getKey(); Expression valueCalc = nextStateTerm.getInverseMap(nextStateValue, varPos); if (valueCalc != null) { + if (valueCalc instanceof Term) { + valueCalc = ((Term) valueCalc).reduce(); + } ArrayList values = bindings.get(var); if (values == null) { values = new ArrayList(); @@ -97,12 +105,18 @@ } Expression messageTerm = getMessageExpression(); - if (!(messageTerm instanceof Term)) throw new InvalidMessage(); + if (!(messageTerm instanceof Term) && !(messageTerm instanceof Variable)) throw new InvalidMessage(); HashMap messageVars = messageTerm.getVariables(); for (Variable var: messageVars.values()) { if (bindings.get(var) != null) { if (bindings.get(var).size() > 1) throw new ResolvingMultipleDefinitionIsFutureWork(); - messageTerm = ((Term) messageTerm).substitute(var, bindings.get(var).iterator().next()); + if (messageTerm instanceof Term) { + messageTerm = ((Term) messageTerm).substitute(var, bindings.get(var).iterator().next()); + } else if (messageTerm instanceof Variable) { + if (messageTerm.equals(var)) { + return bindings.get(var).iterator().next(); + } + } } } return messageTerm; @@ -118,6 +132,9 @@ Position varPos = curStateVarEnt.getKey(); Expression valueCalc = curStateTerm.getInverseMap(curStateValue, varPos); if (valueCalc != null) { + if (valueCalc instanceof Term && !(valueCalc instanceof Constant)) { + valueCalc = ((Term) valueCalc).reduce(); + } ArrayList values = bindings.get(var); if (values == null) { values = new ArrayList(); @@ -128,12 +145,18 @@ } Expression messageTerm = getMessageExpression(); - if (!(messageTerm instanceof Term)) throw new InvalidMessage(); + if (!(messageTerm instanceof Term) && !(messageTerm instanceof Variable)) throw new InvalidMessage(); HashMap messageVars = messageTerm.getVariables(); for (Variable var: messageVars.values()) { if (bindings.get(var) != null) { if (bindings.get(var).size() > 1) throw new ResolvingMultipleDefinitionIsFutureWork(); - messageTerm = ((Term) messageTerm).substitute(var, bindings.get(var).iterator().next()); + if (messageTerm instanceof Term) { + messageTerm = ((Term) messageTerm).substitute(var, bindings.get(var).iterator().next()); + } else if (messageTerm instanceof Variable) { + if (messageTerm.equals(var)) { + return bindings.get(var).iterator().next(); + } + } } } return messageTerm; @@ -150,6 +173,9 @@ Position varPos = curStateVarEnt.getKey(); Expression valueCalc = curStateTerm.getInverseMap(curStateValue, varPos); if (valueCalc != null) { + if (valueCalc instanceof Term && !(valueCalc instanceof Constant)) { + valueCalc = ((Term) valueCalc).reduce(); + } if (bindings.get(var) != null) throw new ResolvingMultipleDefinitionIsFutureWork(); bindings.put(var, valueCalc); } @@ -178,6 +204,9 @@ nextStateTerm = ((Term) nextStateTerm).substitute(var, bindings.get(var)); } } + if (nextStateTerm instanceof Term && !(nextStateTerm instanceof Constant)) { + nextStateTerm = ((Term) nextStateTerm).reduce(); + } return nextStateTerm; } } diff --git a/AlgebraicDataflowArchitectureModel/src/models/dataFlowModel/DataFlowEdge.java b/AlgebraicDataflowArchitectureModel/src/models/dataFlowModel/DataFlowEdge.java index 3c3b25f..9de9359 100644 --- a/AlgebraicDataflowArchitectureModel/src/models/dataFlowModel/DataFlowEdge.java +++ b/AlgebraicDataflowArchitectureModel/src/models/dataFlowModel/DataFlowEdge.java @@ -3,18 +3,18 @@ import models.*; public class DataFlowEdge extends Edge { - protected DataTransferChannelGenerator channelGenerator = null; + protected DataTransferChannel channel = null; - public DataFlowEdge(ResourceNode src, ResourceNode dst, DataTransferChannelGenerator channelGenerator) { + public DataFlowEdge(ResourceNode src, ResourceNode dst, DataTransferChannel channel) { super(src, dst); - this.channelGenerator = channelGenerator; + this.channel = channel; } - public DataTransferChannelGenerator getChannelGenerator() { - return channelGenerator; + public DataTransferChannel getChannel() { + return channel; } public String toString() { - return channelGenerator.getChannelName(); + return channel.getChannelName(); } } diff --git a/AlgebraicDataflowArchitectureModel/src/models/dataFlowModel/DataFlowGraph.java b/AlgebraicDataflowArchitectureModel/src/models/dataFlowModel/DataFlowGraph.java index 5df4229..1b3a208 100644 --- a/AlgebraicDataflowArchitectureModel/src/models/dataFlowModel/DataFlowGraph.java +++ b/AlgebraicDataflowArchitectureModel/src/models/dataFlowModel/DataFlowGraph.java @@ -1,20 +1,24 @@ package models.dataFlowModel; +import java.util.Collection; import java.util.HashMap; +import java.util.HashSet; import java.util.Map; +import java.util.Set; import models.DirectedGraph; -import models.dataConstraintModel.IdentifierTemplate; +import models.Node; +import models.dataConstraintModel.ResourcePath; -public class DataFlowGraph extends DirectedGraph { - protected Map nodeMap = null; +public class DataFlowGraph extends DirectedGraph implements IFlowGraph { + protected Map nodeMap = null; public DataFlowGraph() { super(); nodeMap = new HashMap<>(); } - public void addNode(IdentifierTemplate id) { + public void addNode(ResourcePath id) { if (nodeMap.get(id) == null) { ResourceNode node = new ResourceNode(id); addNode(node); @@ -22,7 +26,7 @@ } } - public void addEdge(IdentifierTemplate in, IdentifierTemplate out, DataTransferChannelGenerator dfChannelGen) { + public void addEdge(ResourcePath in, ResourcePath out, DataTransferChannel dfChannel) { ResourceNode srcNode = nodeMap.get(in); if (srcNode == null) { srcNode = new ResourceNode(in); @@ -35,6 +39,26 @@ addNode(dstNode); nodeMap.put(out, dstNode); } - addEdge(new DataFlowEdge(srcNode, dstNode, dfChannelGen)); + addEdge(new DataFlowEdge(srcNode, dstNode, dfChannel)); + } + + public Collection getResouceNodes(){ + return nodeMap.values(); + } + + public ResourceNode getResouceNode(ResourcePath resourcePath) { +// if(nodeMap.get(identifierTemplate) == null) throw new NullPointerException(identifierTemplate.getResourceName() + " was not found."); // Because with this statement, the original JumpGame.model cannot be read. + return nodeMap.get(resourcePath); + } + + @Override + public Map> getAllNodes() { + Map> allNodeSets = new HashMap<>(); + for (Node n: super.getNodes()) { + Set nodeSet = new HashSet<>(); + nodeSet.add(n); + allNodeSets.put(n, nodeSet); + } + return allNodeSets; } } diff --git a/AlgebraicDataflowArchitectureModel/src/models/dataFlowModel/DataTransferChannel.java b/AlgebraicDataflowArchitectureModel/src/models/dataFlowModel/DataTransferChannel.java new file mode 100644 index 0000000..4241faa --- /dev/null +++ b/AlgebraicDataflowArchitectureModel/src/models/dataFlowModel/DataTransferChannel.java @@ -0,0 +1,273 @@ +package models.dataFlowModel; + +import java.util.HashMap; +import java.util.HashSet; +import java.util.Set; + +import models.algebra.Expression; +import models.algebra.InvalidMessage; +import models.algebra.Parameter; +import models.algebra.ParameterizedIdentifierIsFutureWork; +import models.algebra.Position; +import models.algebra.Term; +import models.algebra.UnificationFailed; +import models.algebra.ValueUndefined; +import models.algebra.Variable; +import models.dataConstraintModel.*; + +public class DataTransferChannel extends Channel { + protected Set inputChannelMembers = null; + protected Set outputChannelMembers = null; + protected Set referenceChannelMembers = null; + + public DataTransferChannel(String channelName) { + super(channelName); + inputChannelMembers = new HashSet<>(); + outputChannelMembers = new HashSet<>(); + referenceChannelMembers = new HashSet<>(); + } + + public Set getInputChannelMembers() { + return inputChannelMembers; + } + + public void setInputChannelMembers(Set inputChannelMembers) { + this.inputChannelMembers = inputChannelMembers; + } + + private void addInputChannelMember(ChannelMember inputChannelMember) { + inputChannelMembers.add(inputChannelMember); + } + + public Set getOutputChannelMembers() { + return outputChannelMembers; + } + + public void setOutputChannelMembers(Set outputChannelMembers) { + this.outputChannelMembers = outputChannelMembers; + } + + private void addOutputChannelMember(ChannelMember outputChannelMember) { + outputChannelMembers.add(outputChannelMember); + } + + public Set getReferenceChannelMembers() { + return referenceChannelMembers; + } + + public void setReferenceChannelMembers(Set referenceChannelMembers) { + this.referenceChannelMembers = referenceChannelMembers; + } + + private void addReferenceChannelMember(ChannelMember referenceChannelMember) { + referenceChannelMembers.add(referenceChannelMember); + } + + public void addChannelMemberAsInput(ChannelMember groupDependentResource) { + addChannelMember(groupDependentResource); + addInputChannelMember(groupDependentResource); + } + + public void addChannelMemberAsOutput(ChannelMember groupDependentResource) { + addChannelMember(groupDependentResource); + addOutputChannelMember(groupDependentResource); + } + + public void addChannelMemberAsReference(ChannelMember groupDependentResource) { + addChannelMember(groupDependentResource); + addReferenceChannelMember(groupDependentResource); + } + + public void removeChannelMember(ResourcePath id) { + for (ChannelMember cm: inputChannelMembers) { + if (cm.getResource() == id) { + inputChannelMembers.remove(cm); + super.removeChannelMember(id); + return; + } + } + for (ChannelMember cm: outputChannelMembers) { + if (cm.getResource() == id) { + outputChannelMembers.remove(cm); + super.removeChannelMember(id); + return; + } + } + for (ChannelMember cm: referenceChannelMembers) { + if (cm.getResource() == id) { + referenceChannelMembers.remove(cm); + super.removeChannelMember(id); + return; + } + } + } + + public Set getInputResources() { + Set inputResources = new HashSet<>(); + for (ChannelMember member: inputChannelMembers) { + inputResources.add(member.getResource()); + } + return inputResources; + } + + public Set getOutputResources() { + Set outputResources = new HashSet<>(); + for (ChannelMember member: outputChannelMembers) { + outputResources.add(member.getResource()); + } + return outputResources; + } + + public Set getReferenceResources() { + Set referenceResources = new HashSet<>(); + for (ChannelMember member: referenceChannelMembers) { + referenceResources.add(member.getResource()); + } + return referenceResources; + } + + /** + * Derive the update expression of the state of the target channel member. + * @param targetMember a channel member whose state is to be updated + * @return the derived update expression + * @throws ParameterizedIdentifierIsFutureWork + * @throws ResolvingMultipleDefinitionIsFutureWork + * @throws InvalidMessage + * @throws UnificationFailed + * @throws ValueUndefined + */ + public Expression deriveUpdateExpressionOf(ChannelMember targetMember) throws ParameterizedIdentifierIsFutureWork, ResolvingMultipleDefinitionIsFutureWork, InvalidMessage, UnificationFailed, ValueUndefined { + IResourceStateAccessor defaultStateAccessor = new IResourceStateAccessor() { + HashMap curStateParams = new HashMap<>(); + HashMap nextStateParams = new HashMap<>(); + + @Override + public Expression getCurrentStateAccessorFor(ResourcePath target, ResourcePath from) { + String resource = target.getResourceName(); + Parameter curStateParam = curStateParams.get(resource); + if (curStateParam == null) { + curStateParam = new Parameter("cur" + resource); + curStateParams.put(resource, curStateParam); + } + return curStateParam; + } + + @Override + public Expression getNextStateAccessorFor(ResourcePath target, ResourcePath from) { + String resource = target.getResourceName(); + Parameter nextStateParam = nextStateParams.get(resource); + if (nextStateParam == null) { + nextStateParam = new Parameter("next" + resource); + nextStateParams.put(resource, nextStateParam); + } + return nextStateParam; + } + }; + return deriveUpdateExpressionOf(targetMember, defaultStateAccessor); + } + + /** + * Derive the update expression of the state of the target channel member with a given resource state accessor. + * @param targetMember a channel member whose state is to be updated + * @param stateAccessor a resource state accessor + * @return the derived update expression + * @throws ParameterizedIdentifierIsFutureWork + * @throws ResolvingMultipleDefinitionIsFutureWork + * @throws InvalidMessage + * @throws UnificationFailed + * @throws ValueUndefined + */ + public Expression deriveUpdateExpressionOf(ChannelMember targetMember, IResourceStateAccessor stateAccessor) + throws ParameterizedIdentifierIsFutureWork, ResolvingMultipleDefinitionIsFutureWork, InvalidMessage, UnificationFailed, ValueUndefined { + return deriveUpdateExpressionOf(targetMember, stateAccessor, null); + } + + public Expression deriveUpdateExpressionOf(ChannelMember targetMember, IResourceStateAccessor stateAccessor, HashMap inputResourceToStateAccessor) + throws ParameterizedIdentifierIsFutureWork, ResolvingMultipleDefinitionIsFutureWork, InvalidMessage, UnificationFailed, ValueUndefined { + if (!getOutputChannelMembers().contains(targetMember)) return null; + HashSet messageConstraints = new HashSet<>(); + + // Calculate message constraints from input state transitions + for (ChannelMember inputMember: getInputChannelMembers()) { + ResourcePath inputResource = inputMember.getResource(); + if (inputResource.getNumberOfParameters() > 0) { + throw new ParameterizedIdentifierIsFutureWork(); + } + Expression curInputStateAccessor = null; + Expression nextInputStateAccessor = null; + if (inputResourceToStateAccessor == null) { + curInputStateAccessor = stateAccessor.getCurrentStateAccessorFor(inputResource, targetMember.getResource()); + nextInputStateAccessor = stateAccessor.getNextStateAccessorFor(inputResource, targetMember.getResource()); + } else { + curInputStateAccessor = inputResourceToStateAccessor.get(inputResource).getCurrentStateAccessorFor(inputResource, targetMember.getResource()); + nextInputStateAccessor = inputResourceToStateAccessor.get(inputResource).getNextStateAccessorFor(inputResource, targetMember.getResource()); + } + Expression messageConstraintByInput = inputMember.getStateTransition().deriveMessageConstraintFor(curInputStateAccessor, nextInputStateAccessor); + messageConstraints.add((Term) messageConstraintByInput); + } + + // Calculate message constraints from reference state transitions + for (ChannelMember referenceMember: getReferenceChannelMembers()) { + ResourcePath referenceResource = referenceMember.getResource(); + if (referenceResource.getNumberOfParameters() > 0) { + throw new ParameterizedIdentifierIsFutureWork(); + } + Expression curInputStateAccessor = null; + if (inputResourceToStateAccessor == null) { + curInputStateAccessor = stateAccessor.getCurrentStateAccessorFor(referenceResource, targetMember.getResource()); + } else { + curInputStateAccessor = inputResourceToStateAccessor.get(referenceResource).getCurrentStateAccessorFor(referenceResource, targetMember.getResource()); + } + Expression messageConstraintByReference = referenceMember.getStateTransition().deriveMessageConstraintFor(curInputStateAccessor); + messageConstraints.add((Term) messageConstraintByReference); + } + + // Unify message constraints + Term unifiedMessage = null; + for (Term messageContraint: messageConstraints) { + if (unifiedMessage == null) { + unifiedMessage = messageContraint; + } else { + unifiedMessage = (Term) unifiedMessage.unify(messageContraint); + if (unifiedMessage == null) { + throw new UnificationFailed(); + } + } + } + + // Calculate the next state of target resource from the unified message and the current resource state + ResourcePath targetResource = targetMember.getResource(); + if (targetResource.getNumberOfParameters() > 0) { + throw new ParameterizedIdentifierIsFutureWork(); + } + Expression curOutputStateAccessor = stateAccessor.getCurrentStateAccessorFor(targetResource, targetResource); + if (unifiedMessage == null) { + // for IOChannel + if (targetMember.getStateTransition().getMessageExpression() instanceof Term) { + unifiedMessage = (Term) targetMember.getStateTransition().getMessageExpression(); + } + } + return targetMember.getStateTransition().deriveNextStateExpressionFor(curOutputStateAccessor, unifiedMessage); + } + + @Override + public String toString() { + String channelSource = "channel " + getChannelName() + " {\n"; + for (ChannelMember inputMember: inputChannelMembers) { + channelSource += "\t in " + inputMember + "\n"; + } + for (ChannelMember refMember: referenceChannelMembers) { + channelSource += "\t ref " + refMember + "\n"; + } + for (ChannelMember outputMember: outputChannelMembers) { + channelSource += "\t out " + outputMember + "\n"; + } + channelSource += "}\n"; + return channelSource; + } + + public interface IResourceStateAccessor { + Expression getCurrentStateAccessorFor(ResourcePath target, ResourcePath from); + Expression getNextStateAccessorFor(ResourcePath target, ResourcePath from); + } +} diff --git a/AlgebraicDataflowArchitectureModel/src/models/dataFlowModel/DataTransferChannelGenerator.java b/AlgebraicDataflowArchitectureModel/src/models/dataFlowModel/DataTransferChannelGenerator.java deleted file mode 100644 index 1426ac7..0000000 --- a/AlgebraicDataflowArchitectureModel/src/models/dataFlowModel/DataTransferChannelGenerator.java +++ /dev/null @@ -1,273 +0,0 @@ -package models.dataFlowModel; - -import java.util.HashMap; -import java.util.HashSet; -import java.util.Set; - -import models.algebra.Expression; -import models.algebra.InvalidMessage; -import models.algebra.Parameter; -import models.algebra.ParameterizedIdentifierIsFutureWork; -import models.algebra.Position; -import models.algebra.Term; -import models.algebra.UnificationFailed; -import models.algebra.ValueUndefined; -import models.algebra.Variable; -import models.dataConstraintModel.*; - -public class DataTransferChannelGenerator extends ChannelGenerator { - protected Set inputChannelMembers = null; - protected Set outputChannelMembers = null; - protected Set referenceChannelMembers = null; - - public DataTransferChannelGenerator(String channelName) { - super(channelName); - inputChannelMembers = new HashSet<>(); - outputChannelMembers = new HashSet<>(); - referenceChannelMembers = new HashSet<>(); - } - - public Set getInputChannelMembers() { - return inputChannelMembers; - } - - public void setInputChannelMembers(Set inputChannelMembers) { - this.inputChannelMembers = inputChannelMembers; - } - - public void addInputChannelMember(ChannelMember inputChannelMember) { - inputChannelMembers.add(inputChannelMember); - } - - public Set getOutputChannelMembers() { - return outputChannelMembers; - } - - public void setOutputChannelMembers(Set outputChannelMembers) { - this.outputChannelMembers = outputChannelMembers; - } - - public void addOutputChannelMember(ChannelMember outputChannelMember) { - outputChannelMembers.add(outputChannelMember); - } - - public Set getReferenceChannelMembers() { - return referenceChannelMembers; - } - - public void setReferenceChannelMembers(Set referenceChannelMembers) { - this.referenceChannelMembers = referenceChannelMembers; - } - - public void addReferenceChannelMember(ChannelMember referenceChannelMember) { - referenceChannelMembers.add(referenceChannelMember); - } - - public void addChannelMemberAsInput(ChannelMember groupDependentResource) { - addChannelMember(groupDependentResource); - addInputChannelMember(groupDependentResource); - } - - public void addChannelMemberAsOutput(ChannelMember groupDependentResource) { - addChannelMember(groupDependentResource); - addOutputChannelMember(groupDependentResource); - } - - public void addChannelMemberAsReference(ChannelMember groupDependentResource) { - addChannelMember(groupDependentResource); - addReferenceChannelMember(groupDependentResource); - } - - public void removeChannelMember(IdentifierTemplate id) { - for (ChannelMember cm: inputChannelMembers) { - if (cm.getIdentifierTemplate() == id) { - inputChannelMembers.remove(cm); - super.removeChannelMember(id); - return; - } - } - for (ChannelMember cm: outputChannelMembers) { - if (cm.getIdentifierTemplate() == id) { - outputChannelMembers.remove(cm); - super.removeChannelMember(id); - return; - } - } - for (ChannelMember cm: referenceChannelMembers) { - if (cm.getIdentifierTemplate() == id) { - referenceChannelMembers.remove(cm); - super.removeChannelMember(id); - return; - } - } - } - - public Set getInputIdentifierTemplates() { - Set inputIdentifierTemplates = new HashSet<>(); - for (ChannelMember member: inputChannelMembers) { - inputIdentifierTemplates.add(member.getIdentifierTemplate()); - } - return inputIdentifierTemplates; - } - - public Set getOutputIdentifierTemplates() { - Set outputIdentifierTemplates = new HashSet<>(); - for (ChannelMember member: outputChannelMembers) { - outputIdentifierTemplates.add(member.getIdentifierTemplate()); - } - return outputIdentifierTemplates; - } - - public Set getReferenceIdentifierTemplates() { - Set referenceIdentifierTemplates = new HashSet<>(); - for (ChannelMember member: referenceChannelMembers) { - referenceIdentifierTemplates.add(member.getIdentifierTemplate()); - } - return referenceIdentifierTemplates; - } - - /** - * Derive the update expression of the state of the target channel member. - * @param targetMember a channel member whose state is to be updated - * @return the derived update expression - * @throws ParameterizedIdentifierIsFutureWork - * @throws ResolvingMultipleDefinitionIsFutureWork - * @throws InvalidMessage - * @throws UnificationFailed - * @throws ValueUndefined - */ - public Expression deriveUpdateExpressionOf(ChannelMember targetMember) throws ParameterizedIdentifierIsFutureWork, ResolvingMultipleDefinitionIsFutureWork, InvalidMessage, UnificationFailed, ValueUndefined { - IResourceStateAccessor defaultStateAccessor = new IResourceStateAccessor() { - HashMap curStateParams = new HashMap<>(); - HashMap nextStateParams = new HashMap<>(); - - @Override - public Expression getCurrentStateAccessorFor(IdentifierTemplate target, IdentifierTemplate from) { - String resource = target.getResourceName(); - Parameter curStateParam = curStateParams.get(resource); - if (curStateParam == null) { - curStateParam = new Parameter("cur" + resource); - curStateParams.put(resource, curStateParam); - } - return curStateParam; - } - - @Override - public Expression getNextStateAccessorFor(IdentifierTemplate target, IdentifierTemplate from) { - String resource = target.getResourceName(); - Parameter nextStateParam = nextStateParams.get(resource); - if (nextStateParam == null) { - nextStateParam = new Parameter("next" + resource); - nextStateParams.put(resource, nextStateParam); - } - return nextStateParam; - } - }; - return deriveUpdateExpressionOf(targetMember, defaultStateAccessor); - } - - /** - * Derive the update expression of the state of the target channel member with a given resource state accessor. - * @param targetMember a channel member whose state is to be updated - * @param stateAccessor a resource state accessor - * @return the derived update expression - * @throws ParameterizedIdentifierIsFutureWork - * @throws ResolvingMultipleDefinitionIsFutureWork - * @throws InvalidMessage - * @throws UnificationFailed - * @throws ValueUndefined - */ - public Expression deriveUpdateExpressionOf(ChannelMember targetMember, IResourceStateAccessor stateAccessor) - throws ParameterizedIdentifierIsFutureWork, ResolvingMultipleDefinitionIsFutureWork, InvalidMessage, UnificationFailed, ValueUndefined { - return deriveUpdateExpressionOf(targetMember, stateAccessor, null); - } - - public Expression deriveUpdateExpressionOf(ChannelMember targetMember, IResourceStateAccessor stateAccessor, HashMap inputIdentifierToStateAccessor) - throws ParameterizedIdentifierIsFutureWork, ResolvingMultipleDefinitionIsFutureWork, InvalidMessage, UnificationFailed, ValueUndefined { - if (!getOutputChannelMembers().contains(targetMember)) return null; - HashSet messageConstraints = new HashSet<>(); - - // Calculate message constraints from input state transitions - for (ChannelMember inputMember: getInputChannelMembers()) { - IdentifierTemplate inputIdentifier = inputMember.getIdentifierTemplate(); - if (inputIdentifier.getNumberOfParameters() > 0) { - throw new ParameterizedIdentifierIsFutureWork(); - } - Expression curInputStateAccessor = null; - Expression nextInputStateAccessor = null; - if (inputIdentifierToStateAccessor == null) { - curInputStateAccessor = stateAccessor.getCurrentStateAccessorFor(inputIdentifier, targetMember.getIdentifierTemplate()); - nextInputStateAccessor = stateAccessor.getNextStateAccessorFor(inputIdentifier, targetMember.getIdentifierTemplate()); - } else { - curInputStateAccessor = inputIdentifierToStateAccessor.get(inputIdentifier).getCurrentStateAccessorFor(inputIdentifier, targetMember.getIdentifierTemplate()); - nextInputStateAccessor = inputIdentifierToStateAccessor.get(inputIdentifier).getNextStateAccessorFor(inputIdentifier, targetMember.getIdentifierTemplate()); - } - Expression messageConstraintByInput = inputMember.getStateTransition().deriveMessageConstraintFor(curInputStateAccessor, nextInputStateAccessor); - messageConstraints.add((Term) messageConstraintByInput); - } - - // Calculate message constraints from reference state transitions - for (ChannelMember referenceMember: getReferenceChannelMembers()) { - IdentifierTemplate referenceIdentifier = referenceMember.getIdentifierTemplate(); - if (referenceIdentifier.getNumberOfParameters() > 0) { - throw new ParameterizedIdentifierIsFutureWork(); - } - Expression curInputStateAccessor = null; - if (inputIdentifierToStateAccessor == null) { - curInputStateAccessor = stateAccessor.getCurrentStateAccessorFor(referenceIdentifier, targetMember.getIdentifierTemplate()); - } else { - curInputStateAccessor = inputIdentifierToStateAccessor.get(referenceIdentifier).getCurrentStateAccessorFor(referenceIdentifier, targetMember.getIdentifierTemplate()); - } - Expression messageConstraintByReference = referenceMember.getStateTransition().deriveMessageConstraintFor(curInputStateAccessor); - messageConstraints.add((Term) messageConstraintByReference); - } - - // Unify message constraints - Term unifiedMessage = null; - for (Term messageContraint: messageConstraints) { - if (unifiedMessage == null) { - unifiedMessage = messageContraint; - } else { - unifiedMessage = (Term) unifiedMessage.unify(messageContraint); - if (unifiedMessage == null) { - throw new UnificationFailed(); - } - } - } - - // Calculate the next state of target resource from the unified message and the current resource state - IdentifierTemplate targetIdentifier = targetMember.getIdentifierTemplate(); - if (targetIdentifier.getNumberOfParameters() > 0) { - throw new ParameterizedIdentifierIsFutureWork(); - } - Expression curOutputStateAccessor = stateAccessor.getCurrentStateAccessorFor(targetIdentifier, targetIdentifier); - if (unifiedMessage == null) { - // for IOChannel - if (targetMember.getStateTransition().getMessageExpression() instanceof Term) { - unifiedMessage = (Term) targetMember.getStateTransition().getMessageExpression(); - } - } - return targetMember.getStateTransition().deriveNextStateExpressionFor(curOutputStateAccessor, unifiedMessage); - } - - @Override - public String toString() { - String channelSource = "channel " + getChannelName() + " {\n"; - for (ChannelMember inputMember: inputChannelMembers) { - channelSource += "\t in " + inputMember + "\n"; - } - for (ChannelMember refMember: referenceChannelMembers) { - channelSource += "\t ref " + refMember + "\n"; - } - for (ChannelMember outputMember: outputChannelMembers) { - channelSource += "\t out " + outputMember + "\n"; - } - channelSource += "}\n"; - return channelSource; - } - - public interface IResourceStateAccessor { - Expression getCurrentStateAccessorFor(IdentifierTemplate target, IdentifierTemplate from); - Expression getNextStateAccessorFor(IdentifierTemplate target, IdentifierTemplate from); - } -} diff --git a/AlgebraicDataflowArchitectureModel/src/models/dataFlowModel/DataTransferModel.java b/AlgebraicDataflowArchitectureModel/src/models/dataFlowModel/DataTransferModel.java index 364a646..1e67efb 100644 --- a/AlgebraicDataflowArchitectureModel/src/models/dataFlowModel/DataTransferModel.java +++ b/AlgebraicDataflowArchitectureModel/src/models/dataFlowModel/DataTransferModel.java @@ -2,27 +2,27 @@ import java.util.Set; -import models.dataConstraintModel.ChannelGenerator; +import models.dataConstraintModel.Channel; import models.dataConstraintModel.DataConstraintModel; -import models.dataConstraintModel.IdentifierTemplate; +import models.dataConstraintModel.ResourcePath; public class DataTransferModel extends DataConstraintModel { public DataFlowGraph getDataFlowGraph() { DataFlowGraph dataFlowGraph = new DataFlowGraph(); - for (ChannelGenerator channelGen: getChannelGenerators()) { - DataTransferChannelGenerator dfChannelGen = (DataTransferChannelGenerator)channelGen; - Set inputResources = dfChannelGen.getInputIdentifierTemplates(); - Set outputResources = dfChannelGen.getOutputIdentifierTemplates(); - for (IdentifierTemplate in: inputResources) { - for (IdentifierTemplate out: outputResources) { + for (Channel channel: getChannels()) { + DataTransferChannel dfChannelGen = (DataTransferChannel)channel; + Set inputResources = dfChannelGen.getInputResources(); + Set outputResources = dfChannelGen.getOutputResources(); + for (ResourcePath in: inputResources) { + for (ResourcePath out: outputResources) { dataFlowGraph.addEdge(in ,out, dfChannelGen); } } } - for (ChannelGenerator channelGen: getIOChannelGenerators()) { - DataTransferChannelGenerator dfChannelGen = (DataTransferChannelGenerator)channelGen; - Set outputResources = dfChannelGen.getOutputIdentifierTemplates(); - for (IdentifierTemplate out: outputResources) { + for (Channel channel: getIOChannels()) { + DataTransferChannel dfChannel = (DataTransferChannel)channel; + Set outputResources = dfChannel.getOutputResources(); + for (ResourcePath out: outputResources) { dataFlowGraph.addNode(out); } } diff --git a/AlgebraicDataflowArchitectureModel/src/models/dataFlowModel/IFlowGraph.java b/AlgebraicDataflowArchitectureModel/src/models/dataFlowModel/IFlowGraph.java new file mode 100644 index 0000000..d159bd7 --- /dev/null +++ b/AlgebraicDataflowArchitectureModel/src/models/dataFlowModel/IFlowGraph.java @@ -0,0 +1,10 @@ +package models.dataFlowModel; + +import java.util.Map; +import java.util.Set; + +import models.Node; + +public interface IFlowGraph { + abstract public Map> getAllNodes(); +} diff --git a/AlgebraicDataflowArchitectureModel/src/models/dataFlowModel/ModelExtension.java b/AlgebraicDataflowArchitectureModel/src/models/dataFlowModel/ModelExtension.java index d8aa4af..54a5c98 100644 --- a/AlgebraicDataflowArchitectureModel/src/models/dataFlowModel/ModelExtension.java +++ b/AlgebraicDataflowArchitectureModel/src/models/dataFlowModel/ModelExtension.java @@ -10,6 +10,8 @@ private static Symbol.Memento mergeMem; private static Symbol.Memento extractFaceDownMem; private static Symbol.Memento sortByKeyMem; + private static Symbol.Memento selectGEMem; + private static Symbol.Memento selectLEMem; public static void extendModel(DataTransferModel model) { Symbol floor = model.getSymbol("floor"); @@ -57,7 +59,7 @@ merge.setGenerator(new Symbol.IImplGenerator() { @Override public String generate(Type type, String[] childrenImpl, String[] childrenSideEffects, String[] sideEffect) { - String implType = "Arrayist<>"; + String implType = "ArrayList<>"; String interfaceType = "List"; String compType = "Integer"; if (type != null) { @@ -119,7 +121,7 @@ Symbol sortByKey = model.getSymbol("sortByKey"); sortByKeyMem = null; - if(sortByKey != null) { + if (sortByKey != null) { sortByKeyMem = sortByKey.createMemento(); sortByKey.setArity(1); sortByKey.setGenerator(new Symbol.IImplGenerator() { @@ -148,6 +150,64 @@ sortByKey.setSignature(new Type[] {DataConstraintModel.typeList, DataConstraintModel.typeList}); sortByKey.setImplOperatorType(Symbol.Type.GENERATIVE); } + + Symbol selectGE = model.getSymbol("selectGE"); + selectGEMem = null; + if (selectGE != null) { + final int[] count = new int[] {0}; + selectGE.setArity(3); + selectGEMem = selectGE.createMemento(); + selectGE.setGenerator(new Symbol.IImplGenerator() { + @Override + public String generate(Type type, String[] childrenImpl, String[] childrenSideEffects, String[] sideEffect) { + String implType = "ArrayList<>"; + String interfaceType = "List>"; + count[0]++; + String impl = ""; + impl += "" + interfaceType + " temp_l" + count[0] + " = new " + implType + "();\n"; + impl += "{\n"; + impl += "\tfor (Map item: " + childrenImpl[0] + ") {\n"; + impl += "\t\tif ((Integer) item.get(" + childrenImpl[1] + ") >= " + childrenImpl[2] + ") {\n"; + impl += "\t\t\ttemp_l" + count[0] + ".add(item);\n"; + impl += "\t\t}\n"; + impl += "\t}\n"; + impl += "}\n"; + sideEffect[0] = sideEffect[0] + impl; + return "temp_l" + count[0]; + } + }); + selectGE.setSignature(new Type[] {DataConstraintModel.typeList, DataConstraintModel.typeList, DataConstraintModel.typeString, DataConstraintModel.typeInt}); + selectGE.setImplOperatorType(Symbol.Type.GENERATIVE); + } + + Symbol selectLE = model.getSymbol("selectLE"); + selectLEMem = null; + if (selectLE != null) { + final int[] count = new int[] {0}; + selectLE.setArity(3); + selectLEMem = selectLE.createMemento(); + selectLE.setGenerator(new Symbol.IImplGenerator() { + @Override + public String generate(Type type, String[] childrenImpl, String[] childrenSideEffects, String[] sideEffect) { + String implType = "ArrayList<>"; + String interfaceType = "List>"; + count[0]++; + String impl = ""; + impl += "" + interfaceType + " temp_l" + count[0] + " = new " + implType + "();\n"; + impl += "{\n"; + impl += "\tfor (Map item: " + childrenImpl[0] + ") {\n"; + impl += "\t\tif ((Integer) item.get(" + childrenImpl[1] + ") <= " + childrenImpl[2] + ") {\n"; + impl += "\t\t\ttemp_l" + count[0] + ".add(item);\n"; + impl += "\t\t}\n"; + impl += "\t}\n"; + impl += "}\n"; + sideEffect[0] = sideEffect[0] + impl; + return "temp_l" + count[0]; + } + }); + selectLE.setSignature(new Type[] {DataConstraintModel.typeList, DataConstraintModel.typeList, DataConstraintModel.typeString, DataConstraintModel.typeInt}); + selectLE.setImplOperatorType(Symbol.Type.GENERATIVE); + } } public static void recoverModel(DataTransferModel model) { @@ -161,5 +221,9 @@ if (extractFaceDown != null) extractFaceDown.setMemento(extractFaceDownMem); Symbol sortByKey = model.getSymbol("sortByKey"); if (sortByKey != null) sortByKey.setMemento(sortByKeyMem); + Symbol selectGE = model.getSymbol("selectGE"); + if (selectGE != null) selectGE.setMemento(selectGEMem); + Symbol selectLE = model.getSymbol("selectLE"); + if (selectLE != null) selectLE.setMemento(selectLEMem); } } diff --git a/AlgebraicDataflowArchitectureModel/src/models/dataFlowModel/ResourceNode.java b/AlgebraicDataflowArchitectureModel/src/models/dataFlowModel/ResourceNode.java index 698eac3..ef286af 100644 --- a/AlgebraicDataflowArchitectureModel/src/models/dataFlowModel/ResourceNode.java +++ b/AlgebraicDataflowArchitectureModel/src/models/dataFlowModel/ResourceNode.java @@ -1,30 +1,30 @@ package models.dataFlowModel; import models.Node; -import models.dataConstraintModel.IdentifierTemplate; +import models.dataConstraintModel.ResourcePath; public class ResourceNode extends Node { - protected IdentifierTemplate identifierTemplate = null; + protected ResourcePath resourcePath = null; - public ResourceNode(IdentifierTemplate identifierTemplate) { - this.identifierTemplate = identifierTemplate; + public ResourceNode(ResourcePath resourcePath) { + this.resourcePath = resourcePath; } - public IdentifierTemplate getIdentifierTemplate() { - return identifierTemplate; + public ResourcePath getResource() { + return resourcePath; } public boolean equals(Object another) { if (this == another) return true; if (!(another instanceof ResourceNode)) return false; - return identifierTemplate.equals(((ResourceNode)another).identifierTemplate); + return resourcePath.equals(((ResourceNode)another).resourcePath); } public int hashCode() { - return identifierTemplate.hashCode(); + return resourcePath.hashCode(); } public String toString() { - return identifierTemplate.getResourceName(); + return resourcePath.getResourceName(); } } diff --git a/AlgebraicDataflowArchitectureModel/src/models/dataFlowModel/ResourceNodeAttribute.java b/AlgebraicDataflowArchitectureModel/src/models/dataFlowModel/ResourceNodeAttribute.java new file mode 100644 index 0000000..a1f8615 --- /dev/null +++ b/AlgebraicDataflowArchitectureModel/src/models/dataFlowModel/ResourceNodeAttribute.java @@ -0,0 +1,63 @@ +package models.dataFlowModel; + +import models.NodeAttribute; + +/************************************************************* + * + * @author k-fujii + * + */ +public class ResourceNodeAttribute extends NodeAttribute { + private ResourceNode resourceNode = null; + + /************************************************************* + * [ *constructor ] + /************************************************************* + * + */ + public ResourceNodeAttribute(ResourceNode resNode) { + this.resourceNode = resNode; + this.resourceNode.setAttribute(this); + } + + /************************************************************* + * [ *public ] + /************************************************************* + * [ getter ] + /************************************************************* + * + * @return + */ + public ResourceNode getResourceNode() { + return resourceNode; + } + + /************************************************************* + * + */ + public String getResourceName() { + return resourceNode.getResource().getResourceName(); + } + + /************************************************************* + * + * @return + */ + public String getDefaultStyle() { + String style =""; + style += "shape=ellipse;"; + style += "perimeter=ellipsePerimeter"; + + return style; + } + + + /************************************************************* + * + * @return + */ + @Override + public String toString() { + return resourceNode.getResource().getResourceName(); + } +} diff --git a/AlgebraicDataflowArchitectureModel/src/models/visualModel/FormulaChannel.java b/AlgebraicDataflowArchitectureModel/src/models/visualModel/FormulaChannel.java new file mode 100644 index 0000000..581d31e --- /dev/null +++ b/AlgebraicDataflowArchitectureModel/src/models/visualModel/FormulaChannel.java @@ -0,0 +1,161 @@ +package models.visualModel; + +import java.util.ArrayList; +import java.util.Collection; +import java.util.HashMap; +import java.util.Map; + +import models.algebra.Expression; +import models.algebra.Symbol; +import models.algebra.Term; +import models.algebra.Variable; +import models.dataConstraintModel.ChannelMember; +import models.dataConstraintModel.DataConstraintModel; +import models.dataConstraintModel.ResourcePath; +import models.dataConstraintModel.StateTransition; +import models.dataFlowModel.DataTransferChannel; + +public class FormulaChannel extends DataTransferChannel { + private Symbol defaultOperator = null; + private String formula = null; + private Expression formulaRhs = null; + + public FormulaChannel(String channelName, Symbol defaultOperator) { + super(channelName); + this.defaultOperator = defaultOperator; + } + + public void addChannelMemberAsInput(ChannelMember channelMember) { +// StateTransition st = new StateTransition(); +// st.setCurStateExpression(new Variable(channelMember.getIdentifierTemplate().getResourceName() + "1")); +// st.setNextStateExpression(new Variable(channelMember.getIdentifierTemplate().getResourceName() + "2")); +// channelMember.setStateTransition(st); + super.addChannelMemberAsInput(channelMember); + if (formula != null && getInputChannelMembers().size() > 1) { + formula += " " + defaultOperator + " " + channelMember.getResource().getResourceName(); + if (formulaRhs != null) { + if (formulaRhs instanceof Variable) { + Term newTerm = new Term(defaultOperator); + newTerm.addChild(formulaRhs); + newTerm.addChild(new Variable(channelMember.getResource().getResourceName()), true); + formulaRhs = newTerm; + } else if (formulaRhs instanceof Term) { + Term newTerm = new Term(defaultOperator); + newTerm.addChild(formulaRhs); + newTerm.addChild(new Variable(channelMember.getResource().getResourceName())); + formulaRhs = newTerm; + } + } + } else { + if (formula == null) formula = ""; + formula += channelMember.getResource().getResourceName(); + formulaRhs = new Variable(channelMember.getResource().getResourceName()); + } + if (formulaRhs != null) { + setFormulaTerm(formulaRhs); + } + } + + public void addChannelMemberAsOutput(ChannelMember channelMember) { +// StateTransition st = new StateTransition(); +// st.setCurStateExpression(new Variable(channelMember.getIdentifierTemplate().getResourceName() + "1")); +// channelMember.setStateTransition(st); + super.addChannelMemberAsOutput(channelMember); + if (getOutputChannelMembers().size() == 1) { + if (formula == null) formula = ""; + if (!formula.contains("==")) { + formula = channelMember.getResource().getResourceName() + " == " + formula; + } + } + if (formulaRhs != null) { + setFormulaTerm(formulaRhs); + } + } + + public Symbol getDefaultOperator() { + return defaultOperator; + } + + public void setDefaultOperator(Symbol defaultOperator) { + this.defaultOperator = defaultOperator; + } + + public void setFormulaTerm(Expression rhs) { + formulaRhs = rhs; + Collection variables; + if (rhs instanceof Variable) { + variables = new ArrayList<>(); + variables.add((Variable) rhs); + } else if (rhs instanceof Term) { + variables = ((Term) rhs).getVariables().values(); + } else { + return; + } + Map curStates = new HashMap<>(); + Map nextStates = new HashMap<>(); + Map resToNextVar = new HashMap<>(); + for (ChannelMember cm: this.getInputChannelMembers()) { + ResourcePath id = cm.getResource(); + String resName = id.getResourceName(); + Variable curVar = new Variable(resName + "1"); + Variable nextVar = new Variable(resName + "2"); + curStates.put(id, curVar); + nextStates.put(id, nextVar); + for (Variable var: variables) { + if (var.getName().equals(resName)) { + resToNextVar.put(var, nextVar); + break; + } + } + } + Symbol update = new Symbol("update"); + update.setArity(resToNextVar.keySet().size()); + for (ChannelMember cm: getInputChannelMembers()) { + ResourcePath id = cm.getResource(); + StateTransition st = new StateTransition(); + st.setCurStateExpression(curStates.get(id)); + st.setNextStateExpression(nextStates.get(id)); + Term message = new Term(update); + for (Variable var: resToNextVar.values()) { + message.addChild(var); + } + st.setMessageExpression(message); + cm.setStateTransition(st); + } + + if (rhs instanceof Variable) { + rhs = resToNextVar.get((Variable) rhs); + } else if (rhs instanceof Term) { + formulaRhs = rhs; + for (Variable var: resToNextVar.keySet()) { + rhs = ((Term) rhs).substitute(var, resToNextVar.get(var)); + } + } + for (ChannelMember cm: getOutputChannelMembers()) { + ResourcePath id = cm.getResource(); + StateTransition st = new StateTransition(); + String resName = id.getResourceName(); + Variable curVar = new Variable(resName + "1"); + st.setCurStateExpression(curVar); + st.setNextStateExpression(rhs); + Term message = new Term(update); + for (Variable var: resToNextVar.values()) { + message.addChild(var); + } + st.setMessageExpression(message); + cm.setStateTransition(st); + } + } + + public Expression getFormulaTerm() { + return formulaRhs; + } + + public void setFormula(String formula) { + this.formula = formula; + } + + public String getFormula() { + return formula; + } +} diff --git a/AlgebraicDataflowArchitectureModel/src/models/visualModel/FormulaChannelGenerator.java b/AlgebraicDataflowArchitectureModel/src/models/visualModel/FormulaChannelGenerator.java deleted file mode 100644 index 4bbfe7e..0000000 --- a/AlgebraicDataflowArchitectureModel/src/models/visualModel/FormulaChannelGenerator.java +++ /dev/null @@ -1,161 +0,0 @@ -package models.visualModel; - -import java.util.ArrayList; -import java.util.Collection; -import java.util.HashMap; -import java.util.Map; - -import models.algebra.Expression; -import models.algebra.Symbol; -import models.algebra.Term; -import models.algebra.Variable; -import models.dataConstraintModel.ChannelMember; -import models.dataConstraintModel.DataConstraintModel; -import models.dataConstraintModel.IdentifierTemplate; -import models.dataConstraintModel.StateTransition; -import models.dataFlowModel.DataTransferChannelGenerator; - -public class FormulaChannelGenerator extends DataTransferChannelGenerator { - private Symbol defaultOperator = null; - private String formula = null; - private Expression formulaRhs = null; - - public FormulaChannelGenerator(String channelName, Symbol defaultOperator) { - super(channelName); - this.defaultOperator = defaultOperator; - } - - public void addChannelMemberAsInput(ChannelMember channelMember) { -// StateTransition st = new StateTransition(); -// st.setCurStateExpression(new Variable(channelMember.getIdentifierTemplate().getResourceName() + "1")); -// st.setNextStateExpression(new Variable(channelMember.getIdentifierTemplate().getResourceName() + "2")); -// channelMember.setStateTransition(st); - super.addChannelMemberAsInput(channelMember); - if (formula != null && getInputChannelMembers().size() > 1) { - formula += " " + defaultOperator + " " + channelMember.getIdentifierTemplate().getResourceName(); - if (formulaRhs != null) { - if (formulaRhs instanceof Variable) { - Term newTerm = new Term(defaultOperator); - newTerm.addChild(formulaRhs); - newTerm.addChild(new Variable(channelMember.getIdentifierTemplate().getResourceName()), true); - formulaRhs = newTerm; - } else if (formulaRhs instanceof Term) { - Term newTerm = new Term(defaultOperator); - newTerm.addChild(formulaRhs); - newTerm.addChild(new Variable(channelMember.getIdentifierTemplate().getResourceName())); - formulaRhs = newTerm; - } - } - } else { - if (formula == null) formula = ""; - formula += channelMember.getIdentifierTemplate().getResourceName(); - formulaRhs = new Variable(channelMember.getIdentifierTemplate().getResourceName()); - } - if (formulaRhs != null) { - setFormulaTerm(formulaRhs); - } - } - - public void addChannelMemberAsOutput(ChannelMember channelMember) { -// StateTransition st = new StateTransition(); -// st.setCurStateExpression(new Variable(channelMember.getIdentifierTemplate().getResourceName() + "1")); -// channelMember.setStateTransition(st); - super.addChannelMemberAsOutput(channelMember); - if (getOutputChannelMembers().size() == 1) { - if (formula == null) formula = ""; - if (!formula.contains("==")) { - formula = channelMember.getIdentifierTemplate().getResourceName() + " == " + formula; - } - } - if (formulaRhs != null) { - setFormulaTerm(formulaRhs); - } - } - - public Symbol getDefaultOperator() { - return defaultOperator; - } - - public void setDefaultOperator(Symbol defaultOperator) { - this.defaultOperator = defaultOperator; - } - - public void setFormulaTerm(Expression rhs) { - formulaRhs = rhs; - Collection variables; - if (rhs instanceof Variable) { - variables = new ArrayList<>(); - variables.add((Variable) rhs); - } else if (rhs instanceof Term) { - variables = ((Term) rhs).getVariables().values(); - } else { - return; - } - Map curStates = new HashMap<>(); - Map nextStates = new HashMap<>(); - Map resToNextVar = new HashMap<>(); - for (ChannelMember cm: this.getInputChannelMembers()) { - IdentifierTemplate id = cm.getIdentifierTemplate(); - String resName = id.getResourceName(); - Variable curVar = new Variable(resName + "1"); - Variable nextVar = new Variable(resName + "2"); - curStates.put(id, curVar); - nextStates.put(id, nextVar); - for (Variable var: variables) { - if (var.getName().equals(resName)) { - resToNextVar.put(var, nextVar); - break; - } - } - } - Symbol update = new Symbol("update"); - update.setArity(resToNextVar.keySet().size()); - for (ChannelMember cm: getInputChannelMembers()) { - IdentifierTemplate id = cm.getIdentifierTemplate(); - StateTransition st = new StateTransition(); - st.setCurStateExpression(curStates.get(id)); - st.setNextStateExpression(nextStates.get(id)); - Term message = new Term(update); - for (Variable var: resToNextVar.values()) { - message.addChild(var); - } - st.setMessageExpression(message); - cm.setStateTransition(st); - } - - if (rhs instanceof Variable) { - rhs = resToNextVar.get((Variable) rhs); - } else if (rhs instanceof Term) { - formulaRhs = rhs; - for (Variable var: resToNextVar.keySet()) { - rhs = ((Term) rhs).substitute(var, resToNextVar.get(var)); - } - } - for (ChannelMember cm: getOutputChannelMembers()) { - IdentifierTemplate id = cm.getIdentifierTemplate(); - StateTransition st = new StateTransition(); - String resName = id.getResourceName(); - Variable curVar = new Variable(resName + "1"); - st.setCurStateExpression(curVar); - st.setNextStateExpression(rhs); - Term message = new Term(update); - for (Variable var: resToNextVar.values()) { - message.addChild(var); - } - st.setMessageExpression(message); - cm.setStateTransition(st); - } - } - - public Expression getFormulaTerm() { - return formulaRhs; - } - - public void setFormula(String formula) { - this.formula = formula; - } - - public String getFormula() { - return formula; - } -} diff --git a/AlgebraicDataflowArchitectureModel/src/parser/Parser.java b/AlgebraicDataflowArchitectureModel/src/parser/Parser.java index ed9aaf9..080f7da 100644 --- a/AlgebraicDataflowArchitectureModel/src/parser/Parser.java +++ b/AlgebraicDataflowArchitectureModel/src/parser/Parser.java @@ -1,6 +1,5 @@ package parser; -import java.awt.image.DataBufferDouble; import java.io.BufferedReader; import java.io.IOException; import java.util.ArrayList; @@ -14,19 +13,24 @@ import models.algebra.Type; import models.algebra.Variable; import models.dataConstraintModel.ChannelMember; -import models.dataConstraintModel.IdentifierTemplate; +import models.dataConstraintModel.DataConstraintModel; +import models.dataConstraintModel.JsonAccessor; +import models.dataConstraintModel.ResourcePath; import models.dataConstraintModel.StateTransition; import models.dataFlowModel.DataTransferModel; -import models.dataFlowModel.DataTransferChannelGenerator; +import models.dataFlowModel.DataTransferChannel; +import parser.Parser.TokenStream; import parser.exceptions.ExpectedAssignment; import parser.exceptions.ExpectedChannel; import parser.exceptions.ExpectedChannelName; +import parser.exceptions.ExpectedColon; import parser.exceptions.ExpectedEquals; import parser.exceptions.ExpectedInOrOutOrRefKeyword; import parser.exceptions.ExpectedLeftCurlyBracket; import parser.exceptions.ExpectedRHSExpression; import parser.exceptions.ExpectedRightBracket; import parser.exceptions.ExpectedStateTransition; +import parser.exceptions.WrongJsonExpression; import parser.exceptions.WrongLHSExpression; import parser.exceptions.WrongRHSExpression; @@ -43,6 +47,10 @@ public static final String RIGHT_BRACKET = ")"; public static final String LEFT_BRACKET_REGX = "\\("; public static final String RIGHT_BRACKET_REGX = "\\)"; + public static final String LEFT_SQUARE_BRACKET = "["; + public static final String RIGHT_SQUARE_BRACKET = "]"; + public static final String LEFT_SQUARE_BRACKET_REGX = "\\["; + public static final String RIGHT_SQUARE_BRACKET_REGX = "\\]"; public static final String ADD = "+"; public static final String MUL = "*"; public static final String SUB = "-"; @@ -59,7 +67,8 @@ public static final String ASSIGNMENT = "="; public static final String COMMA = ","; public static final String COLON = ":"; - + public static final String DOT = "."; + public static final String DOT_REGX = "\\."; public Parser(final TokenStream stream) { this.stream = stream; @@ -79,30 +88,32 @@ } public DataTransferModel doParse() - throws ExpectedRightBracket, ExpectedChannel, ExpectedChannelName, ExpectedLeftCurlyBracket, ExpectedInOrOutOrRefKeyword, ExpectedStateTransition, ExpectedEquals, ExpectedRHSExpression, WrongLHSExpression, WrongRHSExpression, ExpectedAssignment { + throws ExpectedRightBracket, ExpectedChannel, ExpectedChannelName, ExpectedLeftCurlyBracket, ExpectedInOrOutOrRefKeyword, + ExpectedStateTransition, ExpectedEquals, ExpectedRHSExpression, WrongLHSExpression, WrongRHSExpression, ExpectedAssignment, WrongJsonExpression, ExpectedColon { return parseDataFlowModel(); } public DataTransferModel parseDataFlowModel() - throws ExpectedRightBracket, ExpectedChannel, ExpectedChannelName, ExpectedLeftCurlyBracket, ExpectedInOrOutOrRefKeyword, ExpectedStateTransition, ExpectedEquals, ExpectedRHSExpression, WrongLHSExpression, WrongRHSExpression, ExpectedAssignment { + throws ExpectedRightBracket, ExpectedChannel, ExpectedChannelName, ExpectedLeftCurlyBracket, ExpectedInOrOutOrRefKeyword, + ExpectedStateTransition, ExpectedEquals, ExpectedRHSExpression, WrongLHSExpression, WrongRHSExpression, ExpectedAssignment, WrongJsonExpression, ExpectedColon { DataTransferModel model = new DataTransferModel(); - DataTransferChannelGenerator channel; + DataTransferChannel channel; while ((channel = parseChannel(model)) != null) { if (channel.getInputChannelMembers().size() == 0) { - model.addIOChannelGenerator(channel); + model.addIOChannel(channel); } else { - model.addChannelGenerator(channel); + model.addChannel(channel); } } return model; } - public DataTransferChannelGenerator parseChannel(DataTransferModel model) + public DataTransferChannel parseChannel(DataTransferModel model) throws ExpectedLeftCurlyBracket, ExpectedRightBracket, ExpectedAssignment, ExpectedRHSExpression, WrongLHSExpression, WrongRHSExpression, ExpectedChannel, ExpectedChannelName, ExpectedInOrOutOrRefKeyword, - ExpectedStateTransition, ExpectedEquals + ExpectedStateTransition, ExpectedEquals, WrongJsonExpression, ExpectedColon { if (!stream.hasNext()) return null; if (stream.checkNext().equals(RIGHT_CURLY_BRACKET)) return null; @@ -119,7 +130,7 @@ if (channelName.equals(LEFT_CURLY_BRACKET)) throw new ExpectedChannelName(stream.getLine()); int fromLine = stream.getLine(); - DataTransferChannelGenerator channel = new DataTransferChannelGenerator(channelName); + DataTransferChannel channel = new DataTransferChannel(channelName); String leftBracket = stream.next(); if (!leftBracket.equals(LEFT_CURLY_BRACKET)) throw new ExpectedLeftCurlyBracket(stream.getLine()); @@ -152,17 +163,17 @@ public void parseInit(DataTransferModel model) throws - ExpectedLeftCurlyBracket, ExpectedAssignment, ExpectedRHSExpression, WrongRHSExpression, ExpectedRightBracket + ExpectedLeftCurlyBracket, ExpectedAssignment, ExpectedRHSExpression, WrongRHSExpression, ExpectedRightBracket, WrongJsonExpression, ExpectedColon { String leftBracket = stream.next(); if (!leftBracket.equals(LEFT_CURLY_BRACKET)) throw new ExpectedLeftCurlyBracket(stream.getLine()); String resourceName = null; while (stream.hasNext() && !(resourceName = stream.next()).equals(RIGHT_CURLY_BRACKET)) { int fromLine = stream.getLine(); - IdentifierTemplate identifier = model.getIdentifierTemplate(resourceName); - if (identifier == null) { - identifier = new IdentifierTemplate(resourceName, 0); - model.addIdentifierTemplate(identifier); + ResourcePath resource = model.getResourcePath(resourceName); + if (resource == null) { + resource = new ResourcePath(resourceName, 0); + model.addResourcePath(resource); } if (!stream.hasNext()) throw new ExpectedAssignment(stream.getLine()); @@ -178,15 +189,15 @@ rightTerm = parseTerm(stream, model); if (rightTerm == null) throw new WrongRHSExpression(stream.getLine()); - identifier.setInitialValue(rightTerm); - identifier.setInitText(stream.getSourceText(fromLine, toLine)); + resource.setInitialValue(rightTerm); + resource.setInitText(stream.getSourceText(fromLine, toLine)); } } public ChannelMember parseChannelMember(DataTransferModel model, final String inOrOutOrRef) throws ExpectedRightBracket, ExpectedStateTransition, ExpectedEquals, - ExpectedRHSExpression, WrongLHSExpression, WrongRHSExpression + ExpectedRHSExpression, WrongLHSExpression, WrongRHSExpression, WrongJsonExpression, ExpectedColon { if (!stream.hasNext()) throw new ExpectedStateTransition(stream.getLine()); Expression leftTerm = parseTerm(stream, model); @@ -204,22 +215,22 @@ } String resourceName = ((Term) leftTerm).getSymbol().getName(); - IdentifierTemplate identifier = model.getIdentifierTemplate(resourceName); - if (identifier == null) { - identifier = new IdentifierTemplate(resourceName, 0); - model.addIdentifierTemplate(identifier); + ResourcePath resource = model.getResourcePath(resourceName); + if (resource == null) { + resource = new ResourcePath(resourceName, 0); + model.addResourcePath(resource); } - ChannelMember channelMember = new ChannelMember(identifier); + ChannelMember channelMember = new ChannelMember(resource); StateTransition stateTransition = new StateTransition(); stateTransition.setCurStateExpression(((Term) leftTerm).getChild(0)); stateTransition.setMessageExpression(((Term) leftTerm).getChild(1)); if (!inOrOutOrRef.equals(REF)) stateTransition.setNextStateExpression(rightTerm); channelMember.setStateTransition(stateTransition); // for type definition - if (identifier.getResourceStateType() == null && ((Term) leftTerm).getChild(0) instanceof Variable) { + if (resource.getResourceStateType() == null && ((Term) leftTerm).getChild(0) instanceof Variable) { Variable stateVar = (Variable) ((Term) leftTerm).getChild(0); if (stateVar.getType() != null) { - identifier.setResourceStateType(stateVar.getType()); + resource.setResourceStateType(stateVar.getType()); } } if (((Term) leftTerm).getChild(1) instanceof Term) { @@ -240,7 +251,7 @@ } public Expression parseTerm(TokenStream stream, DataTransferModel model) - throws ExpectedRightBracket + throws ExpectedRightBracket, WrongJsonExpression, ExpectedColon { ArrayList expressions = new ArrayList<>(); ArrayList operators = new ArrayList<>(); @@ -252,6 +263,16 @@ String rightBracket = stream.next(); if (!rightBracket.equals(RIGHT_BRACKET)) throw new ExpectedRightBracket(stream.getLine()); expressions.add(exp); + } else if (leftBracketOrMinus.equals(LEFT_CURLY_BRACKET)) { + Expression exp = parseJsonTerm(stream, model); + String rightBracket = stream.next(); + if (!rightBracket.equals(RIGHT_CURLY_BRACKET)) throw new ExpectedRightBracket(stream.getLine()); + expressions.add(exp); + } else if (leftBracketOrMinus.equals(LEFT_SQUARE_BRACKET)) { + Expression exp = parseListTerm(stream, model); + String rightBracket = stream.next(); + if (!rightBracket.equals(RIGHT_SQUARE_BRACKET)) throw new ExpectedRightBracket(stream.getLine()); + expressions.add(exp); } else { Symbol minus = null; String symbolName = null; @@ -283,31 +304,29 @@ symbol.setArity(arity); exp = term; } else { - // constant or variable - try { - Symbol symbol = model.getSymbol(symbolName); - if (symbol != null && symbol.getArity() == 0) { - exp = new Constant(symbol); - } else { + // constant or variable or json access + Symbol symbol = model.getSymbol(symbolName); + if (symbol != null && symbol.getArity() == 0) { + // a constant + exp = new Constant(symbol); + } else { + if (Character.isDigit(symbolName.charAt(0))) { + // maybe a numerical value + if (stream.checkNext() != null && stream.checkNext().equals(DOT)) { + // Because tokens are separated by a DOT. + stream.next(); + symbolName += DOT + stream.next(); // decimal fraction + } Double d = Double.parseDouble(symbolName); - if (symbolName.contains(".")) { + // a numerical value + if (symbolName.contains(DOT)) { exp = new Constant(symbolName, DataTransferModel.typeDouble); } else { exp = new Constant(symbolName, DataTransferModel.typeInt); } - } - } catch (NumberFormatException e) { - if (stream.checkNext() != null && stream.checkNext().equals(COLON)) { - // when a type is specified. - stream.next(); - String typeName = stream.next(); - Type type = model.getType(typeName); - if (type == null) { - type = new Type(typeName, typeName); - } - exp = new Variable(symbolName, type); } else { - exp = new Variable(symbolName); + // a variable + exp = parseVariable(stream, model, symbolName); } } } @@ -324,16 +343,52 @@ break; } else if (operator.equals(ADD)) { operators.add(DataTransferModel.add); + stream.next(); } else if (operator.equals(MUL)) { operators.add(DataTransferModel.mul); + stream.next(); } else if (operator.equals(SUB)) { operators.add(DataTransferModel.sub); // not minus + stream.next(); } else if (operator.equals(DIV)) { operators.add(DataTransferModel.div); + stream.next(); + } else if (operator.equals(DOT)) { + // json accessor + Expression exp = expressions.remove(0); + stream.next(); // DOT + if (stream.checkNext() == null) throw new WrongJsonExpression(stream.getLine()); + String literalOrLeftCurlyBracket = stream.next(); + Expression paramTerm = null; + if (literalOrLeftCurlyBracket.equals(LEFT_CURLY_BRACKET)) { + // parameter + paramTerm = parseTerm(stream, model); + String rightCurlyBracket = stream.next(); + if (rightCurlyBracket == null || !rightCurlyBracket.equals(RIGHT_CURLY_BRACKET)) throw new WrongJsonExpression(stream.getLine()); + } else { + // literal + paramTerm = new Constant(literalOrLeftCurlyBracket, DataTransferModel.typeString); + } + Type paramType = null; + if (paramTerm instanceof Variable) { + paramType = ((Variable) paramTerm).getType(); + } else if (paramTerm instanceof Term) { + paramType = ((Term) paramTerm).getType(); + } + Term term = null; + if (paramType != null && DataConstraintModel.typeInt.isAncestorOf(paramType)) { + term = new JsonAccessor(DataConstraintModel.dotParam); + } else { + term = new JsonAccessor(DataConstraintModel.dot); + } + term.addChild(exp); + term.addChild(paramTerm); + expressions.add(term); + operator = stream.checkNext(); + if (operator == null || !operator.equals(DOT)) break; } else { break; } - stream.next(); // an arithmetic operator } if (expressions.size() == 1) { // no arithmetic operators @@ -372,6 +427,59 @@ return firstMonomial; } + private Expression parseJsonTerm(TokenStream stream, DataTransferModel model) throws ExpectedRightBracket, WrongJsonExpression, ExpectedColon { + Term jsonTerm = new Constant(DataConstraintModel.nil); + jsonTerm.setType(DataConstraintModel.typeJson); + while (stream.checkNext() != null && !stream.checkNext().equals(RIGHT_CURLY_BRACKET)) { + String key = stream.next(); + Constant keyExp = new Constant(key); + keyExp.setType(DataConstraintModel.typeString); + if (stream.checkNext() == null || !stream.checkNext().equals(COLON)) throw new ExpectedColon(stream.getLine()); + String colon = stream.next(); + Expression value = parseTerm(stream, model); + Term nextTerm = new Term(DataConstraintModel.addMember); + nextTerm.addChild(jsonTerm); + nextTerm.addChild(keyExp); + nextTerm.addChild(value); + jsonTerm = nextTerm; + if (stream.checkNext() == null || !stream.checkNext().equals(COMMA)) break; + String comma = stream.next(); + } + return jsonTerm; + } + + private Expression parseListTerm(TokenStream stream2, DataTransferModel model) throws ExpectedRightBracket, WrongJsonExpression, ExpectedColon { + Term listTerm = new Constant(DataConstraintModel.nil); + listTerm.setType(DataConstraintModel.typeList); + while (stream.checkNext() != null && !stream.checkNext().equals(RIGHT_SQUARE_BRACKET)) { + Expression element = parseTerm(stream, model); + Term nextTerm = new Term(DataConstraintModel.cons); + nextTerm.addChild(element); + nextTerm.addChild(listTerm); + listTerm = nextTerm; + if (stream.checkNext() == null || !stream.checkNext().equals(COMMA)) break; + String comma = stream.next(); + } + return listTerm; + } + + private Variable parseVariable(TokenStream stream, DataTransferModel model, String symbolName) { + Variable var; + if (stream.checkNext() != null && stream.checkNext().equals(COLON)) { + // when a type is specified. + stream.next(); + String typeName = stream.next(); + Type type = model.getType(typeName); + if (type == null) { + type = new Type(typeName, typeName); + } + var = new Variable(symbolName, type); + } else { + var = new Variable(symbolName); + } + return var; + } + /**-------------------------------------------------------------------------------- * [protected] /**-------------------------------------------------------------------------------- @@ -416,29 +524,38 @@ splitBy( splitBy( splitBy( - Arrays.asList(line.split("[ \t]")), - ADD, - ADD_REGX), - MUL, - MUL_REGX), - SUB, - SUB_REGX), - DIV, - DIV_REGX), - COMMA, - COMMA), - COLON, - COLON), - LEFT_BRACKET, - LEFT_BRACKET_REGX), - RIGHT_BRACKET, - RIGHT_BRACKET_REGX), - EQUALS, - EQUALS), - LEFT_CURLY_BRACKET, - LEFT_CURLY_BRACKET_REGX), - RIGHT_CURLY_BRACKET, - RIGHT_CURLY_BRACKET_REGX)); + splitBy( + splitBy( + splitBy( + Arrays.asList(line.split("[ \t]")), + ADD, + ADD_REGX), + MUL, + MUL_REGX), + SUB, + SUB_REGX), + DIV, + DIV_REGX), + DOT, + DOT_REGX), + COMMA, + COMMA), + COLON, + COLON), + LEFT_BRACKET, + LEFT_BRACKET_REGX), + RIGHT_BRACKET, + RIGHT_BRACKET_REGX), + EQUALS, + EQUALS), + LEFT_CURLY_BRACKET, + LEFT_CURLY_BRACKET_REGX), + RIGHT_CURLY_BRACKET, + RIGHT_CURLY_BRACKET_REGX), + LEFT_SQUARE_BRACKET, + LEFT_SQUARE_BRACKET_REGX), + RIGHT_SQUARE_BRACKET, + RIGHT_SQUARE_BRACKET_REGX)); } private ArrayList splitBy(final List tokens, final String delimiter, final String delimiterRegx) { diff --git a/AlgebraicDataflowArchitectureModel/src/parser/ParserDTRAM.java b/AlgebraicDataflowArchitectureModel/src/parser/ParserDTRAM.java index 830bd5f..2369375 100644 --- a/AlgebraicDataflowArchitectureModel/src/parser/ParserDTRAM.java +++ b/AlgebraicDataflowArchitectureModel/src/parser/ParserDTRAM.java @@ -10,10 +10,12 @@ import com.mxgraph.view.mxGraph; import com.mxgraph.view.mxGraphView; +import application.editor.Stage; import models.dataFlowModel.DataTransferModel; import parser.exceptions.ExpectedAssignment; import parser.exceptions.ExpectedChannel; import parser.exceptions.ExpectedChannelName; +import parser.exceptions.ExpectedColon; import parser.exceptions.ExpectedEquals; import parser.exceptions.ExpectedFormulaChannel; import parser.exceptions.ExpectedGeometry; @@ -26,6 +28,7 @@ import parser.exceptions.ExpectedResource; import parser.exceptions.ExpectedRightBracket; import parser.exceptions.ExpectedStateTransition; +import parser.exceptions.WrongJsonExpression; import parser.exceptions.WrongLHSExpression; import parser.exceptions.WrongRHSExpression; @@ -61,9 +64,11 @@ /**-------------------------------------------------------------------------------- * * @param reader + * @throws WrongJsonExpression + * @throws ExpectedColon */ public DataTransferModel doParseModel() - throws ExpectedRightBracket, ExpectedChannel, ExpectedChannelName, ExpectedLeftCurlyBracket, ExpectedInOrOutOrRefKeyword, ExpectedStateTransition, ExpectedEquals, ExpectedRHSExpression, WrongLHSExpression, WrongRHSExpression, ExpectedAssignment, ExpectedModel, ExpectedGeometry { + throws ExpectedRightBracket, ExpectedChannel, ExpectedChannelName, ExpectedLeftCurlyBracket, ExpectedInOrOutOrRefKeyword, ExpectedStateTransition, ExpectedEquals, ExpectedRHSExpression, WrongLHSExpression, WrongRHSExpression, ExpectedAssignment, ExpectedModel, ExpectedGeometry, WrongJsonExpression, ExpectedColon { DataTransferModel model = getParsedModel(); return model; } @@ -83,9 +88,11 @@ /**-------------------------------------------------------------------------------- * * @param stream + * @throws WrongJsonExpression + * @throws ExpectedColon */ private DataTransferModel getParsedModel() - throws ExpectedRightBracket, ExpectedChannel, ExpectedChannelName, ExpectedLeftCurlyBracket, ExpectedInOrOutOrRefKeyword, ExpectedStateTransition, ExpectedEquals, ExpectedRHSExpression, WrongLHSExpression, WrongRHSExpression, ExpectedAssignment, ExpectedModel, ExpectedGeometry { + throws ExpectedRightBracket, ExpectedChannel, ExpectedChannelName, ExpectedLeftCurlyBracket, ExpectedInOrOutOrRefKeyword, ExpectedStateTransition, ExpectedEquals, ExpectedRHSExpression, WrongLHSExpression, WrongRHSExpression, ExpectedAssignment, ExpectedModel, ExpectedGeometry, WrongJsonExpression, ExpectedColon { if (!stream.hasNext()) throw new NullPointerException(); @@ -148,11 +155,28 @@ String h = stream.next(); int hC = Integer.parseInt(h); - Object root = graph.getDefaultParent(); mxIGraphModel graphModel = graph.getModel(); - for (int i = 0; i < graph.getModel().getChildCount(root); i++) { + mxCell root = (mxCell) graph.getDefaultParent(); + mxCell nodeLayer = (mxCell) root.getChildAt(Stage.NODE_LAYER); + mxCell dataFlowLayer = (mxCell) root.getChildAt(Stage.DATA_FLOW_LAYER); + for (int i = 0; i < graph.getModel().getChildCount(nodeLayer); i++) { - Object cell = graph.getModel().getChildAt(root, i); + Object cell = graph.getModel().getChildAt(nodeLayer, i); + if (!graph.getModel().isVertex(cell)) continue; + + mxGeometry geom = (mxGeometry) ((mxCell) cell).getGeometry().clone(); + mxGraphView view = graph.getView(); + mxCellState state = view.getState(cell); + + if (!name.equals(state.getLabel())) continue; + + geom.setX(xC); + geom.setY(yC); + graphModel.setGeometry(cell, geom); + } + for (int i = 0; i < graph.getModel().getChildCount(dataFlowLayer); i++) { + + Object cell = graph.getModel().getChildAt(dataFlowLayer, i); if (!graph.getModel().isVertex(cell)) continue; mxGeometry geom = (mxGeometry) ((mxCell) cell).getGeometry().clone(); diff --git a/AlgebraicDataflowArchitectureModel/src/parser/exceptions/ExpectedColon.java b/AlgebraicDataflowArchitectureModel/src/parser/exceptions/ExpectedColon.java new file mode 100644 index 0000000..426aaf1 --- /dev/null +++ b/AlgebraicDataflowArchitectureModel/src/parser/exceptions/ExpectedColon.java @@ -0,0 +1,8 @@ +package parser.exceptions; + +public class ExpectedColon extends ParseException { + + public ExpectedColon(int line) { + super(line); + } +} diff --git a/AlgebraicDataflowArchitectureModel/src/parser/exceptions/WrongJsonExpression.java b/AlgebraicDataflowArchitectureModel/src/parser/exceptions/WrongJsonExpression.java new file mode 100644 index 0000000..6a84d6f --- /dev/null +++ b/AlgebraicDataflowArchitectureModel/src/parser/exceptions/WrongJsonExpression.java @@ -0,0 +1,9 @@ +package parser.exceptions; + +public class WrongJsonExpression extends ParseException { + + public WrongJsonExpression(int line) { + super(line); + } + +} diff --git a/AlgebraicDataflowArchitectureModel/src/tests/CodeGeneratorTest.java b/AlgebraicDataflowArchitectureModel/src/tests/CodeGeneratorTest.java index a89ea3c..f439501 100644 --- a/AlgebraicDataflowArchitectureModel/src/tests/CodeGeneratorTest.java +++ b/AlgebraicDataflowArchitectureModel/src/tests/CodeGeneratorTest.java @@ -17,12 +17,14 @@ import parser.exceptions.ExpectedAssignment; import parser.exceptions.ExpectedChannel; import parser.exceptions.ExpectedChannelName; +import parser.exceptions.ExpectedColon; import parser.exceptions.ExpectedEquals; import parser.exceptions.ExpectedInOrOutOrRefKeyword; import parser.exceptions.ExpectedLeftCurlyBracket; import parser.exceptions.ExpectedRHSExpression; import parser.exceptions.ExpectedRightBracket; import parser.exceptions.ExpectedStateTransition; +import parser.exceptions.WrongJsonExpression; import parser.exceptions.WrongLHSExpression; import parser.exceptions.WrongRHSExpression; @@ -41,7 +43,7 @@ System.out.println(codetree); } catch (ExpectedChannel | ExpectedChannelName | ExpectedLeftCurlyBracket | ExpectedInOrOutOrRefKeyword | ExpectedStateTransition | ExpectedEquals | ExpectedRHSExpression | WrongLHSExpression - | WrongRHSExpression | ExpectedRightBracket | ExpectedAssignment e) { + | WrongRHSExpression | ExpectedRightBracket | ExpectedAssignment | WrongJsonExpression | ExpectedColon e) { e.printStackTrace(); } } catch (FileNotFoundException e) { diff --git a/AlgebraicDataflowArchitectureModel/src/tests/DataConstraintModelTest.java b/AlgebraicDataflowArchitectureModel/src/tests/DataConstraintModelTest.java index 5719cac..e621180 100644 --- a/AlgebraicDataflowArchitectureModel/src/tests/DataConstraintModelTest.java +++ b/AlgebraicDataflowArchitectureModel/src/tests/DataConstraintModelTest.java @@ -12,33 +12,33 @@ public void test() { // Construct a data constraint architecture model. DataConstraintModel model = new DataConstraintModel(); - IdentifierTemplate customer_off = new IdentifierTemplate("customers.{customer_id}.off", 1); - IdentifierTemplate customer_add = new IdentifierTemplate("customers.{customer_id}.add", 1); - IdentifierTemplate company_add = new IdentifierTemplate("companies.{company_id}.add", 1); + ResourcePath customer_off = new ResourcePath("customers.{customer_id}.off", 1); + ResourcePath customer_add = new ResourcePath("customers.{customer_id}.add", 1); + ResourcePath company_add = new ResourcePath("companies.{company_id}.add", 1); - ChannelGenerator gin_1 = new ChannelGenerator("gin_1"); // set customer's office - GroupSelector x1 = new GroupSelector(); + Channel gin_1 = new Channel("gin_1"); // set customer's office +// GroupSelector x1 = new GroupSelector(); ChannelMember customer_off_1 = new ChannelMember(customer_off); - customer_off_1.addSelector(x1); +// customer_off_1.addSelector(x1); gin_1.addChannelMember(customer_off_1); assertEquals(customer_off.getNumberOfParameters(), customer_off_1.getSelectors().size()); - ChannelGenerator gin_2 = new ChannelGenerator("gin_2"); // set companie's address - GroupSelector x2 = new GroupSelector(); + Channel gin_2 = new Channel("gin_2"); // set companie's address +// GroupSelector x2 = new GroupSelector(); ChannelMember company_add_1 = new ChannelMember(company_add); - company_add_1.addSelector(x2); +// company_add_1.addSelector(x2); gin_2.addChannelMember(company_add_1); assertEquals(company_add.getNumberOfParameters(), company_add_1.getSelectors().size()); - ChannelGenerator g = new ChannelGenerator("g"); // update customer's address - GroupSelector x3 = new GroupSelector(); - ChannelSelector y = new ChannelSelector(); + Channel g = new Channel("g"); // update customer's address +// GroupSelector x3 = new GroupSelector(); +// ChannelSelector y = new ChannelSelector(); ChannelMember customer_off_2 = new ChannelMember(customer_off); ChannelMember company_add_2 = new ChannelMember(company_add); ChannelMember customer_add_2 = new ChannelMember(customer_add); - customer_off_2.addSelector(x3); - company_add_2.addSelector(y); - customer_add_2.addSelector(x3); +// customer_off_2.addSelector(x3); +// company_add_2.addSelector(y); +// customer_add_2.addSelector(x3); g.addChannelMember(customer_off_2); g.addChannelMember(customer_add_2); g.addChannelMember(company_add_2); @@ -46,14 +46,14 @@ assertEquals(customer_add.getNumberOfParameters(), customer_add_2.getSelectors().size()); assertEquals(company_add.getNumberOfParameters(), company_add_2.getSelectors().size()); - model.addIOChannelGenerator(gin_1); - model.addIOChannelGenerator(gin_2); - model.addChannelGenerator(g); + model.addIOChannel(gin_1); + model.addIOChannel(gin_2); + model.addChannel(g); // Check the model. - assertEquals(3, model.getIdentifierTemplates().size()); - assertEquals(2, model.getIOChannelGenerators().size()); - assertEquals(1, model.getChannelGenerators().size()); + assertEquals(3, model.getResourcePaths().size()); + assertEquals(2, model.getIOChannels().size()); + assertEquals(1, model.getChannels().size()); } } diff --git a/AlgebraicDataflowArchitectureModel/src/tests/DataFlowModelTest.java b/AlgebraicDataflowArchitectureModel/src/tests/DataFlowModelTest.java index 6065992..cea2cee 100644 --- a/AlgebraicDataflowArchitectureModel/src/tests/DataFlowModelTest.java +++ b/AlgebraicDataflowArchitectureModel/src/tests/DataFlowModelTest.java @@ -14,19 +14,19 @@ public void test() { // Construct a data-flow architecture model. DataTransferModel model = new DataTransferModel(); - IdentifierTemplate customer_off = new IdentifierTemplate("customers.{x1}.off", 1); // an identifier template to specify a customer's office resource - IdentifierTemplate company_add = new IdentifierTemplate("companies.{x2}.add", 1); // an identifier template to specify a companie's address resource - IdentifierTemplate customer_add = new IdentifierTemplate("customers.{x1}.add", 1); // an identifier template to specify a customer's address resource + ResourcePath customer_off = new ResourcePath("customers.{x1}.off", 1); // an identifier template to specify a customer's office resource + ResourcePath company_add = new ResourcePath("companies.{x2}.add", 1); // an identifier template to specify a companie's address resource + ResourcePath customer_add = new ResourcePath("customers.{x1}.add", 1); // an identifier template to specify a customer's address resource // === gin_1 === // // customers.{x1}.off(c, set(x)) == x // customers.{x1}.off(c, e) == c // - DataTransferChannelGenerator gin_1 = new DataTransferChannelGenerator("gin_1"); // set customer's office (an input channel) - GroupSelector x1 = new GroupSelector(); + DataTransferChannel gin_1 = new DataTransferChannel("gin_1"); // set customer's office (an input channel) +// GroupSelector x1 = new GroupSelector(); ChannelMember customer_off_1 = new ChannelMember(customer_off); - customer_off_1.addSelector(x1); // x1 is determined by the path parameter in customer's office template, and serves as a group selector in this channel +// customer_off_1.addSelector(x1); // x1 is determined by the path parameter in customer's office template, and serves as a group selector in this channel gin_1.addChannelMember(customer_off_1); assertEquals(customer_off.getNumberOfParameters(), customer_off_1.getSelectors().size()); @@ -35,10 +35,10 @@ // companies.{x2}.add(a, set(y)) == y // companies.{x2}.add(a, e) == a // - DataTransferChannelGenerator gin_2 = new DataTransferChannelGenerator("gin_2"); // set companie's address (an input channel) - GroupSelector x2 = new GroupSelector(); + DataTransferChannel gin_2 = new DataTransferChannel("gin_2"); // set companie's address (an input channel) +// GroupSelector x2 = new GroupSelector(); ChannelMember company_add_1 = new ChannelMember(company_add); - company_add_1.addSelector(x2); // x2 is determined by the path parameter in companie's address template, and serves as a group selector in this channel +// company_add_1.addSelector(x2); // x2 is determined by the path parameter in companie's address template, and serves as a group selector in this channel gin_2.addChannelMember(company_add_1); assertEquals(company_add.getNumberOfParameters(), company_add_1.getSelectors().size()); @@ -48,15 +48,15 @@ // companies.{y}.add( a1, update(y, z)) == z // customers.{x3}.add(a2, update(y, z)) == z // - DataTransferChannelGenerator g = new DataTransferChannelGenerator("g"); // update customer's address - GroupSelector x3 = new GroupSelector(); - ChannelSelector y = new ChannelSelector(); + DataTransferChannel g = new DataTransferChannel("g"); // update customer's address +// GroupSelector x3 = new GroupSelector(); +// ChannelSelector y = new ChannelSelector(); ChannelMember customer_off_2 = new ChannelMember(customer_off); ChannelMember company_add_2 = new ChannelMember(company_add); ChannelMember customer_add_2 = new ChannelMember(customer_add); - customer_off_2.addSelector(x3); // x3 is determined by the path parameter in customer's office template, and serves as a group selector in this channel - company_add_2.addSelector(y); // y is determined by the value of the customer's office resource, and serves as a channel selector in this channel - customer_add_2.addSelector(x3); // x3 determines the path parameter in customer's address template to update +// customer_off_2.addSelector(x3); // x3 is determined by the path parameter in customer's office template, and serves as a group selector in this channel +// company_add_2.addSelector(y); // y is determined by the value of the customer's office resource, and serves as a channel selector in this channel +// customer_add_2.addSelector(x3); // x3 determines the path parameter in customer's address template to update g.addChannelMemberAsInput(customer_off_2); g.addChannelMemberAsInput(customer_add_2); g.addChannelMemberAsOutput(company_add_2); @@ -65,14 +65,14 @@ assertEquals(company_add.getNumberOfParameters(), company_add_2.getSelectors().size()); // Construct a data-flow architecture model. - model.addIOChannelGenerator(gin_1); - model.addIOChannelGenerator(gin_2); - model.addChannelGenerator(g); + model.addIOChannel(gin_1); + model.addIOChannel(gin_2); + model.addChannel(g); // Check the model. - assertEquals(3, model.getIdentifierTemplates().size()); - assertEquals(2, model.getIOChannelGenerators().size()); - assertEquals(1, model.getChannelGenerators().size()); + assertEquals(3, model.getResourcePaths().size()); + assertEquals(2, model.getIOChannels().size()); + assertEquals(1, model.getChannels().size()); // Extract the resource dependency graph. DataFlowGraph resourceDependencyGraph = model.getDataFlowGraph(); diff --git a/AlgebraicDataflowArchitectureModel/src/tests/DataStorageDecisionTest.java b/AlgebraicDataflowArchitectureModel/src/tests/DataStorageDecisionTest.java index 67a1a2a..e4799a2 100644 --- a/AlgebraicDataflowArchitectureModel/src/tests/DataStorageDecisionTest.java +++ b/AlgebraicDataflowArchitectureModel/src/tests/DataStorageDecisionTest.java @@ -13,12 +13,14 @@ import parser.exceptions.ExpectedAssignment; import parser.exceptions.ExpectedChannel; import parser.exceptions.ExpectedChannelName; +import parser.exceptions.ExpectedColon; import parser.exceptions.ExpectedEquals; import parser.exceptions.ExpectedInOrOutOrRefKeyword; import parser.exceptions.ExpectedLeftCurlyBracket; import parser.exceptions.ExpectedRHSExpression; import parser.exceptions.ExpectedRightBracket; import parser.exceptions.ExpectedStateTransition; +import parser.exceptions.WrongJsonExpression; import parser.exceptions.WrongLHSExpression; import parser.exceptions.WrongRHSExpression; @@ -35,11 +37,11 @@ DataTransferModelAnalyzer.annotateWithSelectableDataTransferAttiribute(graph); DataTransferMethodAnalyzer.decideToStoreResourceStates(graph); for(Node n:graph.getNodes()) { - System.out.println(((ResourceNode) n).getIdentifierTemplate().getResourceName() + ":" + ((StoreAttribute) ((ResourceNode) n).getAttribute()).isStored()); + System.out.println(((ResourceNode) n).getResource().getResourceName() + ":" + ((StoreAttribute) ((ResourceNode) n).getAttribute()).isStored()); } } catch (ExpectedChannel | ExpectedChannelName | ExpectedLeftCurlyBracket | ExpectedInOrOutOrRefKeyword | ExpectedStateTransition | ExpectedEquals | ExpectedRHSExpression | WrongLHSExpression - | WrongRHSExpression | ExpectedRightBracket | ExpectedAssignment e) { + | WrongRHSExpression | ExpectedRightBracket | ExpectedAssignment | WrongJsonExpression | ExpectedColon e) { e.printStackTrace(); } } catch (FileNotFoundException e) { diff --git a/AlgebraicDataflowArchitectureModel/src/tests/DataStorageNecessityTest.java b/AlgebraicDataflowArchitectureModel/src/tests/DataStorageNecessityTest.java index 9a7c300..75cde4f 100644 --- a/AlgebraicDataflowArchitectureModel/src/tests/DataStorageNecessityTest.java +++ b/AlgebraicDataflowArchitectureModel/src/tests/DataStorageNecessityTest.java @@ -12,12 +12,14 @@ import parser.exceptions.ExpectedAssignment; import parser.exceptions.ExpectedChannel; import parser.exceptions.ExpectedChannelName; +import parser.exceptions.ExpectedColon; import parser.exceptions.ExpectedEquals; import parser.exceptions.ExpectedInOrOutOrRefKeyword; import parser.exceptions.ExpectedLeftCurlyBracket; import parser.exceptions.ExpectedRHSExpression; import parser.exceptions.ExpectedRightBracket; import parser.exceptions.ExpectedStateTransition; +import parser.exceptions.WrongJsonExpression; import parser.exceptions.WrongLHSExpression; import parser.exceptions.WrongRHSExpression; @@ -39,7 +41,7 @@ } } catch (ExpectedChannel | ExpectedChannelName | ExpectedLeftCurlyBracket | ExpectedInOrOutOrRefKeyword | ExpectedStateTransition | ExpectedEquals | ExpectedRHSExpression | WrongLHSExpression - | WrongRHSExpression | ExpectedRightBracket | ExpectedAssignment e) { + | WrongRHSExpression | ExpectedRightBracket | ExpectedAssignment | WrongJsonExpression | ExpectedColon e) { e.printStackTrace(); } } catch (FileNotFoundException e) { diff --git a/AlgebraicDataflowArchitectureModel/src/tests/EdgeTransitionSelectableTest.java b/AlgebraicDataflowArchitectureModel/src/tests/EdgeTransitionSelectableTest.java index 847fb6f..150b1b6 100644 --- a/AlgebraicDataflowArchitectureModel/src/tests/EdgeTransitionSelectableTest.java +++ b/AlgebraicDataflowArchitectureModel/src/tests/EdgeTransitionSelectableTest.java @@ -12,12 +12,14 @@ import parser.exceptions.ExpectedAssignment; import parser.exceptions.ExpectedChannel; import parser.exceptions.ExpectedChannelName; +import parser.exceptions.ExpectedColon; import parser.exceptions.ExpectedEquals; import parser.exceptions.ExpectedInOrOutOrRefKeyword; import parser.exceptions.ExpectedLeftCurlyBracket; import parser.exceptions.ExpectedRHSExpression; import parser.exceptions.ExpectedRightBracket; import parser.exceptions.ExpectedStateTransition; +import parser.exceptions.WrongJsonExpression; import parser.exceptions.WrongLHSExpression; import parser.exceptions.WrongRHSExpression; @@ -38,7 +40,7 @@ } } catch (ExpectedChannel | ExpectedChannelName | ExpectedLeftCurlyBracket | ExpectedInOrOutOrRefKeyword | ExpectedStateTransition | ExpectedEquals | ExpectedRHSExpression | WrongLHSExpression - | WrongRHSExpression | ExpectedRightBracket | ExpectedAssignment e) { + | WrongRHSExpression | ExpectedRightBracket | ExpectedAssignment | WrongJsonExpression | ExpectedColon e) { e.printStackTrace(); } } catch (FileNotFoundException e) { diff --git a/AlgebraicDataflowArchitectureModel/src/tests/FormulaChannelTest.java b/AlgebraicDataflowArchitectureModel/src/tests/FormulaChannelTest.java index 2cf2b37..a8f3503 100644 --- a/AlgebraicDataflowArchitectureModel/src/tests/FormulaChannelTest.java +++ b/AlgebraicDataflowArchitectureModel/src/tests/FormulaChannelTest.java @@ -5,18 +5,18 @@ import models.algebra.Symbol; import models.dataConstraintModel.ChannelMember; import models.dataConstraintModel.DataConstraintModel; -import models.dataConstraintModel.IdentifierTemplate; -import models.visualModel.FormulaChannelGenerator; +import models.dataConstraintModel.ResourcePath; +import models.visualModel.FormulaChannel; public class FormulaChannelTest { @Test public void test() { - IdentifierTemplate id1 = new IdentifierTemplate("r1", 0); - IdentifierTemplate id2 = new IdentifierTemplate("r2", 0); - IdentifierTemplate id3 = new IdentifierTemplate("r3", 0); + ResourcePath id1 = new ResourcePath("r1", 0); + ResourcePath id2 = new ResourcePath("r2", 0); + ResourcePath id3 = new ResourcePath("r3", 0); - FormulaChannelGenerator ch1 = new FormulaChannelGenerator("ch1", DataConstraintModel.add); + FormulaChannel ch1 = new FormulaChannel("ch1", DataConstraintModel.add); System.out.println(ch1.getFormula()); System.out.println(ch1.getFormulaTerm()); System.out.println(ch1.getSourceText()); @@ -33,7 +33,7 @@ System.out.println(ch1.getFormulaTerm()); System.out.println(ch1.getSourceText()); - FormulaChannelGenerator ch2 = new FormulaChannelGenerator("ch2", DataConstraintModel.mul); + FormulaChannel ch2 = new FormulaChannel("ch2", DataConstraintModel.mul); System.out.println(ch2.getFormula()); System.out.println(ch2.getFormulaTerm()); System.out.println(ch2.getSourceText()); diff --git a/AlgebraicDataflowArchitectureModel/src/tests/InverseTest.java b/AlgebraicDataflowArchitectureModel/src/tests/InverseTest.java index bfa8957..165013e 100644 --- a/AlgebraicDataflowArchitectureModel/src/tests/InverseTest.java +++ b/AlgebraicDataflowArchitectureModel/src/tests/InverseTest.java @@ -14,18 +14,23 @@ import models.algebra.Expression; import models.algebra.Position; +import models.algebra.Term; import models.algebra.Variable; +import models.dataConstraintModel.DataConstraintModel; +import models.dataConstraintModel.JsonType; import models.dataFlowModel.DataTransferModel; import parser.Parser; import parser.Parser.TokenStream; +import parser.exceptions.ExpectedColon; import parser.exceptions.ExpectedRightBracket; +import parser.exceptions.WrongJsonExpression; public class InverseTest { @Test public void test() { - String lhs = "y"; DataTransferModel model = new DataTransferModel(); try { + String lhs = "y"; String rhs = "(a * x + b) * c"; TokenStream stream = new Parser.TokenStream(); @@ -33,7 +38,7 @@ stream.addLine(rhs); Expression rhsExp = parser.parseTerm(stream, model); - System.out.println(lhs + " = " + rhsExp); + System.out.println("=== solve{" + lhs + " = " + rhsExp + "} for a, b, d, x ==="); HashMap rhsVars = rhsExp.getVariables(); assertEquals(4, rhsVars.size()); @@ -47,7 +52,66 @@ assertFalse(inv.contains(v)); System.out.println(rhsVars.get(vPos) + " = " + inv); } - } catch (ExpectedRightBracket e) { + + // Extract an element in a tuple + TokenStream stream2 = new Parser.TokenStream(); + Parser parser2 = new Parser(stream2); + stream2.addLine("fst(tuple(x, y))"); + Expression tupleExp = parser2.parseTerm(stream2, model); + stream2.addLine("snd(tuple(x, y))"); + Expression tupleExp2 = parser2.parseTerm(stream2, model); + Expression reduced = ((Term) tupleExp).reduce(); + Expression reduced2 = ((Term) tupleExp2).reduce(); + Variable x = new Variable("x"); + assertEquals(reduced, x); + assertEquals(reduced2, y); + System.out.println("=== simplify ==="); + System.out.println(tupleExp + " = " + reduced); + System.out.println(tupleExp2 + " = " + reduced2); + + // Solve {z = fst(x)} for x + TokenStream stream3 = new Parser.TokenStream(); + Parser parser3 = new Parser(stream3); + stream3.addLine("fst(x)"); + Expression rhsExp3 = parser3.parseTerm(stream3, model); + Variable z = new Variable("z"); + System.out.println("=== solve{" + z + " = " + rhsExp3 + "} for x ==="); + HashMap rhsVars3 = rhsExp3.getVariables(); + for (Position vPos: rhsVars3.keySet()) { + Variable v = rhsVars3.get(vPos); + Expression inv = rhsExp3.getInverseMap(z, vPos); // inverse map to get v back from the output value z + if (inv instanceof Term) { + inv = ((Term) inv).reduce(); + } + assertTrue(inv.contains(z)); + assertFalse(inv.contains(v)); + System.out.println(rhsVars3.get(vPos) + " = " + inv); + } + + // Solve {z = x.id} for x + TokenStream stream4 = new Parser.TokenStream(); + Parser parser4 = new Parser(stream4); + stream4.addLine("x.id"); + Expression rhsExp4 = parser4.parseTerm(stream4, model); + System.out.println("=== solve{" + z + " = " + rhsExp4 + "} for x ==="); + HashMap rhsVars4 = rhsExp4.getVariables(); + for (Position vPos: rhsVars4.keySet()) { + Variable v = rhsVars4.get(vPos); + if (x.getName().equals("x")) { + JsonType jsonType = new JsonType("Json", "HashMap<>", DataConstraintModel.typeJson); + jsonType.addMemberType("id", DataConstraintModel.typeInt); + jsonType.addMemberType("name", DataConstraintModel.typeString); + v.setType(jsonType); + } + Expression inv = rhsExp4.getInverseMap(z, vPos); // inverse map to get v back from the output value z + if (inv instanceof Term) { + inv = ((Term) inv).reduce(); + } + System.out.println(rhsVars4.get(vPos) + " = " + inv); + assertTrue(inv.contains(z)); + assertFalse(inv.contains(v)); + } + } catch (ExpectedRightBracket | WrongJsonExpression | ExpectedColon e) { e.printStackTrace(); } } diff --git a/AlgebraicDataflowArchitectureModel/src/tests/SimplifiedDataFlowModelTest.java b/AlgebraicDataflowArchitectureModel/src/tests/SimplifiedDataFlowModelTest.java index ff262b2..acb5333 100644 --- a/AlgebraicDataflowArchitectureModel/src/tests/SimplifiedDataFlowModelTest.java +++ b/AlgebraicDataflowArchitectureModel/src/tests/SimplifiedDataFlowModelTest.java @@ -14,16 +14,16 @@ public void test() { // Construct a data-flow architecture model. DataTransferModel model = new DataTransferModel(); - IdentifierTemplate payment = new IdentifierTemplate("payment", 0); // an identifier template to specify the payment resource - IdentifierTemplate loyalty = new IdentifierTemplate("loyalty", 0); // an identifier template to specify the loyalty resource - IdentifierTemplate history = new IdentifierTemplate("history", 0); // an identifier template to specify the payment history resource - IdentifierTemplate total = new IdentifierTemplate("total", 0); // an identifier template to specify the total payment resource + ResourcePath payment = new ResourcePath("payment", 0); // a resource to specify the payment resource + ResourcePath loyalty = new ResourcePath("loyalty", 0); // a resource to specify the loyalty resource + ResourcePath history = new ResourcePath("history", 0); // a resource to specify the payment history resource + ResourcePath total = new ResourcePath("total", 0); // a resource to specify the total payment resource // === cin === // // payment(p1, purchase(x)) == x // - DataTransferChannelGenerator cin = new DataTransferChannelGenerator("cin"); + DataTransferChannel cin = new DataTransferChannel("cin"); ChannelMember cin_payment = new ChannelMember(payment); cin.addChannelMember(cin_payment); assertEquals(cin.getChannelMembers().size(), 1); @@ -33,7 +33,7 @@ // payment(p1, update1(y)) == y // loyalty(l, update1(y)) == floor(y * 0.05) // - DataTransferChannelGenerator c1 = new DataTransferChannelGenerator("c1"); + DataTransferChannel c1 = new DataTransferChannel("c1"); ChannelMember c1_payment = new ChannelMember(payment); ChannelMember c1_loyalty = new ChannelMember(loyalty); c1.addChannelMemberAsInput(c1_payment); @@ -47,7 +47,7 @@ // payment(p1, update2(z)) == z // history(h, update2(z)) == cons(z, h) // - DataTransferChannelGenerator c2 = new DataTransferChannelGenerator("c2"); + DataTransferChannel c2 = new DataTransferChannel("c2"); ChannelMember c2_payment = new ChannelMember(payment); ChannelMember c2_history = new ChannelMember(history); c2.addChannelMemberAsInput(c2_payment); @@ -61,7 +61,7 @@ // history(h, update3(u)) == u // total(t, update3(u)) == sum(u) // - DataTransferChannelGenerator c3 = new DataTransferChannelGenerator("c3"); + DataTransferChannel c3 = new DataTransferChannel("c3"); ChannelMember c3_history = new ChannelMember(history); ChannelMember c3_total = new ChannelMember(total); c3.addChannelMemberAsInput(c3_history); @@ -71,15 +71,15 @@ assertEquals(c3.getOutputChannelMembers().size(), 1); // Construct a data-flow architecture model. - model.addIOChannelGenerator(cin); - model.addChannelGenerator(c1); - model.addChannelGenerator(c2); - model.addChannelGenerator(c3); + model.addIOChannel(cin); + model.addChannel(c1); + model.addChannel(c2); + model.addChannel(c3); // Check the model. - assertEquals(4, model.getIdentifierTemplates().size()); - assertEquals(1, model.getIOChannelGenerators().size()); - assertEquals(3, model.getChannelGenerators().size()); + assertEquals(4, model.getResourcePaths().size()); + assertEquals(1, model.getIOChannels().size()); + assertEquals(3, model.getChannels().size()); // Extract the resource dependency graph. DataFlowGraph resourceDependencyGraph = model.getDataFlowGraph(); diff --git a/AlgebraicDataflowArchitectureModel/src/tests/UpdateCodeGenerationTest.java b/AlgebraicDataflowArchitectureModel/src/tests/UpdateCodeGenerationTest.java index cfd510c..69a5b1f 100644 --- a/AlgebraicDataflowArchitectureModel/src/tests/UpdateCodeGenerationTest.java +++ b/AlgebraicDataflowArchitectureModel/src/tests/UpdateCodeGenerationTest.java @@ -13,8 +13,8 @@ import models.algebra.Variable; import models.dataConstraintModel.*; import models.dataFlowModel.DataTransferModel; -import models.dataFlowModel.DataTransferChannelGenerator; -import models.dataFlowModel.DataTransferChannelGenerator.IResourceStateAccessor; +import models.dataFlowModel.DataTransferChannel; +import models.dataFlowModel.DataTransferChannel.IResourceStateAccessor; import models.dataFlowModel.ResolvingMultipleDefinitionIsFutureWork; public class UpdateCodeGenerationTest { @@ -25,10 +25,10 @@ Symbol sum = new Symbol("sum", 1, Symbol.Type.PREFIX, "stream().mapToInt(x->x).sum", Symbol.Type.METHOD); // resources - IdentifierTemplate payment = new IdentifierTemplate("payment", DataConstraintModel.typeInt, 0); // an identifier template to specify the payment resource - IdentifierTemplate loyalty = new IdentifierTemplate("loyalty", DataConstraintModel.typeInt, 0); // an identifier template to specify the loyalty resource - IdentifierTemplate history = new IdentifierTemplate("history", DataConstraintModel.typeList, 0);// an identifier template to specify the payment history resource - IdentifierTemplate total = new IdentifierTemplate("total", DataConstraintModel.typeInt, 0); // an identifier template to specify the total payment resource + ResourcePath payment = new ResourcePath("payment", DataConstraintModel.typeInt, 0); // a resource to specify the payment resource + ResourcePath loyalty = new ResourcePath("loyalty", DataConstraintModel.typeInt, 0); // a resource to specify the loyalty resource + ResourcePath history = new ResourcePath("history", DataConstraintModel.typeList, 0);// a resource to specify the payment history resource + ResourcePath total = new ResourcePath("total", DataConstraintModel.typeInt, 0); // a resource to specify the total payment resource // fields in the Java program final Field fPayment = new Field("payment", DataConstraintModel.typeInt); @@ -42,7 +42,7 @@ final Parameter pTotal = new Parameter("total", DataConstraintModel.typeInt); IResourceStateAccessor pushAccessor = new IResourceStateAccessor() { @Override - public Expression getCurrentStateAccessorFor(IdentifierTemplate target, IdentifierTemplate from) { + public Expression getCurrentStateAccessorFor(ResourcePath target, ResourcePath from) { if (target.equals(from)) { if (target.equals(payment)) return fPayment; if (target.equals(loyalty)) return fLoyalty; @@ -52,7 +52,7 @@ return null; } @Override - public Expression getNextStateAccessorFor(IdentifierTemplate target, IdentifierTemplate from) { + public Expression getNextStateAccessorFor(ResourcePath target, ResourcePath from) { if (target.equals(payment)) return pPayment; if (target.equals(loyalty)) return pLoyalty; if (target.equals(history)) return pHistory; @@ -68,7 +68,7 @@ final Symbol totalGetter = new Symbol("getTotal", 1, Symbol.Type.METHOD); IResourceStateAccessor pullAccessor = new IResourceStateAccessor() { @Override - public Expression getCurrentStateAccessorFor(IdentifierTemplate target, IdentifierTemplate from) { + public Expression getCurrentStateAccessorFor(ResourcePath target, ResourcePath from) { if (target.equals(from)) { if (target.equals(payment)) return fPayment; if (target.equals(loyalty)) return fLoyalty; @@ -78,7 +78,7 @@ return null; } @Override - public Expression getNextStateAccessorFor(IdentifierTemplate target, IdentifierTemplate from) { + public Expression getNextStateAccessorFor(ResourcePath target, ResourcePath from) { if (target.equals(payment)) { Term getter = new Term(paymentGetter); getter.addChild(fPayment); @@ -108,7 +108,7 @@ // payment(p1, update1(y)) == y // loyalty(l, update1(y)) == floor(y * 0.05) // - DataTransferChannelGenerator c1 = new DataTransferChannelGenerator("c1"); + DataTransferChannel c1 = new DataTransferChannel("c1"); ChannelMember c1_payment = new ChannelMember(payment); ChannelMember c1_loyalty = new ChannelMember(loyalty); c1.addChannelMemberAsInput(c1_payment); @@ -175,7 +175,7 @@ // payment(p1, update2(z)) == z // history(h, update2(z)) == cons(z, h) // - DataTransferChannelGenerator c2 = new DataTransferChannelGenerator("c2"); + DataTransferChannel c2 = new DataTransferChannel("c2"); ChannelMember c2_payment = new ChannelMember(payment); ChannelMember c2_history = new ChannelMember(history); c2.addChannelMemberAsInput(c2_payment); @@ -238,7 +238,7 @@ // history(h, update3(u)) = u // total(t, update3(u)) = sum(u) // - DataTransferChannelGenerator c3 = new DataTransferChannelGenerator("c3"); + DataTransferChannel c3 = new DataTransferChannel("c3"); ChannelMember c3_history = new ChannelMember(history); ChannelMember c3_total = new ChannelMember(total); c3.addChannelMemberAsInput(c3_history); diff --git a/AlgebraicDataflowArchitectureModel/src/tests/UpdateConflictCheckTest.java b/AlgebraicDataflowArchitectureModel/src/tests/UpdateConflictCheckTest.java index 5f51af7..7001ea8 100644 --- a/AlgebraicDataflowArchitectureModel/src/tests/UpdateConflictCheckTest.java +++ b/AlgebraicDataflowArchitectureModel/src/tests/UpdateConflictCheckTest.java @@ -11,12 +11,14 @@ import parser.exceptions.ExpectedAssignment; import parser.exceptions.ExpectedChannel; import parser.exceptions.ExpectedChannelName; +import parser.exceptions.ExpectedColon; import parser.exceptions.ExpectedEquals; import parser.exceptions.ExpectedInOrOutOrRefKeyword; import parser.exceptions.ExpectedLeftCurlyBracket; import parser.exceptions.ExpectedRHSExpression; import parser.exceptions.ExpectedRightBracket; import parser.exceptions.ExpectedStateTransition; +import parser.exceptions.WrongJsonExpression; import parser.exceptions.WrongLHSExpression; import parser.exceptions.WrongRHSExpression; @@ -61,6 +63,12 @@ } catch (ExpectedAssignment e) { // TODO Auto-generated catch block e.printStackTrace(); + } catch (WrongJsonExpression e) { + // TODO Auto-generated catch block + e.printStackTrace(); + } catch (ExpectedColon e) { + // TODO Auto-generated catch block + e.printStackTrace(); } } catch (FileNotFoundException e) { e.printStackTrace(); diff --git a/AlgebraicDataflowArchitectureModel/src/tests/controlFlowModel/ControlFlowDelegatorTest.java b/AlgebraicDataflowArchitectureModel/src/tests/controlFlowModel/ControlFlowDelegatorTest.java new file mode 100644 index 0000000..57e4351 --- /dev/null +++ b/AlgebraicDataflowArchitectureModel/src/tests/controlFlowModel/ControlFlowDelegatorTest.java @@ -0,0 +1,26 @@ +package tests.controlFlowModel; + +import org.junit.Test; + +import models.dataConstraintModel.ResourcePath; +import models.dataFlowModel.DataTransferModel; + +import static org.junit.Assert.*; + + +/**-------------------------------------------------------------------------------- + * + */ +public class ControlFlowDelegatorTest { + @Test + public void test() { + // Construct a data-flow architecture model. + DataTransferModel model = new DataTransferModel(); + ResourcePath customer_off = new ResourcePath("customers.{x1}.off", 1); // a resource to specify a customer's office resource + ResourcePath company_add = new ResourcePath("companies.{x2}.add", 1); // a resource to specify a companie's address resource + ResourcePath customer_add = new ResourcePath("customers.{x1}.add", 1); // a resource to specify a customer's address resource + + + + } +} diff --git a/AlgebraicDataflowArchitectureModel/src/tests/parser/ParseTest.java b/AlgebraicDataflowArchitectureModel/src/tests/parser/ParseTest.java index 008d004..0f0e40e 100644 --- a/AlgebraicDataflowArchitectureModel/src/tests/parser/ParseTest.java +++ b/AlgebraicDataflowArchitectureModel/src/tests/parser/ParseTest.java @@ -10,19 +10,21 @@ import models.algebra.ParameterizedIdentifierIsFutureWork; import models.algebra.UnificationFailed; import models.algebra.ValueUndefined; -import models.dataConstraintModel.ChannelGenerator; +import models.dataConstraintModel.Channel; import models.dataConstraintModel.ChannelMember; import models.dataFlowModel.*; import parser.Parser; import parser.exceptions.ExpectedAssignment; import parser.exceptions.ExpectedChannel; import parser.exceptions.ExpectedChannelName; +import parser.exceptions.ExpectedColon; import parser.exceptions.ExpectedEquals; import parser.exceptions.ExpectedInOrOutOrRefKeyword; import parser.exceptions.ExpectedLeftCurlyBracket; import parser.exceptions.ExpectedRHSExpression; import parser.exceptions.ExpectedRightBracket; import parser.exceptions.ExpectedStateTransition; +import parser.exceptions.WrongJsonExpression; import parser.exceptions.WrongLHSExpression; import parser.exceptions.WrongRHSExpression; @@ -37,10 +39,10 @@ model = parser.doParse(); System.out.println(model); - for (ChannelGenerator c: model.getChannelGenerators()) { - for (ChannelMember out: ((DataTransferChannelGenerator) c).getOutputChannelMembers()) { + for (Channel c: model.getChannels()) { + for (ChannelMember out: ((DataTransferChannel) c).getOutputChannelMembers()) { String[] sideEffects = new String[] {""}; - System.out.println("next" + out.getIdentifierTemplate().getResourceName() + " = " + ((DataTransferChannelGenerator) c).deriveUpdateExpressionOf(out).toImplementation(sideEffects)); + System.out.println("next" + out.getResource().getResourceName() + " = " + ((DataTransferChannel) c).deriveUpdateExpressionOf(out).toImplementation(sideEffects)); } } @@ -54,7 +56,7 @@ | ExpectedStateTransition | ExpectedEquals | ExpectedRHSExpression | WrongLHSExpression | WrongRHSExpression | ExpectedRightBracket | ParameterizedIdentifierIsFutureWork | ResolvingMultipleDefinitionIsFutureWork | InvalidMessage - | UnificationFailed | ValueUndefined | ExpectedAssignment e) { + | UnificationFailed | ValueUndefined | ExpectedAssignment | WrongJsonExpression | ExpectedColon e) { e.printStackTrace(); } } catch (FileNotFoundException e) {