diff --git a/AlgebraicDataflowArchitectureModel/src/application/actions/JavaPrototypeGenerateAction.java b/AlgebraicDataflowArchitectureModel/src/application/actions/JavaPrototypeGenerateAction.java index 90bbd0e..92b552b 100644 --- a/AlgebraicDataflowArchitectureModel/src/application/actions/JavaPrototypeGenerateAction.java +++ b/AlgebraicDataflowArchitectureModel/src/application/actions/JavaPrototypeGenerateAction.java @@ -13,9 +13,12 @@ import algorithms.*; import application.editor.Editor; import code.ast.*; +import generators.CodeGenerator; import generators.DataTransferMethodAnalyzer; import generators.JavaCodeGenerator; import generators.JavaMethodBodyGenerator; +import generators.JavaSpecific; +import models.controlFlowModel.ControlFlowGraph; import models.dataConstraintModel.IdentifierTemplate; import models.dataFlowModel.DataTransferModel; import models.dataFlowModel.ModelExtension; @@ -35,16 +38,16 @@ @Override public void actionPerformed(ActionEvent e) { - DataFlowGraph graph = editor.getDataFlowGraph(); - if (graph == null) { + DataFlowGraph dataFlowgraph = editor.getDataFlowGraph(); + if (dataFlowgraph == null) { editor.changeStage(Editor.STAGE_PUSH_PULL_SELECTION); - graph = editor.getDataFlowGraph(); + dataFlowgraph = editor.getDataFlowGraph(); } - if (graph != null) { + if (dataFlowgraph != null) { DataTransferModel model = editor.getModel(); ModelExtension.extendModel(model); TypeInference.infer(model); - DataTransferMethodAnalyzer.decideToStoreResourceStates(graph); + DataTransferMethodAnalyzer.decideToStoreResourceStates(dataFlowgraph); String fileName = editor.getCurFileName(); if (fileName == null) fileName = "Main"; String mainTypeName = fileName.split("\\.")[0]; @@ -56,11 +59,16 @@ } } if (!exist) { - JavaCodeGenerator.setMainTypeName(mainTypeName); // use model's file name as the main type's name. + CodeGenerator.setMainTypeName(mainTypeName); // use model's file name as the main type's name. } else { - JavaCodeGenerator.resetMainTypeName(); // use the default main type's name. + CodeGenerator.resetMainTypeName(); // use the default main type's name. } - editor.setCodes(JavaMethodBodyGenerator.doGenerate(graph, model, JavaCodeGenerator.doGenerate(graph, model))); + ControlFlowGraph controlFlowGraph = editor.getControlFlowGraph(); + if (controlFlowGraph != null) { + editor.setCodes(CodeGenerator.doGenerate(model, controlFlowGraph, new JavaSpecific())); + } else { + editor.setCodes(CodeGenerator.doGenerate(model, dataFlowgraph, new JavaSpecific())); + } ModelExtension.recoverModel(model); for (CompilationUnit file : editor.getCodes()) { System.out.println(file); diff --git a/AlgebraicDataflowArchitectureModel/src/application/editor/Editor.java b/AlgebraicDataflowArchitectureModel/src/application/editor/Editor.java index ab13d4d..9aa7f96 100644 --- a/AlgebraicDataflowArchitectureModel/src/application/editor/Editor.java +++ b/AlgebraicDataflowArchitectureModel/src/application/editor/Editor.java @@ -25,6 +25,7 @@ import application.layouts.*; import code.ast.CompilationUnit; import models.EdgeAttribute; +import models.controlFlowModel.ControlFlowGraph; import models.dataConstraintModel.ChannelGenerator; import models.dataConstraintModel.IdentifierTemplate; import models.dataFlowModel.DataTransferModel; @@ -144,10 +145,19 @@ 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; } diff --git a/AlgebraicDataflowArchitectureModel/src/application/editor/stages/ControlFlowDelegationStage.java b/AlgebraicDataflowArchitectureModel/src/application/editor/stages/ControlFlowDelegationStage.java index 15497b4..a53f4f6 100644 --- a/AlgebraicDataflowArchitectureModel/src/application/editor/stages/ControlFlowDelegationStage.java +++ b/AlgebraicDataflowArchitectureModel/src/application/editor/stages/ControlFlowDelegationStage.java @@ -76,7 +76,7 @@ graph = constructGraph(graph, controlFlowGraph); } } - + /************************************************************* * */ @@ -90,6 +90,10 @@ return null; } + public ControlFlowGraph getControlFlowGraph() { + return controlFlowGraph; + } + /************************************************************* * */ 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/generators/CodeGenerator.java b/AlgebraicDataflowArchitectureModel/src/generators/CodeGenerator.java new file mode 100644 index 0000000..6b1890c --- /dev/null +++ b/AlgebraicDataflowArchitectureModel/src/generators/CodeGenerator.java @@ -0,0 +1,665 @@ +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.controlFlowModel.EntryPointObjectNode; +import models.controlFlowModel.ObjectNode; +import models.controlFlowModel.StatefulObjectNode; +import models.dataConstraintModel.ChannelGenerator; +import models.dataConstraintModel.ChannelMember; +import models.dataConstraintModel.IdentifierTemplate; +import models.dataFlowModel.DataFlowEdge; +import models.dataFlowModel.DataTransferChannelGenerator; +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.DataTransferChannelGenerator.IResourceStateAccessor; + +/** + * Common generator for prototypes + * + * @author Nitta + * + */ +public 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 + */ + static public ArrayList doGenerate(DataTransferModel model, IFlowGraph flowGraph, ILanguageSpecific langSpec) { + ArrayList codes = new ArrayList<>(); + 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); + + // For each of other components. + for (Node componentNode: components) { + // Declare this component. + String componentName = null; + if (componentNode instanceof ResourceNode) { + componentName = langSpec.toComponentName(((ResourceNode) componentNode).getIdentifierTemplate().getResourceName()); + } else if (componentNode instanceof ObjectNode) { + componentName = langSpec.toComponentName(((ObjectNode) componentNode).getName()); + } + TypeDeclaration component = langSpec.newTypeDeclaration(componentName); + + // Declare the constructor and the fields to refer to other resources (to the callee components). + MethodDeclaration constructor = null; + List depends = new ArrayList<>(); + if (componentNode instanceof ResourceNode) { + // For data-flow graph + constructor = declareConstructorAndFieldsToReferToResources((ResourceNode) componentNode, component, depends, langSpec); + } else if (componentNode instanceof ObjectNode) { + // For control-flow graph + constructor = declareConstructorAndFieldsToCalleeComponents((ObjectNode) componentNode, component, depends, langSpec); + } + + // Update the main component for this component. + updateMainComponent(model, mainComponent, mainConstructor, componentNode, depends, langSpec); + + if (componentNode instanceof ResourceNode || componentNode instanceof StatefulObjectNode) { + // For this resource. + ResourceNode resourceNode = null; + if (componentNode instanceof ResourceNode) { + // For data-flow graph + resourceNode = (ResourceNode) componentNode; + } else if (componentNode instanceof StatefulObjectNode) { + // For control-flow graph + resourceNode = ((StatefulObjectNode) componentNode).getResource(); + } + IdentifierTemplate resId = resourceNode.getIdentifierTemplate(); + Type resStateType = resId.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, resId.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, resId, 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); + } + + return codes; + } + + private static ArrayList determineComponentOrder(IFlowGraph graph) { + ArrayList objects = new ArrayList<>(); + Set visited = new HashSet<>(); + Set allNodes = graph.getAllNodes(); + for (Node n: allNodes) { + if (!(n instanceof EntryPointObjectNode)) { + topologicalSort(allNodes, n, visited, objects); + } + } + return objects; + } + + private static void topologicalSort(Set allNodes, Node curNode, Set visited, List orderedList) { + if (visited.contains(curNode)) return; + visited.add(curNode); + // a caller is before the callee + for (Edge e: curNode.getInEdges()) { + if (!(e.getSource() instanceof EntryPointObjectNode)) { + topologicalSort(allNodes, e.getSource(), visited, orderedList); + } + } + // For reference resources. + ResourceNode cn = null; + if (curNode instanceof ResourceNode) { + cn = (ResourceNode) curNode; + } else if (curNode instanceof StatefulObjectNode) { + cn = ((StatefulObjectNode) curNode).getResource(); + } + if (cn != null) { + for (Node n: allNodes) { + 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()) { + DataTransferChannelGenerator ch = ((DataFlowEdge) e).getChannelGenerator(); + for (ChannelMember m: ch.getReferenceChannelMembers()) { + if (m.getIdentifierTemplate() == cn.getIdentifierTemplate()) { + topologicalSort(allNodes, n, visited, orderedList); + } + } + } + } + } + } + orderedList.add(0, curNode); + } + + private static void updateMainComponent(DataTransferModel model, TypeDeclaration mainType, MethodDeclaration mainConstructor, Node componentNode, List depends, 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.getIdentifierTemplate().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<>(); + for (IdentifierTemplate id: depends) { + // For the callee objects (the destination resource of push transfer or the source resource of pull transfer). + parameters.add(id.getResourceName()); + } + // For the refs. + if (resNode != null) { + Set refs = new HashSet<>(); + for (ChannelGenerator cg : model.getChannelGenerators()) { + DataTransferChannelGenerator ch = (DataTransferChannelGenerator) cg; + if (ch.getInputIdentifierTemplates().contains(resNode.getIdentifierTemplate())) { + for (IdentifierTemplate id: ch.getReferenceIdentifierTemplates()) { + if (!refs.contains(id) && !depends.contains(id)) { + refs.add(id); + String refResName = id.getResourceName(); + parameters.add(refResName); + } + } + } + } + } + + 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()); + } + + private static 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); + IdentifierTemplate dstId = ((ResourceNode) e.getDestination()).getIdentifierTemplate(); + 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); + IdentifierTemplate srcId = ((ResourceNode) e.getSource()).getIdentifierTemplate(); + if (!depends.contains(srcId)) depends.add(srcId); + } + } + return constructor; + } + + private static MethodDeclaration declareConstructorAndFieldsToCalleeComponents(ObjectNode componentNode, 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 (Edge e: componentNode.getOutEdges()) { + ObjectNode dstNode = (ObjectNode) e.getDestination(); + addReference(component, constructor, dstNode, langSpec); + if (dstNode instanceof StatefulObjectNode) { + IdentifierTemplate dstId = ((StatefulObjectNode) dstNode).getResource().getIdentifierTemplate(); + if (!depends.contains(dstId)) depends.add(dstId); + } + } + return constructor; + } + + private static void addReference(TypeDeclaration component, MethodDeclaration constructor, Node dstNode, ILanguageSpecific langSpec) { + String dstNodeName = null; + if (dstNode instanceof ResourceNode) { + dstNodeName = ((ResourceNode) dstNode).getIdentifierTemplate().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()); + } + + private static 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()) { + // 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); + } + } else { + // invocations to other getter methods when at least one incoming data-flow edges is PULL-style. + boolean isContainedPush = false; + DataTransferChannelGenerator ch = null; + HashMap inputIdentifierToStateAccessor = new HashMap<>(); + for (Edge eIn: resourceNode.getInEdges()) { + DataFlowEdge dIn = (DataFlowEdge) eIn; + if (((PushPullAttribute) dIn.getAttribute()).getOptions().get(0) == PushPullValue.PUSH) { + // PUSH transfer + isContainedPush = true; + inputIdentifierToStateAccessor.put(((ResourceNode) dIn.getSource()).getIdentifierTemplate(), langSpec.getPushAccessor()); + } else { + // PULL transfer + inputIdentifierToStateAccessor.put(((ResourceNode) dIn.getSource()).getIdentifierTemplate(), langSpec.getPullAccessor()); + ch = dIn.getChannelGenerator(); + } + } + // for reference channel members. + for (ChannelMember c: ch.getReferenceChannelMembers()) { + inputIdentifierToStateAccessor.put(c.getIdentifierTemplate(), langSpec.getPullAccessor()); // by pull data transfer + } + + // generate a return statement. + try { + for (ChannelMember out: ch.getOutputChannelMembers()) { + if (out.getIdentifierTemplate() == resourceNode.getIdentifierTemplate()) { + String[] sideEffects = new String[] {""}; + if (!isContainedPush) { + // All incoming edges are in PULL-style. + String curState = ch.deriveUpdateExpressionOf(out, langSpec.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, langSpec.getPullAccessor(), inputIdentifierToStateAccessor).toImplementation(sideEffects); + getter.addStatement(sideEffects[0] + langSpec.getReturnStatement(curState) + langSpec.getStatementDelimiter()); + } + break; + } + } + } catch (ParameterizedIdentifierIsFutureWork | ResolvingMultipleDefinitionIsFutureWork + | InvalidMessage | UnificationFailed | ValueUndefined e) { + e.printStackTrace(); + } + } + + return getter; + } + + private static void declareAccessorInMainComponent(TypeDeclaration mainComponent, IdentifierTemplate accessResId, ILanguageSpecific langSpec) { + MethodDeclaration getter = new MethodDeclaration("get" + langSpec.toComponentName(accessResId.getResourceName()), accessResId.getResourceStateType()); + Block block = new Block(); + block.addStatement(langSpec.getReturnStatement(langSpec.getMethodInvocation(accessResId.getResourceName(), getterOfResourceState)) + langSpec.getStatementDelimiter()); + getter.setBody(block); + mainComponent.addMethod(getter); + } + + private static void declareFieldsToReferenceResources(DataTransferModel model, ResourceNode resourceNode, TypeDeclaration component, MethodDeclaration constructor, + List depends, ILanguageSpecific langSpec) { + Set refs = new HashSet<>(); + for (ChannelGenerator ch : model.getChannelGenerators()) { + DataTransferChannelGenerator c = (DataTransferChannelGenerator) ch; + if (c.getInputIdentifierTemplates().contains(resourceNode.getIdentifierTemplate())) { + for (IdentifierTemplate id: c.getReferenceIdentifierTemplates()) { + 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()); + } + } + } + } + } + + private static List declareCacheFieldsAndUpdateMethods(ResourceNode resourceNode, TypeDeclaration component, ILanguageSpecific langSpec) { + // Declare cash fields and update methods in the component. + String resComponentName = langSpec.toComponentName(resourceNode.getIdentifierTemplate().getResourceName()); + List updateMethods = new ArrayList<>(); + for (Edge e: resourceNode.getInEdges()) { + DataFlowEdge re = (DataFlowEdge) e; + IdentifierTemplate srcRes = ((ResourceNode) re.getSource()).getIdentifierTemplate(); + 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. + DataTransferChannelGenerator ch = (DataTransferChannelGenerator) re.getChannelGenerator(); + for (IdentifierTemplate ref: ch.getReferenceIdentifierTemplates()) { + if (ref != resourceNode.getIdentifierTemplate()) { + 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.getChannelGenerator().getOutputChannelMembers()) { + if (out.getIdentifierTemplate() == resourceNode.getIdentifierTemplate()) { + Expression updateExp = re.getChannelGenerator().deriveUpdateExpressionOf(out, langSpec.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.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(); + 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()).getIdentifierTemplate().getResourceName()), + updateMethodName + resComponentName, + params) + langSpec.getStatementDelimiter()); // this.dst.updateSrc(value, refParams); + } + } + } + } + return updateMethods; + } + + private static List declareInputMethodsInThisAndMainComponents(ResourceNode resourceNode, TypeDeclaration component, + TypeDeclaration mainComponent, DataTransferModel model, ILanguageSpecific langSpec) { + // Declare input methods. + String resName = resourceNode.getIdentifierTemplate().getResourceName(); + String resComponentName = langSpec.toComponentName(resName); + List inputMethods = new ArrayList<>(); + for (ChannelGenerator ch : model.getIOChannelGenerators()) { + for (ChannelMember out : ((DataTransferChannelGenerator) ch).getOutputChannelMembers()) { + if (out.getIdentifierTemplate().equals(resourceNode.getIdentifierTemplate())) { + 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. + 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 = ((DataTransferChannelGenerator) ch).deriveUpdateExpressionOf(out, langSpec.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: ((DataTransferChannelGenerator) ch).getReferenceChannelMembers()) { + // to get the value of reference member. + IdentifierTemplate ref = rc.getIdentifierTemplate(); + if (referredSet == null) { + referredSet = new HashSet<>(); + referredResources.put(input, 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(); + 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()).getIdentifierTemplate().getResourceName()), + updateMethodName + resComponentName, + params) + langSpec.getStatementDelimiter()); // this.dst.updateSrc(value, refParams); + } + } + } + } + } + } + return inputMethods; + } + + private static MethodDeclaration getMethod(TypeDeclaration component, String methodName) { + for (MethodDeclaration m: component.getMethods()) { + if (m.getName().equals(methodName)) return m; + } + return null; + } +} diff --git a/AlgebraicDataflowArchitectureModel/src/generators/ILanguageSpecific.java b/AlgebraicDataflowArchitectureModel/src/generators/ILanguageSpecific.java new file mode 100644 index 0000000..3b4f817 --- /dev/null +++ b/AlgebraicDataflowArchitectureModel/src/generators/ILanguageSpecific.java @@ -0,0 +1,38 @@ +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.DataTransferChannelGenerator.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, ArrayList parameters); + FieldDeclaration newFieldDeclaration(Type fieldType, String fieldName); + FieldDeclaration newFieldDeclaration(Type fieldType, String fieldName, String fieldInitializer); + String getVariableDeclaration(String typeName, String varName); + String getFieldInitializer(Type type, Expression initialValue); + boolean declareField(); + String getFieldAccessor(String fieldName); + 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 getMainComponentName(); + String getAssignment(); + String getStatementDelimiter(); + boolean isValueType(Type resStateType); + IResourceStateAccessor getPushAccessor(); + IResourceStateAccessor getPullAccessor(); +} diff --git a/AlgebraicDataflowArchitectureModel/src/generators/JavaCodeGenerator.java b/AlgebraicDataflowArchitectureModel/src/generators/JavaCodeGenerator.java index 74ed6a8..5af38f1 100644 --- a/AlgebraicDataflowArchitectureModel/src/generators/JavaCodeGenerator.java +++ b/AlgebraicDataflowArchitectureModel/src/generators/JavaCodeGenerator.java @@ -76,8 +76,7 @@ // 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 = toTypeName(rn.getIdentifierTemplate().getResourceName()); TypeDeclaration type = new TypeDeclaration(resourceName); // Declare the field to refer to each resource in the main type. @@ -86,7 +85,7 @@ for (Edge e : rn.getOutEdges()) { DataFlowEdge re = (DataFlowEdge) e; IdentifierTemplate dstRes = ((ResourceNode) re.getDestination()).getIdentifierTemplate(); - String resName = dstRes.getResourceName().substring(0, 1).toUpperCase() + dstRes.getResourceName().substring(1); + String resName = toTypeName(dstRes.getResourceName()); if (((PushPullAttribute) re.getAttribute()).getOptions().get(0) == PushPullValue.PUSH) { depends.add(dstRes); fieldInitializer += resName.toLowerCase() + ","; @@ -96,17 +95,16 @@ for (Edge e : rn.getInEdges()) { DataFlowEdge re = (DataFlowEdge) e; IdentifierTemplate srcRes = ((ResourceNode) re.getSource()).getIdentifierTemplate(); - String resName = srcRes.getResourceName().substring(0, 1).toUpperCase() + srcRes.getResourceName().substring(1); + String resName = toTypeName(srcRes.getResourceName()); if (((PushPullAttribute) re.getAttribute()).getOptions().get(0) != PushPullValue.PUSH) { depends.add(srcRes); fieldInitializer += resName.toLowerCase() + ","; f = true; } 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(); - type.addField(new FieldDeclaration( - cashResId.getResourceStateType(), ((ResourceNode) re.getSource()).getIdentifierTemplate().getResourceName(), getInitializer(cashResId))); + // Declare a field to cache the state of the source resource in the type of the destination resource. + IdentifierTemplate cacheResId = ((ResourceNode) re.getSource()).getIdentifierTemplate(); + type.addField(new FieldDeclaration(cacheResId.getResourceStateType(), cacheResId.getResourceName(), getInitializer(cacheResId))); } } } @@ -128,12 +126,14 @@ fieldInitializer += ")"; FieldDeclaration field = new FieldDeclaration(new Type(resourceName, resourceName), rn.getIdentifierTemplate().getResourceName()); mainType.addField(field); - Block manConstructorBody = mainConstructor.getBody(); - if (manConstructorBody == null) { - manConstructorBody = new Block(); - mainConstructor.setBody(manConstructorBody); + + // Add a statement to instantiate each object to the main constructor. + Block mainConstructorBody = mainConstructor.getBody(); + if (mainConstructorBody == null) { + mainConstructorBody = new Block(); + mainConstructor.setBody(mainConstructorBody); } - manConstructorBody.addStatement(rn.getIdentifierTemplate().getResourceName() + " = " + fieldInitializer + ";"); + mainConstructorBody.addStatement(rn.getIdentifierTemplate().getResourceName() + " = " + fieldInitializer + ";"); // Declare a constructor, fields and update methods in the type of each resource. MethodDeclaration constructor = new MethodDeclaration(resourceName, true); @@ -142,7 +142,7 @@ for (Edge e : rn.getOutEdges()) { DataFlowEdge re = (DataFlowEdge) e; IdentifierTemplate dstRes = ((ResourceNode) re.getDestination()).getIdentifierTemplate(); - String dstResName = dstRes.getResourceName().substring(0, 1).toUpperCase() + dstRes.getResourceName().substring(1); + String dstResName = toTypeName(dstRes.getResourceName()); if (((PushPullAttribute) re.getAttribute()).getOptions().get(0) == PushPullValue.PUSH) { // Declare a field to refer to the destination resource of push transfer. depends.add(dstRes); @@ -154,7 +154,7 @@ for (Edge e : rn.getInEdges()) { DataFlowEdge re = (DataFlowEdge) e; IdentifierTemplate srcRes = ((ResourceNode) re.getSource()).getIdentifierTemplate(); - String srcResName = srcRes.getResourceName().substring(0, 1).toUpperCase() + srcRes.getResourceName().substring(1); + String srcResName = toTypeName(srcRes.getResourceName()); if (((PushPullAttribute) re.getAttribute()).getOptions().get(0) != PushPullValue.PUSH) { // Declare a field to refer to the source resource of pull transfer. depends.add(srcRes); @@ -183,7 +183,7 @@ if (!refs.contains(id) && !depends.contains(id)) { refs.add(id); String refResName = id.getResourceName(); - refResName = refResName.substring(0, 1).toUpperCase() + refResName.substring(1); + refResName = toTypeName(refResName); 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() + ";"); @@ -200,16 +200,16 @@ for (ChannelMember cm : ((DataTransferChannelGenerator) cg).getOutputChannelMembers()) { if (cm.getIdentifierTemplate().equals(rn.getIdentifierTemplate())) { 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())); } MethodDeclaration input = new MethodDeclaration( - ((Term) cm.getStateTransition().getMessageExpression()).getSymbol().getImplName(), + ((Term) message).getSymbol().getImplName(), false, typeVoid, params); type.addMethod(input); - String str = ((Term) cm.getStateTransition().getMessageExpression()).getSymbol().getImplName(); + String str = ((Term) message).getSymbol().getImplName(); input = getMethod(mainType, str); if (input == null) { input = new MethodDeclaration(str, false, typeVoid, params); @@ -226,15 +226,13 @@ } } } - } else if (message.getClass() == Variable.class) { - MethodDeclaration input = new MethodDeclaration( - ((Variable) cm.getStateTransition().getMessageExpression()).getName(), - false, typeVoid, null); + } else if (message instanceof Variable) { + MethodDeclaration input = new MethodDeclaration(((Variable) message).getName(), typeVoid); type.addMethod(input); - String str = ((Variable) cm.getStateTransition().getMessageExpression()).getName(); + String str = ((Variable) message).getName(); input = getMethod(mainType, str); if (input == null) { - input = new MethodDeclaration(str, false, typeVoid, null); + input = new MethodDeclaration(str, typeVoid); mainType.addMethod(input); } } @@ -278,7 +276,7 @@ for(FieldDeclaration field : type.getFields()) { MethodDeclaration getter = new MethodDeclaration( - "get" + field.getName().substring(0,1).toUpperCase() + field.getName().substring(1), + "get" + toTypeName(field.getName()), new Type("Double","T")); getter.setBody(new Block()); getter.getBody().addStatement("return " + field.getName() + ";"); @@ -297,8 +295,7 @@ 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), + "get" + toTypeName(rn.getIdentifierTemplate().getResourceName()), rn.getIdentifierTemplate().getResourceStateType()); getter.setBody(new Block()); getter.getBody().addStatement( @@ -306,7 +303,7 @@ mainType.addMethod(getter); } - + // ????? HashSet tmps = new HashSet<>(); HashSet cont = new HashSet<>(); for (MethodDeclaration method : mainType.getMethods()) { @@ -317,23 +314,26 @@ } for (MethodDeclaration method : mainType.getMethods()) { if (cont.contains(method.getName())) { - method.setName(method.getName() + method.getParameters().get(0).getName().substring(0, 1).toUpperCase() - + method.getParameters().get(0).getName().substring(1)); + method.setName(method.getName() + toTypeName(method.getParameters().get(0).getName())); } } return codes; } - private static String getInitializer(IdentifierTemplate resId) { + private static String toTypeName(String resName) { + return resName.substring(0, 1).toUpperCase() + resName.substring(1); + } + + static private String getInitializer(IdentifierTemplate resId) { Type stateType = resId.getResourceStateType(); String initializer = null; if (resId.getInitialValue() != null) { initializer = resId.getInitialValue().toImplementation(new String[] {""}); } else { if (DataConstraintModel.typeList.isAncestorOf(stateType)) { - initializer = "new " + resId.getResourceStateType().getImplementationTypeName() + "()"; + initializer = "new " + stateType.getImplementationTypeName() + "()"; } else if (DataConstraintModel.typeMap.isAncestorOf(stateType)) { - initializer = "new " + resId.getResourceStateType().getImplementationTypeName() + "()"; + initializer = "new " + stateType.getImplementationTypeName() + "()"; } } return initializer; diff --git a/AlgebraicDataflowArchitectureModel/src/generators/JavaMethodBodyGenerator.java b/AlgebraicDataflowArchitectureModel/src/generators/JavaMethodBodyGenerator.java index ec17706..a6f7dd8 100644 --- a/AlgebraicDataflowArchitectureModel/src/generators/JavaMethodBodyGenerator.java +++ b/AlgebraicDataflowArchitectureModel/src/generators/JavaMethodBodyGenerator.java @@ -79,7 +79,7 @@ } } if (dst.getIndegree() > 1) { - // update a cash of src side resource (when incoming edges are multiple) + // update a cache of src side resource (when incoming edges are multiple) String cashStatement = "this." + srcResourceName + " = " + srcResourceName + ";"; if (update.getBody() == null || !update.getBody().getStatements().contains(cashStatement)) { update.addFirstStatement(cashStatement); diff --git a/AlgebraicDataflowArchitectureModel/src/generators/JavaSpecific.java b/AlgebraicDataflowArchitectureModel/src/generators/JavaSpecific.java new file mode 100644 index 0000000..ac4715c --- /dev/null +++ b/AlgebraicDataflowArchitectureModel/src/generators/JavaSpecific.java @@ -0,0 +1,224 @@ +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.Field; +import models.algebra.Parameter; +import models.algebra.Symbol; +import models.algebra.Term; +import models.algebra.Type; +import models.dataConstraintModel.DataConstraintModel; +import models.dataConstraintModel.IdentifierTemplate; +import models.dataFlowModel.DataTransferChannelGenerator.IResourceStateAccessor; + +public class JavaSpecific implements ILanguageSpecific { + public static final Type typeVoid = new Type("Void", "void"); + + @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, ArrayList 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 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 "this." + fieldName; + } + + @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 getMainComponentName() { + return "Main"; + } + + @Override + public String getAssignment() { + return " = "; + } + + @Override + public String getStatementDelimiter() { + return ";"; + } + + @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 IResourceStateAccessor getPushAccessor() { + return new IResourceStateAccessor() { + @Override + public Expression getCurrentStateAccessorFor(IdentifierTemplate target, IdentifierTemplate from) { + if (target.equals(from)) { + return new Field(CodeGenerator.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(IdentifierTemplate target, IdentifierTemplate from) { + return new Parameter(target.getResourceName(), + target.getResourceStateType() != null ? target.getResourceStateType() + : DataConstraintModel.typeInt); + } + }; + } + + @Override + public IResourceStateAccessor getPullAccessor() { + return new IResourceStateAccessor() { + @Override + public Expression getCurrentStateAccessorFor(IdentifierTemplate target, IdentifierTemplate from) { + if (target.equals(from)) { + return new Field(CodeGenerator.fieldOfResourceState, + target.getResourceStateType() != null ? target.getResourceStateType() + : DataConstraintModel.typeInt); + } + // for reference channel member + Term getter = new Term(new Symbol(CodeGenerator.getterOfResourceState, 1, Symbol.Type.METHOD)); + getter.addChild(new Field(target.getResourceName(), target.getResourceStateType())); + return getter; + } + + @Override + public Expression getNextStateAccessorFor(IdentifierTemplate target, IdentifierTemplate from) { + Term getter = new Term(new Symbol(CodeGenerator.getterOfResourceState, 1, Symbol.Type.METHOD)); + getter.addChild(new Field(target.getResourceName(), target.getResourceStateType())); + return getter; + } + }; + } + +} diff --git a/AlgebraicDataflowArchitectureModel/src/models/controlFlowModel/ControlFlowGraph.java b/AlgebraicDataflowArchitectureModel/src/models/controlFlowModel/ControlFlowGraph.java index 0ebaaa2..5d4b77e 100644 --- a/AlgebraicDataflowArchitectureModel/src/models/controlFlowModel/ControlFlowGraph.java +++ b/AlgebraicDataflowArchitectureModel/src/models/controlFlowModel/ControlFlowGraph.java @@ -1,6 +1,10 @@ package models.controlFlowModel; +import java.util.HashSet; +import java.util.Set; + import models.Edge; +import models.Node; import models.algebra.Expression; import models.algebra.Term; import models.algebra.Variable; @@ -10,11 +14,12 @@ import models.dataFlowModel.DataFlowGraph; import models.dataFlowModel.DataTransferChannelGenerator; import models.dataFlowModel.DataTransferModel; +import models.dataFlowModel.IFlowGraph; import models.dataFlowModel.PushPullAttribute; import models.dataFlowModel.PushPullValue; import models.dataFlowModel.ResourceNode; -public class ControlFlowGraph { +public class ControlFlowGraph implements IFlowGraph { private DataFlowGraph dataFlowGraph; private CallGraph pushCallGraph; private CallGraph pullCallGraph; @@ -101,4 +106,12 @@ public CallGraph getPullCallGraph() { return pullCallGraph; } + + @Override + public Set getAllNodes() { + Set allNodes = new HashSet<>(); + allNodes.addAll(pushCallGraph.getNodes()); + allNodes.addAll(pullCallGraph.getNodes()); + return allNodes; + } } diff --git a/AlgebraicDataflowArchitectureModel/src/models/controlFlowModel/ObjectNode.java b/AlgebraicDataflowArchitectureModel/src/models/controlFlowModel/ObjectNode.java index 53d7459..9303eb3 100644 --- a/AlgebraicDataflowArchitectureModel/src/models/controlFlowModel/ObjectNode.java +++ b/AlgebraicDataflowArchitectureModel/src/models/controlFlowModel/ObjectNode.java @@ -9,7 +9,7 @@ /************************************************************* * */ -public class ObjectNode extends Node{ +public class ObjectNode extends Node { protected String name = ""; /************************************************************* diff --git a/AlgebraicDataflowArchitectureModel/src/models/controlFlowModel/ObjectNodeAttribute.java b/AlgebraicDataflowArchitectureModel/src/models/controlFlowModel/ObjectNodeAttribute.java index 0a5efa9..da80d92 100644 --- a/AlgebraicDataflowArchitectureModel/src/models/controlFlowModel/ObjectNodeAttribute.java +++ b/AlgebraicDataflowArchitectureModel/src/models/controlFlowModel/ObjectNodeAttribute.java @@ -7,7 +7,7 @@ * @author k-fujii * */ -public class ObjectNodeAttribute extends NodeAttribute{ +public class ObjectNodeAttribute extends NodeAttribute { private ObjectNode objectNode = null; private String shapeStyle = ""; diff --git a/AlgebraicDataflowArchitectureModel/src/models/dataFlowModel/DataFlowGraph.java b/AlgebraicDataflowArchitectureModel/src/models/dataFlowModel/DataFlowGraph.java index dde47b2..f315047 100644 --- a/AlgebraicDataflowArchitectureModel/src/models/dataFlowModel/DataFlowGraph.java +++ b/AlgebraicDataflowArchitectureModel/src/models/dataFlowModel/DataFlowGraph.java @@ -3,11 +3,13 @@ import java.util.Collection; import java.util.HashMap; import java.util.Map; +import java.util.Set; import models.DirectedGraph; +import models.Node; import models.dataConstraintModel.IdentifierTemplate; -public class DataFlowGraph extends DirectedGraph { +public class DataFlowGraph extends DirectedGraph implements IFlowGraph { protected Map nodeMap = null; public DataFlowGraph() { @@ -47,4 +49,9 @@ if(nodeMap.get(identifierTemplate) == null) throw new NullPointerException(identifierTemplate.getResourceName() + "was not found."); return nodeMap.get(identifierTemplate); } + + @Override + public Set getAllNodes() { + return super.getNodes(); + } } diff --git a/AlgebraicDataflowArchitectureModel/src/models/dataFlowModel/IFlowGraph.java b/AlgebraicDataflowArchitectureModel/src/models/dataFlowModel/IFlowGraph.java new file mode 100644 index 0000000..141c81f --- /dev/null +++ b/AlgebraicDataflowArchitectureModel/src/models/dataFlowModel/IFlowGraph.java @@ -0,0 +1,9 @@ +package models.dataFlowModel; + +import java.util.Set; + +import models.Node; + +public interface IFlowGraph { + abstract public Set getAllNodes(); +}