diff --git a/AlgebraicDataflowArchitectureModel/src/generators/CodeGenerator.java b/AlgebraicDataflowArchitectureModel/src/generators/CodeGenerator.java index ae548ee..d1cb9de 100644 --- a/AlgebraicDataflowArchitectureModel/src/generators/CodeGenerator.java +++ b/AlgebraicDataflowArchitectureModel/src/generators/CodeGenerator.java @@ -93,10 +93,18 @@ // map or list. if (DataConstraintModel.typeList.isAncestorOf(res.getResourceStateType())) { // list. - return langSpec.newListType(getComponentName(child, langSpec)); + if (generatesComponent(child)) { + return langSpec.newListType(getComponentName(child, langSpec)); + } else { + return langSpec.newListType(getImplStateType(child, langSpec).getImplementationTypeName()); + } } else if (DataConstraintModel.typeMap.isAncestorOf(res.getResourceStateType())) { // map. - return langSpec.newMapType(DataConstraintModel.typeString, getComponentName(child, langSpec)); + if (generatesComponent(child)) { + return langSpec.newMapType(DataConstraintModel.typeString, getComponentName(child, langSpec)); + } else { + return langSpec.newMapType(DataConstraintModel.typeString, getImplStateType(child, langSpec).getImplementationTypeName()); + } } return null; } else { @@ -105,6 +113,12 @@ } } } + + public static boolean generatesComponent(ResourceHierarchy res) { + return res.getParent() == null || !(res.getChildren() == null || res.getChildren().size() == 0); +// Type resType = res.getResourceStateType(); +// return DataConstraintModel.typeJson.isAncestorOf(resType) || DataConstraintModel.typeList.isAncestorOf(resType) || DataConstraintModel.typeMap.isAncestorOf(resType); + } /** * Generate source codes in specified language from data-flow/control-flow graph. @@ -336,23 +350,23 @@ } protected void declareAccessorInMainComponent(TypeDeclaration mainComponent, ResourceNode accessRes, MethodDeclaration stateGetter, ILanguageSpecific langSpec) { - List mainParams = new ArrayList<>(); + List mainGetterParams = new ArrayList<>(); int v = 1; for (Selector selector: accessRes.getAllSelectors()) { if (selector.getExpression() instanceof Variable) { Variable var = (Variable) selector.getExpression(); - mainParams.add(langSpec.newVariableDeclaration(var.getType(), var.getName())); + mainGetterParams.add(langSpec.newVariableDeclaration(var.getType(), var.getName())); } else if (selector.getExpression() instanceof Term) { Term var = (Term) selector.getExpression(); - mainParams.add(new VariableDeclaration(var.getType(), "v" + v)); + mainGetterParams.add(new VariableDeclaration(var.getType(), "v" + v)); } v++; } MethodDeclaration accessor = null; - if (mainParams.size() == 0) { + if (mainGetterParams.size() == 0) { accessor = langSpec.newMethodDeclaration(getterPrefix + getComponentName(accessRes.getResourceHierarchy(), langSpec), getImplStateType(accessRes.getResourceHierarchy(), langSpec)); } else { - accessor = langSpec.newMethodDeclaration(getterPrefix + getComponentName(accessRes.getResourceHierarchy(), langSpec), false, getImplStateType(accessRes.getResourceHierarchy(), langSpec), mainParams); + accessor = langSpec.newMethodDeclaration(getterPrefix + getComponentName(accessRes.getResourceHierarchy(), langSpec), false, getImplStateType(accessRes.getResourceHierarchy(), langSpec), mainGetterParams); } Block block = new Block(); Expression getState = JavaCodeGenerator.pullAccessor.getCurrentStateAccessorFor(accessRes.getOutSideResource(), null); @@ -500,8 +514,7 @@ } } - if (target.getResourceHierarchy().getNumParameters() > 0 - || (target.getResourceHierarchy().getChildren() != null && target.getResourceHierarchy().getChildren().size() > 0)) { + if (generatesComponent(target.getResourceHierarchy())) { Term newGetter = new Term(new Symbol(getterOfResourceState, 1, Symbol.Type.METHOD)); newGetter.addChild(getter); getter = newGetter; diff --git a/AlgebraicDataflowArchitectureModel/src/generators/CodeGeneratorFromDataFlowGraph.java b/AlgebraicDataflowArchitectureModel/src/generators/CodeGeneratorFromDataFlowGraph.java index 3f05ff0..5e43545 100644 --- a/AlgebraicDataflowArchitectureModel/src/generators/CodeGeneratorFromDataFlowGraph.java +++ b/AlgebraicDataflowArchitectureModel/src/generators/CodeGeneratorFromDataFlowGraph.java @@ -1,5 +1,6 @@ package generators; +import java.util.AbstractMap; import java.util.ArrayList; import java.util.HashMap; import java.util.HashSet; @@ -47,79 +48,87 @@ public void generateCodeFromFlowGraph(DataTransferModel model, DataFlowGraph flowGraph, ArrayList components, TypeDeclaration mainComponent, MethodDeclaration mainConstructor, ArrayList codes, ILanguageSpecific langSpec) { + Map resourceComponents = new HashMap<>(); + List> getters = new ArrayList<>(); + List> inputs = new ArrayList<>(); + // For each components. for (Node componentNode: components) { // Declare this resource. ResourceNode resourceNode = (ResourceNode) componentNode; - if (resourceNode.getResourceHierarchy().getChildren().size() == 0 && resourceNode.getResourceHierarchy().getNumParameters() == 0) { - // No component is created for a simple leaf resource. - continue; - } - - String resourceName = getComponentName(resourceNode.getResourceHierarchy(), langSpec); - TypeDeclaration component = getComponent(resourceName, codes); - List depends = new ArrayList<>(); - if (component == null) { - // Add compilation unit for this component. - component = langSpec.newTypeDeclaration(resourceName); - CompilationUnit cu = langSpec.newCompilationUnit(component); - codes.add(cu); - - if (resourceNode.getResourceHierarchy().getParent() == null) { - // For each root resource - // Declare the constructor and the fields to refer to other resources. - MethodDeclaration constructor = declareConstructorAndFieldsToReferToResources(resourceNode, component, depends, langSpec); + Type resStateType = getImplStateType(resourceNode.getResourceHierarchy(), langSpec); + TypeDeclaration component = null; + if (generatesComponent(resourceNode.getResourceHierarchy())) { + // A component will be generated for this resource. + String resourceName = getComponentName(resourceNode.getResourceHierarchy(), langSpec); + component = resourceComponents.get(resourceNode.getResourceHierarchy()); + List depends = new ArrayList<>(); + if (component == null) { + // Add compilation unit for this component. + component = langSpec.newTypeDeclaration(resourceName); + resourceComponents.put(resourceNode.getResourceHierarchy(), component); + CompilationUnit cu = langSpec.newCompilationUnit(component); + codes.add(cu); - // Update the main component for this component. - updateMainComponent(model, mainComponent, mainConstructor, componentNode, depends, langSpec); - - // Declare the fields to refer to reference resources. - declareFieldsToReferenceResources(model, resourceNode, component, constructor, depends, langSpec); - - if (constructor.getParameters() == null) { - component.removeMethod(constructor); + if (resourceNode.getResourceHierarchy().getParent() == null) { + // For each root resource + // Declare the constructor and the fields to refer to other resources. + MethodDeclaration constructor = declareConstructorAndFieldsToReferToResources(resourceNode, component, depends, langSpec); + + // Update the main component for this component. + updateMainComponent(model, mainComponent, mainConstructor, componentNode, depends, langSpec); + + // Declare the fields to refer to reference resources. + declareFieldsToReferenceResources(model, resourceNode, component, constructor, depends, langSpec); + + if (constructor.getParameters() == null) { + component.removeMethod(constructor); + } } } + + // Declare the field in this resource to store the state. + if (((StoreAttribute) resourceNode.getAttribute()).isStored()) { + declareStateField(resourceNode, component, resStateType, langSpec); + } + + // Declare the getter methods in this resource to obtain the children resources. + declareChildGetterMethod(resourceNode, component, langSpec); + + // Declare cache fields and update methods in this resource. + List updates = declareCacheFieldsAndUpdateMethods(resourceNode, component, langSpec); } - - Type resStateType = getImplStateType(resourceNode.getResourceHierarchy(), langSpec); - - // Declare the field in this resource to store the state. - if (((StoreAttribute) resourceNode.getAttribute()).isStored()) { - declareStateField(resourceNode, component, resStateType, langSpec); - } - // Declare the getter method in this resource to obtain the state. MethodDeclaration stateGetter = declareStateGetterMethod(resourceNode, component, resStateType, langSpec); - - // Declare the getter methods in this resource to obtain children of the resource. - declareChildGetterMethod(resourceNode, component, langSpec); + if (component == null) { + // stateGetter was not added to any component because no component had been generated. + getters.add(new AbstractMap.SimpleEntry(resourceNode.getResourceHierarchy().getParent(), stateGetter)); + } // Declare the accessor method in the main component to call the getter method. declareAccessorInMainComponent(mainComponent, resourceNode, stateGetter, 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); + List inputMethods = declareInputMethodsInThisAndMainComponents(resourceNode, component, mainComponent, model, langSpec); + if (component == null) { + // inputMethods were not added to any component because no component had been generated. + for (MethodDeclaration in: inputMethods) { + inputs.add(new AbstractMap.SimpleEntry(resourceNode.getResourceHierarchy().getParent(), in)); + } + } + } + + // Add leaf getter methods to the parent components. + for (Map.Entry entry: getters) { + resourceComponents.get(entry.getKey()).addMethod(entry.getValue()); + } + + // Add leaf input methods to the parent components. + for (Map.Entry entry: inputs) { + resourceComponents.get(entry.getKey()).addMethod(entry.getValue()); } } - private TypeDeclaration getComponent(String resourceName, ArrayList codes) { - TypeDeclaration component = null; - for (CompilationUnit cu: codes) { - for (TypeDeclaration comp: cu.types()) { - if (resourceName.equals(comp.getTypeName())) { - component = comp; - break; - } - } - if (component != null) break; - } - return component; - } - private MethodDeclaration declareConstructorAndFieldsToReferToResources(ResourceNode resourceNode, TypeDeclaration component, List depends, ILanguageSpecific langSpec) { // Declare a constructor in each component. @@ -186,95 +195,120 @@ private MethodDeclaration declareStateGetterMethod(ResourceNode resourceNode, TypeDeclaration component, Type resStateType, ILanguageSpecific langSpec) { // Declare the getter method of the resource state. - MethodDeclaration stateGetter = langSpec.newMethodDeclaration(getterOfResourceState, resStateType); - component.addMethod(stateGetter); + MethodDeclaration stateGetter = null; + if (component != null) { + // A component is created for this resource. + stateGetter = langSpec.newMethodDeclaration(getterOfResourceState, resStateType); + component.addMethod(stateGetter); + } else { + // No component is created for this resource. + List getterParams = new ArrayList<>(); + int v = 1; + for (Selector param: resourceNode.getSelectors()) { + if (param.getExpression() instanceof Variable) { + Variable var = (Variable) param.getExpression(); + getterParams.add(new VariableDeclaration(var.getType(), var.getName())); + } else if (param.getExpression() instanceof Term) { + Term var = (Term) param.getExpression(); + getterParams.add(new VariableDeclaration(var.getType(), "v" + v)); + } + v++; + } + String resCompName = getComponentName(resourceNode.getResourceHierarchy(), langSpec); + if (getterParams.size() == 0) { + stateGetter = new MethodDeclaration(getterPrefix + resCompName, resStateType); + } else { + stateGetter = new MethodDeclaration(getterPrefix + resCompName, false, resStateType, getterParams); + } + } - if (((StoreAttribute) resourceNode.getAttribute()).isStored()) { - fillStateGetterMethod(stateGetter, resourceNode.getResourceHierarchy(), 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 chToRes: resourceNode.getInEdges()) { - for (Edge resToCh: chToRes.getSource().getInEdges()) { - DataFlowEdge dIn = (DataFlowEdge) resToCh; - if (((PushPullAttribute) dIn.getAttribute()).getOptions().get(0) == PushPullValue.PUSH) { - // PUSH transfer - isContainedPush = true; - inputResourceToStateAccessor.put(((ResourceNode) resToCh.getSource()).getOutSideResource(), getPushAccessor()); - } else { - // PULL transfer - inputResourceToStateAccessor.put(((ResourceNode) resToCh.getSource()).getOutSideResource(), getPullAccessor()); - ch = ((ChannelNode) resToCh.getDestination()).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 (resourceNode.getInSideResources().contains(out.getResource())) { - String[] sideEffects = new String[] {""}; - if (!isContainedPush) { - // All incoming edges are in PULL-style. - String curState = ch.deriveUpdateExpressionOf(out, getPullAccessor()).toImplementation(sideEffects); - stateGetter.addStatement(sideEffects[0] + langSpec.getReturnStatement(curState) + langSpec.getStatementDelimiter()); + if (component != null) { + // A component is created for this resource. + if (((StoreAttribute) resourceNode.getAttribute()).isStored()) { + fillStateGetterMethod(stateGetter, resourceNode.getResourceHierarchy(), 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 chToRes: resourceNode.getInEdges()) { + for (Edge resToCh: chToRes.getSource().getInEdges()) { + DataFlowEdge dIn = (DataFlowEdge) resToCh; + if (((PushPullAttribute) dIn.getAttribute()).getOptions().get(0) == PushPullValue.PUSH) { + // PUSH transfer + isContainedPush = true; + inputResourceToStateAccessor.put(((ResourceNode) resToCh.getSource()).getOutSideResource(), getPushAccessor()); } else { - // At least one incoming edge is in PUSH-style. - String curState = ch.deriveUpdateExpressionOf(out, getPullAccessor(), inputResourceToStateAccessor).toImplementation(sideEffects); - stateGetter.addStatement(sideEffects[0] + langSpec.getReturnStatement(curState) + langSpec.getStatementDelimiter()); + // PULL transfer + inputResourceToStateAccessor.put(((ResourceNode) resToCh.getSource()).getOutSideResource(), getPullAccessor()); + ch = ((ChannelNode) resToCh.getDestination()).getChannel(); } - break; } } - } catch (ParameterizedIdentifierIsFutureWork | ResolvingMultipleDefinitionIsFutureWork - | InvalidMessage | UnificationFailed | ValueUndefined e) { - e.printStackTrace(); + // 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 (resourceNode.getInSideResources().contains(out.getResource())) { + String[] sideEffects = new String[] {""}; + if (!isContainedPush) { + // All incoming edges are in PULL-style. + String curState = ch.deriveUpdateExpressionOf(out, getPullAccessor()).toImplementation(sideEffects); + stateGetter.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); + stateGetter.addStatement(sideEffects[0] + langSpec.getReturnStatement(curState) + langSpec.getStatementDelimiter()); + } + break; + } + } + } catch (ParameterizedIdentifierIsFutureWork | ResolvingMultipleDefinitionIsFutureWork + | InvalidMessage | UnificationFailed | ValueUndefined e) { + e.printStackTrace(); + } } + } else { + // No component is created for this resource. + fillChildGetterMethod(stateGetter, resourceNode.getResourceHierarchy(), resourceNode.getResourceHierarchy().getParent().getResourceStateType(), langSpec); } return stateGetter; } private void declareChildGetterMethod(ResourceNode resourceNode, TypeDeclaration component, ILanguageSpecific langSpec) { - // Declare the getter methods in this resource to obtain children of the resource. + // Declare the getter methods in this resource to obtain the children resources. for (ResourceNode child: resourceNode.getChildren()) { - List pathParams = new ArrayList<>(); - int v = 1; - for (Selector pathParam: child.getSelectors()) { - if (pathParam.getExpression() instanceof Variable) { - Variable var = (Variable) pathParam.getExpression(); - pathParams.add(langSpec.newVariableDeclaration(var.getType(), var.getName())); - } else if (pathParam.getExpression() instanceof Term) { - Term var = (Term) pathParam.getExpression(); - pathParams.add(langSpec.newVariableDeclaration(var.getType(), "v" + v)); + if (generatesComponent(child.getResourceHierarchy())) { + // A component is generated for the child. + List params = new ArrayList<>(); + int v = 1; + for (Selector param: child.getSelectors()) { + if (param.getExpression() instanceof Variable) { + Variable var = (Variable) param.getExpression(); + params.add(langSpec.newVariableDeclaration(var.getType(), var.getName())); + } else if (param.getExpression() instanceof Term) { + Term var = (Term) param.getExpression(); + params.add(langSpec.newVariableDeclaration(var.getType(), "v" + v)); + } + v++; } - v++; + String childCompName = getComponentName(child.getResourceHierarchy(), langSpec); + Type childType = new Type(childCompName, childCompName); + MethodDeclaration childGetter = null; + if (params.size() == 0) { + childGetter = langSpec.newMethodDeclaration(getterPrefix + childCompName, childType); + } else { + childGetter = langSpec.newMethodDeclaration(getterPrefix + childCompName, false, childType, params); + } + + fillChildGetterMethod(childGetter, child.getResourceHierarchy(), resourceNode.getResourceStateType(), langSpec); + component.addMethod(childGetter); } - String childTypeName = getComponentName(child.getResourceHierarchy(), langSpec); - Type childType = null; - if ((child.getResourceHierarchy().getChildren() == null || child.getResourceHierarchy().getChildren().size() == 0) - && child.getResourceHierarchy().getNumParameters() == 0) { - // The child does not have a component. - childType = child.getResourceStateType(); - } else { - // The child has a component. - childType = new Type(childTypeName, childTypeName); - } - MethodDeclaration childGetter = null; - if (pathParams.size() == 0) { - childGetter = langSpec.newMethodDeclaration(getterPrefix + childTypeName, childType); - } else { - childGetter = langSpec.newMethodDeclaration(getterPrefix + childTypeName, false, childType, pathParams); - } - - fillChildGetterMethod(childGetter, child.getResourceHierarchy(), resourceNode.getResourceStateType(), langSpec); - component.addMethod(childGetter); } } @@ -403,37 +437,61 @@ if (resourceNode.getInSideResources().contains(out.getResource())) { Expression message = out.getStateTransition().getMessageExpression(); MethodDeclaration input = null; - MethodDeclaration mainInput = null; + MethodDeclaration inputAccessor = null; if (message instanceof Term) { // Declare an input method in this component. - ArrayList resParams = new ArrayList<>(); - ArrayList mainParams = new ArrayList<>(); - for (Selector selector: resourceNode.getAllSelectors()) { + ArrayList resInputParams = new ArrayList<>(); + ArrayList mainInputParams = new ArrayList<>(); + int v = 1; + for (Selector selector: resourceNode.getSelectors()) { if (selector.getExpression() instanceof Variable) { Variable var = (Variable) selector.getExpression(); - mainParams.add(new VariableDeclaration(var.getType(), var.getName())); + resInputParams.add(langSpec.newVariableDeclaration(var.getType(), var.getName())); + mainInputParams.add(langSpec.newVariableDeclaration(var.getType(), var.getName())); + } else if (selector.getExpression() instanceof Term) { + Term var = (Term) selector.getExpression(); + resInputParams.add(langSpec.newVariableDeclaration(var.getType(), "v" + v)); + mainInputParams.add(langSpec.newVariableDeclaration(var.getType(), "v" + v)); + } + v++; + } + if (resourceNode.getParent() != null) { + for (Selector selector: resourceNode.getParent().getAllSelectors()) { + if (selector.getExpression() instanceof Variable) { + Variable var = (Variable) selector.getExpression(); + mainInputParams.add(langSpec.newVariableDeclaration(var.getType(), var.getName())); + } else if (selector.getExpression() instanceof Term) { + Term var = (Term) selector.getExpression(); + mainInputParams.add(langSpec.newVariableDeclaration(var.getType(), "v" + v)); + } + v++; } } for (Variable var: message.getVariables().values()) { - resParams.add(langSpec.newVariableDeclaration(var.getType(), var.getName())); - mainParams.add(langSpec.newVariableDeclaration(var.getType(), var.getName())); + resInputParams.add(langSpec.newVariableDeclaration(var.getType(), var.getName())); + mainInputParams.add(langSpec.newVariableDeclaration(var.getType(), var.getName())); } - input = langSpec.newMethodDeclaration(((Term) message).getSymbol().getImplName(), false, null, resParams); - component.addMethod(input); - inputMethods.add(input); + input = langSpec.newMethodDeclaration(((Term) message).getSymbol().getImplName(), false, null, resInputParams); + if (component != null) { + // A component is created for this resource. + component.addMethod(input); + } else { + // No component is created for this resource. + 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, mainParams); - mainComponent.addMethod(mainInput); + inputAccessor = getMethod(mainComponent, str); + if (inputAccessor == null) { + inputAccessor = langSpec.newMethodDeclaration(str, false, null, mainInputParams); + mainComponent.addMethod(inputAccessor); } else { // Add type to a parameter without type. - if (mainInput.getParameters() != null) { - for (VariableDeclaration param: mainInput.getParameters()) { + if (inputAccessor.getParameters() != null) { + for (VariableDeclaration param: inputAccessor.getParameters()) { if (param.getType() == null) { - for (VariableDeclaration p: mainParams) { + for (VariableDeclaration p: mainInputParams) { if (param.getName().equals(p.getName()) && p.getType() != null) { param.setType(p.getType()); } @@ -444,50 +502,77 @@ } } else if (message instanceof Variable) { // Declare an input method in this component. - ArrayList resParams = new ArrayList<>(); - ArrayList mainParams = new ArrayList<>(); - for (Selector selector: resourceNode.getAllSelectors()) { + ArrayList resInputParams = new ArrayList<>(); + ArrayList mainInputParams = new ArrayList<>(); + int v = 1; + for (Selector selector: resourceNode.getSelectors()) { if (selector.getExpression() instanceof Variable) { Variable var = (Variable) selector.getExpression(); - mainParams.add(new VariableDeclaration(var.getType(), var.getName())); + resInputParams.add(langSpec.newVariableDeclaration(var.getType(), var.getName())); + mainInputParams.add(langSpec.newVariableDeclaration(var.getType(), var.getName())); + } else if (selector.getExpression() instanceof Term) { + Term var = (Term) selector.getExpression(); + resInputParams.add(langSpec.newVariableDeclaration(var.getType(), "v" + v)); + mainInputParams.add(langSpec.newVariableDeclaration(var.getType(), "v" + v)); + } + v++; + } + if (resourceNode.getResourceHierarchy().getParent() != null) { + for (Selector selector: resourceNode.getParent().getSelectors()) { + if (selector.getExpression() instanceof Variable) { + Variable var = (Variable) selector.getExpression(); + mainInputParams.add(langSpec.newVariableDeclaration(var.getType(), var.getName())); + } else if (selector.getExpression() instanceof Term) { + Term var = (Term) selector.getExpression(); + mainInputParams.add(langSpec.newVariableDeclaration(var.getType(), "v" + v)); + } + v++; } } - if (resParams.size() == 0) { + if (resInputParams.size() == 0) { input = langSpec.newMethodDeclaration(((Variable) message).getName(), null); } else { - input = langSpec.newMethodDeclaration(((Variable) message).getName(), false, null, resParams); + input = langSpec.newMethodDeclaration(((Variable) message).getName(), false, null, resInputParams); } - component.addMethod(input); - inputMethods.add(input); - String str = ((Variable) message).getName(); - + if (component != null) { + // A component is created for this resource. + component.addMethod(input); + } else { + // No component is created for this resource. + inputMethods.add(input); + } + // Declare the accessor in the main component to call the input method. - mainInput = getMethod(mainComponent, str); - if (mainInput == null) { - if (mainParams.size() == 0) { - mainInput = langSpec.newMethodDeclaration(str, null); + String str = ((Variable) message).getName(); + inputAccessor = getMethod(mainComponent, str); + if (inputAccessor == null) { + if (mainInputParams.size() == 0) { + inputAccessor = langSpec.newMethodDeclaration(str, null); } else { - mainInput = langSpec.newMethodDeclaration(str, false, null, mainParams); + inputAccessor = langSpec.newMethodDeclaration(str, false, null, mainInputParams); } - mainComponent.addMethod(mainInput); + mainComponent.addMethod(inputAccessor); } } // Add an invocation to the accessor method. - if (mainInput != null) { - Expression resExp = JavaCodeGenerator.pullAccessor.getCurrentStateAccessorFor(out.getResource(), null); + if (inputAccessor != null) { + Expression resExp = getPullAccessor().getCurrentStateAccessorFor(out.getResource(), null); + List args = new ArrayList<>(); if (resExp instanceof Term) { - // remove '.getValue()' + // to access the parent + if (((Term) resExp).getChildren().size() > 1 && ((Term) resExp).getChild(1) instanceof Variable) { + args.add(((Variable)((Term) resExp).getChild(1)).getName()); + } resExp = ((Term) resExp).getChild(0); } String resourceAccess = resExp.toImplementation(new String[] {null}); - List args = new ArrayList<>(); if (message instanceof Term) { for (Variable var: message.getVariables().values()) { args.add(var.getName()); } } - mainInput.addStatement(langSpec.getMethodInvocation(resourceAccess, input.getName(), args) + langSpec.getStatementDelimiter()); + inputAccessor.addStatement(langSpec.getMethodInvocation(resourceAccess, input.getName(), args) + langSpec.getStatementDelimiter()); } if (input != null) { @@ -498,7 +583,7 @@ updateExp = ((DataTransferChannel) ch).deriveUpdateExpressionOf(out, getPullAccessor()); String newState = updateExp.toImplementation(sideEffects); ResourceHierarchy resource = resourceNode.getResourceHierarchy(); - if (resource.getNumParameters() == 0 || resource.getChildren() == null || resource.getChildren().size() == 0) { + if (JavaCodeGenerator.generatesComponent(resource)) { String updateStatement; if (updateExp instanceof Term && ((Term) updateExp).getSymbol().isImplWithSideEffect()) { updateStatement = sideEffects[0]; diff --git a/AlgebraicDataflowArchitectureModel/src/generators/JavaCodeGenerator.java b/AlgebraicDataflowArchitectureModel/src/generators/JavaCodeGenerator.java index 16510b7..d37aa16 100644 --- a/AlgebraicDataflowArchitectureModel/src/generators/JavaCodeGenerator.java +++ b/AlgebraicDataflowArchitectureModel/src/generators/JavaCodeGenerator.java @@ -1,9 +1,12 @@ package generators; +import java.util.AbstractMap; 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 java.util.Stack; @@ -77,6 +80,10 @@ return name.substring(0, 1).toUpperCase() + name.substring(1); } + public static String toVariableName(String name) { + return name.substring(0, 1).toLowerCase() + name.substring(1); + } + public static Type getImplStateType(ResourceHierarchy res) { Set children = res.getChildren(); if (children == null || children.size() == 0) { @@ -88,10 +95,18 @@ // map or list. if (DataConstraintModel.typeList.isAncestorOf(res.getResourceStateType())) { // list. - return new Type("List", "ArrayList<>", "List<" + getComponentName(child) + ">", DataConstraintModel.typeList); + if (generatesComponent(child)) { + return new Type("List", "ArrayList<>", "List<" + getComponentName(child) + ">", DataConstraintModel.typeList); + } else { + return new Type("List", "ArrayList<>", "List<" + getImplStateType(child).getImplementationTypeName() + ">", DataConstraintModel.typeList); + } } else if (DataConstraintModel.typeMap.isAncestorOf(res.getResourceStateType())) { // map. - return new Type("Map", "HashMap<>", "Map", DataConstraintModel.typeMap); + if (generatesComponent(child)) { + return new Type("Map", "HashMap<>", "Map", DataConstraintModel.typeMap); + } else { + return new Type("Map", "HashMap<>", "Map", DataConstraintModel.typeMap); + } } return null; } else { @@ -100,10 +115,19 @@ } } } + + public static boolean generatesComponent(ResourceHierarchy res) { + return res.getParent() == null || !(res.getChildren() == null || res.getChildren().size() == 0); +// Type resType = res.getResourceStateType(); +// return DataConstraintModel.typeJson.isAncestorOf(resType) || DataConstraintModel.typeList.isAncestorOf(resType) || DataConstraintModel.typeMap.isAncestorOf(resType); + } static public ArrayList doGenerate(DataFlowGraph graph, DataTransferModel model) { ArrayList codes = new ArrayList<>(); ArrayList resources = determineResourceOrder(graph); + Map resourceTypes = new HashMap<>(); + List> getters = new ArrayList<>(); + List> inputs = new ArrayList<>(); TypeDeclaration mainType = new TypeDeclaration(mainTypeName); CompilationUnit mainCU = new CompilationUnit(mainType); @@ -116,44 +140,97 @@ // For each resource node. for (ResourceNode rn: resources) { - if (rn.getResourceHierarchy().getChildren().size() == 0 && rn.getResourceHierarchy().getNumParameters() == 0) { - // No component is created for a simple leaf resource. - continue; - } - boolean f = false; - String resourceName = getComponentName(rn.getResourceHierarchy()); TypeDeclaration type = null; - for (CompilationUnit cu: codes) { - for (TypeDeclaration t: cu.types()) { - if (resourceName.equals(t.getTypeName())) { - type = t; - break; + if (generatesComponent(rn.getResourceHierarchy())) { + boolean f = false; + String resourceName = getComponentName(rn.getResourceHierarchy()); + + type = resourceTypes.get(rn.getResourceHierarchy()); + if (type == null) { + // Add compilation unit for each resource. + type = new TypeDeclaration(resourceName); + resourceTypes.put(rn.getResourceHierarchy(), type); + CompilationUnit cu = new CompilationUnit(type); + cu.addImport(new ImportDeclaration("java.util.*")); + codes.add(cu); + + // Declare the field to refer to each resource in the main type. + Set depends = new HashSet<>(); + Set refs = new HashSet<>(); + if (rn.getResourceHierarchy().getParent() == null) { + // For a root resource + String fieldInitializer = "new " + resourceName + "("; + for (Edge resToCh: rn.getOutEdges()) { + DataFlowEdge re = (DataFlowEdge) resToCh; + if (((PushPullAttribute) re.getAttribute()).getOptions().get(0) == PushPullValue.PUSH) { + for (Edge chToRes: re.getDestination().getOutEdges()) { + ResourcePath dstRes = ((ResourceNode) chToRes.getDestination()).getOutSideResource(); + String resName = getComponentName(dstRes.getResourceHierarchy()); + depends.add(dstRes); + fieldInitializer += toVariableName(resName) + ","; + f = true; + } + } + } + for (Edge chToRes : rn.getInEdges()) { + for (Edge resToCh: chToRes.getSource().getInEdges()) { + DataFlowEdge re = (DataFlowEdge) resToCh; + ResourcePath srcRes = ((ResourceNode) re.getSource()).getOutSideResource(); + String resName = getComponentName(srcRes.getResourceHierarchy()); + if (((PushPullAttribute) re.getAttribute()).getOptions().get(0) != PushPullValue.PUSH) { + depends.add(srcRes); + fieldInitializer += toVariableName(resName) + ","; + f = true; + } else { + if (re.getDestination().getIndegree() > 1) { + // Declare a field to cash the state of the source resource in the type of the destination resource. + ResourcePath cashRes = ((ResourceNode) re.getSource()).getOutSideResource(); + type.addField(new FieldDeclaration( + cashRes.getResourceStateType(), ((ResourceNode) re.getSource()).getOutSideResource().getResourceName(), getInitializer(cashRes))); + } + } + } + } + for (Channel ch : model.getChannels()) { + DataTransferChannel c = (DataTransferChannel) ch; + if (c.getInputResources().contains(rn.getOutSideResource())) { + for (ResourcePath res: c.getReferenceResources()) { + if (!refs.contains(res) && !depends.contains(res)) { + refs.add(res); + String refResName = res.getResourceName(); + fieldInitializer += toVariableName(refResName) + ","; + f = true; + } + } + } + } + if (f) fieldInitializer = fieldInitializer.substring(0, fieldInitializer.length() - 1); + fieldInitializer += ")"; + FieldDeclaration field = new FieldDeclaration(new Type(resourceName, resourceName), rn.getResourceName()); + mainType.addField(field); + Block mainConstructorBody = mainConstructor.getBody(); + if (mainConstructorBody == null) { + mainConstructorBody = new Block(); + mainConstructor.setBody(mainConstructorBody); + } + mainConstructorBody.addStatement(rn.getResourceName() + " = " + fieldInitializer + ";"); } - } - if (type != null) break; - } - if (type == null) { - // Add compilation unit for each resource. - type = new TypeDeclaration(resourceName); - CompilationUnit cu = new CompilationUnit(type); - cu.addImport(new ImportDeclaration("java.util.*")); - codes.add(cu); - - // Declare the field to refer to each resource in the main type. - Set depends = new HashSet<>(); - Set refs = new HashSet<>(); - if (rn.getResourceHierarchy().getParent() == null) { - // For a root resource - String fieldInitializer = "new " + resourceName + "("; - for (Edge resToCh: rn.getOutEdges()) { + + // Declare a constructor, fields and update methods in the type of each resource. + MethodDeclaration constructor = new MethodDeclaration(resourceName, true); + Block block = new Block(); + depends = new HashSet<>(); + for (Edge resToCh : rn.getOutEdges()) { DataFlowEdge re = (DataFlowEdge) resToCh; if (((PushPullAttribute) re.getAttribute()).getOptions().get(0) == PushPullValue.PUSH) { + // Declare a field to refer to the destination resource of push transfer. for (Edge chToRes: re.getDestination().getOutEdges()) { ResourcePath dstRes = ((ResourceNode) chToRes.getDestination()).getOutSideResource(); - String resName = getComponentName(dstRes.getResourceHierarchy()); + String dstResName = getComponentName(dstRes.getResourceHierarchy()); depends.add(dstRes); - fieldInitializer += resName.toLowerCase() + ","; - f = true; + type.addField(new FieldDeclaration(new Type(dstResName, dstResName), dstRes.getResourceName())); + constructor.addParameter(new VariableDeclaration(new Type(dstResName, dstResName), dstRes.getResourceName())); + block.addStatement("this." + toVariableName(dstResName) + " = " + toVariableName(dstResName) + ";"); } } } @@ -161,150 +238,226 @@ for (Edge resToCh: chToRes.getSource().getInEdges()) { DataFlowEdge re = (DataFlowEdge) resToCh; ResourcePath srcRes = ((ResourceNode) re.getSource()).getOutSideResource(); - String resName = getComponentName(srcRes.getResourceHierarchy()); + String srcResName = getComponentName(srcRes.getResourceHierarchy()); if (((PushPullAttribute) re.getAttribute()).getOptions().get(0) != PushPullValue.PUSH) { + // Declare a field to refer to the source resource of pull transfer. depends.add(srcRes); - fieldInitializer += resName.toLowerCase() + ","; - f = true; + type.addField(new FieldDeclaration(new Type(srcResName, srcResName), srcRes.getResourceName())); + constructor.addParameter(new VariableDeclaration(new Type(srcResName, srcResName), srcRes.getResourceName())); + block.addStatement("this." + toVariableName(srcResName) + " = " + toVariableName(srcResName) + ";"); } else { - if (re.getDestination().getIndegree() > 1) { - // Declare a field to cash the state of the source resource in the type of the destination resource. - ResourcePath cashRes = ((ResourceNode) re.getSource()).getOutSideResource(); - type.addField(new FieldDeclaration( - cashRes.getResourceStateType(), ((ResourceNode) re.getSource()).getOutSideResource().getResourceName(), getInitializer(cashRes))); + // Declare an update method in the type of the destination resource. + ArrayList vars = new ArrayList<>(); + vars.add(new VariableDeclaration(srcRes.getResourceStateType(), srcRes.getResourceName())); + DataTransferChannel c = ((ChannelNode) resToCh.getDestination()).getChannel(); + for (ResourcePath ref: c.getReferenceResources()) { + if (!ref.equals(rn.getOutSideResource())) { + vars.add(new VariableDeclaration(ref.getResourceStateType(), ref.getResourceName())); + } } + type.addMethod(new MethodDeclaration("update" + srcResName, false, typeVoid, vars)); } } } + // Declare a field to refer to the reference resource. + refs = new HashSet<>(); for (Channel ch : model.getChannels()) { DataTransferChannel c = (DataTransferChannel) ch; if (c.getInputResources().contains(rn.getOutSideResource())) { for (ResourcePath res: c.getReferenceResources()) { if (!refs.contains(res) && !depends.contains(res)) { refs.add(res); - String refResName = res.getResourceName(); - fieldInitializer += refResName.toLowerCase() + ","; - f = true; + String refResName = getComponentName(res.getResourceHierarchy()); + 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() + ";"); } } } } - if (f) fieldInitializer = fieldInitializer.substring(0, fieldInitializer.length() - 1); - fieldInitializer += ")"; - FieldDeclaration field = new FieldDeclaration(new Type(resourceName, resourceName), rn.getResourceName()); - mainType.addField(field); - Block mainConstructorBody = mainConstructor.getBody(); - if (mainConstructorBody == null) { - mainConstructorBody = new Block(); - mainConstructor.setBody(mainConstructorBody); + constructor.setBody(block); + if (constructor.getParameters() != null) + type.addMethod(constructor); + } + + // Declare the field to store the state in the type of each resource. + if (((StoreAttribute) rn.getAttribute()).isStored()) { + ResourcePath res = rn.getOutSideResource(); + Set children = rn.getResourceHierarchy().getChildren(); + if (children == null || children.size() == 0) { + // leaf resource. + type.addField(new FieldDeclaration(getImplStateType(res.getResourceHierarchy()), "value", getInitializer(res))); + } else { + ResourceHierarchy child = children.iterator().next(); + if (children.size() == 1 && child.getNumParameters() > 0) { + // map or list. + type.addField(new FieldDeclaration(getImplStateType(res.getResourceHierarchy()), "value", getInitializer(res))); + } else { + // class + for (ResourceHierarchy c: children) { + String childTypeName = getComponentName(c); + Type childType = null; + if ((c.getChildren() == null || c.getChildren().size() == 0) && c.getNumParameters() == 0) { + // The child does not have a component. + childType = c.getResourceStateType(); + } else { + // The child has a component. + childType = new Type(childTypeName, childTypeName); + } + String fieldName = toVariableName(childTypeName); + type.addField(new FieldDeclaration(childType, fieldName, getInitializer(res))); + } + } } - mainConstructorBody.addStatement(rn.getResourceName() + " = " + fieldInitializer + ";"); } - // Declare a constructor, fields and update methods in the type of each resource. - MethodDeclaration constructor = new MethodDeclaration(resourceName, true); - Block block = new Block(); - depends = new HashSet<>(); - for (Edge resToCh : rn.getOutEdges()) { - DataFlowEdge re = (DataFlowEdge) resToCh; - if (((PushPullAttribute) re.getAttribute()).getOptions().get(0) == PushPullValue.PUSH) { - // Declare a field to refer to the destination resource of push transfer. - for (Edge chToRes: re.getDestination().getOutEdges()) { - ResourcePath dstRes = ((ResourceNode) chToRes.getDestination()).getOutSideResource(); - String dstResName = getComponentName(dstRes.getResourceHierarchy()); - depends.add(dstRes); - type.addField(new FieldDeclaration(new Type(dstResName, dstResName), dstRes.getResourceName())); - constructor.addParameter(new VariableDeclaration(new Type(dstResName, dstResName), dstRes.getResourceName())); - block.addStatement("this." + dstResName.toLowerCase() + " = " + dstResName.toLowerCase() + ";"); + // Declare the getter methods to obtain the children resources. + for (ResourceNode child: rn.getChildren()) { + if (generatesComponent(child.getResourceHierarchy())) { + // A component is generated for the child. + List params = new ArrayList<>(); + int v = 1; + for (Selector param: child.getSelectors()) { + if (param.getExpression() instanceof Variable) { + Variable var = (Variable) param.getExpression(); + params.add(new VariableDeclaration(var.getType(), var.getName())); + } else if (param.getExpression() instanceof Term) { + Term var = (Term) param.getExpression(); + params.add(new VariableDeclaration(var.getType(), "v" + v)); + } + v++; } - } - } - for (Edge chToRes : rn.getInEdges()) { - for (Edge resToCh: chToRes.getSource().getInEdges()) { - DataFlowEdge re = (DataFlowEdge) resToCh; - ResourcePath srcRes = ((ResourceNode) re.getSource()).getOutSideResource(); - String srcResName = getComponentName(srcRes.getResourceHierarchy()); - if (((PushPullAttribute) re.getAttribute()).getOptions().get(0) != PushPullValue.PUSH) { - // Declare a field to refer to the source resource of pull transfer. - depends.add(srcRes); - type.addField(new FieldDeclaration(new Type(srcResName, srcResName), srcRes.getResourceName())); - constructor.addParameter(new VariableDeclaration(new Type(srcResName, srcResName), srcRes.getResourceName())); - block.addStatement("this." + srcResName.toLowerCase() + " = " + srcResName.toLowerCase() + ";"); + String childCompName = getComponentName(child.getResourceHierarchy()); + Type childType = new Type(childCompName, childCompName); + MethodDeclaration childGetter = null; + if (params.size() == 0) { + childGetter = new MethodDeclaration("get" + childCompName, childType); } else { - // Declare an update method in the type of the destination resource. - ArrayList vars = new ArrayList<>(); - vars.add(new VariableDeclaration(srcRes.getResourceStateType(), srcRes.getResourceName())); - DataTransferChannel c = ((ChannelNode) resToCh.getDestination()).getChannel(); - for (ResourcePath ref: c.getReferenceResources()) { - if (!ref.equals(rn.getOutSideResource())) { - vars.add(new VariableDeclaration(ref.getResourceStateType(), ref.getResourceName())); - } - } - type.addMethod(new MethodDeclaration("update" + srcResName, false, typeVoid, vars)); + childGetter = new MethodDeclaration("get" + childCompName, false, childType, params); } + type.addMethod(childGetter); } } - // Declare a field to refer to the reference resource. - refs = new HashSet<>(); - for (Channel ch : model.getChannels()) { - DataTransferChannel c = (DataTransferChannel) ch; - if (c.getInputResources().contains(rn.getOutSideResource())) { - for (ResourcePath res: c.getReferenceResources()) { - if (!refs.contains(res) && !depends.contains(res)) { - refs.add(res); - String refResName = getComponentName(res.getResourceHierarchy()); - 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() + ";"); - } - } - } - } - constructor.setBody(block); - if (constructor.getParameters() != null) - type.addMethod(constructor); } - // Declare input methods in resources and the main type. + // Declare the getter method to obtain the resource state in the component of each resource. + if (type != null) { + // A component is created for this resource. + MethodDeclaration stateGetter = new MethodDeclaration("getValue", getImplStateType(rn.getResourceHierarchy())); + type.addMethod(stateGetter); + } else { + // No component is created for this resource. + List getterParams = new ArrayList<>(); + int v = 1; + for (Selector param: rn.getSelectors()) { + if (param.getExpression() instanceof Variable) { + Variable var = (Variable) param.getExpression(); + getterParams.add(new VariableDeclaration(var.getType(), var.getName())); + } else if (param.getExpression() instanceof Term) { + Term var = (Term) param.getExpression(); + getterParams.add(new VariableDeclaration(var.getType(), "v" + v)); + } + v++; + } + String resCompName = getComponentName(rn.getResourceHierarchy()); + Type resType = getImplStateType(rn.getResourceHierarchy()); + MethodDeclaration stateGetter = null; + if (getterParams.size() == 0) { + stateGetter = new MethodDeclaration("get" + resCompName, resType); + } else { + stateGetter = new MethodDeclaration("get" + resCompName, false, resType, getterParams); + } + getters.add(new AbstractMap.SimpleEntry(rn.getParent().getResourceHierarchy(), stateGetter)); + } + + // Declare the getter accessor in the main type. + MethodDeclaration accessor = null; + List mainGetterParams = new ArrayList<>(); + int v = 1; + for (Selector param: rn.getAllSelectors()) { + if (param.getExpression() instanceof Variable) { + Variable var = (Variable) param.getExpression(); + mainGetterParams.add(new VariableDeclaration(var.getType(), var.getName())); + } else if (param.getExpression() instanceof Term) { + Term var = (Term) param.getExpression(); + mainGetterParams.add(new VariableDeclaration(var.getType(), "v" + v)); + } + v++; + } + if (mainGetterParams.size() > 0) { + accessor = new MethodDeclaration("get" + getComponentName(rn.getResourceHierarchy()), + false, + getImplStateType(rn.getResourceHierarchy()), + mainGetterParams); + } else { + accessor = new MethodDeclaration("get" + getComponentName(rn.getResourceHierarchy()), + getImplStateType(rn.getResourceHierarchy())); + } + accessor.setBody(new Block()); + Expression getState = JavaCodeGenerator.pullAccessor.getCurrentStateAccessorFor(rn.getOutSideResource(), null); + accessor.getBody().addStatement("return " + getState.toImplementation(new String[] {null}) + ";"); + mainType.addMethod(accessor); + + // Declare the input method in each resource and the main component. for (Channel ch : model.getIOChannels()) { for (ChannelMember cm : ((DataTransferChannel) ch).getOutputChannelMembers()) { if (rn.getInSideResources().contains(cm.getResource())) { Expression message = cm.getStateTransition().getMessageExpression(); if (message instanceof Term) { // In each resource. - ArrayList resParams = new ArrayList<>(); - ArrayList mainParams = new ArrayList<>(); - int v = 1; - for (Selector selector: rn.getAllSelectors()) { + ArrayList resInputParams = new ArrayList<>(); + ArrayList mainInputParams = new ArrayList<>(); + v = 1; + for (Selector selector: rn.getSelectors()) { if (selector.getExpression() instanceof Variable) { Variable var = (Variable) selector.getExpression(); - mainParams.add(new VariableDeclaration(var.getType(), var.getName())); + resInputParams.add(new VariableDeclaration(var.getType(), var.getName())); + mainInputParams.add(new VariableDeclaration(var.getType(), var.getName())); } else if (selector.getExpression() instanceof Term) { Term var = (Term) selector.getExpression(); - mainParams.add(new VariableDeclaration(var.getType(), "v" + v)); + resInputParams.add(new VariableDeclaration(var.getType(), "v" + v)); + mainInputParams.add(new VariableDeclaration(var.getType(), "v" + v)); } v++; } + if (rn.getParent() != null) { + for (Selector selector: rn.getParent().getAllSelectors()) { + if (selector.getExpression() instanceof Variable) { + Variable var = (Variable) selector.getExpression(); + mainInputParams.add(new VariableDeclaration(var.getType(), var.getName())); + } else if (selector.getExpression() instanceof Term) { + Term var = (Term) selector.getExpression(); + mainInputParams.add(new VariableDeclaration(var.getType(), "v" + v)); + } + v++; + } + } for (Variable var: message.getVariables().values()) { - resParams.add(new VariableDeclaration(var.getType(), var.getName())); - mainParams.add(new VariableDeclaration(var.getType(), var.getName())); + resInputParams.add(new VariableDeclaration(var.getType(), var.getName())); + mainInputParams.add(new VariableDeclaration(var.getType(), var.getName())); } MethodDeclaration input = new MethodDeclaration( ((Term) cm.getStateTransition().getMessageExpression()).getSymbol().getImplName(), - false, typeVoid, resParams); - type.addMethod(input); + false, typeVoid, resInputParams); + if (type != null) { + // A component is created for this resource. + type.addMethod(input); + } else { + // No component is created for this resource. + inputs.add(new AbstractMap.SimpleEntry(rn.getParent().getResourceHierarchy(), input)); + } // In the main type. String str = ((Term) cm.getStateTransition().getMessageExpression()).getSymbol().getImplName(); - input = getMethod(mainType, str, mainParams); + input = getMethod(mainType, str, mainInputParams); if (input == null) { - input = new MethodDeclaration(str, false, typeVoid, mainParams); + input = new MethodDeclaration(str, false, typeVoid, mainInputParams); mainType.addMethod(input); } else { // Add type to a parameter without type. for (VariableDeclaration param: input.getParameters()) { if (param.getType() == null) { - for (VariableDeclaration p: mainParams) { + for (VariableDeclaration p: mainInputParams) { if (param.getName().equals(p.getName()) && p.getType() != null) { param.setType(p.getType()); } @@ -314,37 +467,57 @@ } } else if (message instanceof Variable) { // In each resource. - ArrayList resParams = new ArrayList<>(); - ArrayList mainParams = new ArrayList<>(); - int v = 1; - for (Selector selector: rn.getAllSelectors()) { + ArrayList resInputParams = new ArrayList<>(); + ArrayList mainInputParams = new ArrayList<>(); + v = 1; + for (Selector selector: rn.getSelectors()) { if (selector.getExpression() instanceof Variable) { Variable var = (Variable) selector.getExpression(); - mainParams.add(new VariableDeclaration(var.getType(), var.getName())); + resInputParams.add(new VariableDeclaration(var.getType(), var.getName())); + mainInputParams.add(new VariableDeclaration(var.getType(), var.getName())); } else if (selector.getExpression() instanceof Term) { Term var = (Term) selector.getExpression(); - mainParams.add(new VariableDeclaration(var.getType(), "v" + v)); + resInputParams.add(new VariableDeclaration(var.getType(), "v" + v)); + mainInputParams.add(new VariableDeclaration(var.getType(), "v" + v)); } v++; } + if (rn.getResourceHierarchy().getParent() != null) { + for (Selector selector: rn.getParent().getSelectors()) { + if (selector.getExpression() instanceof Variable) { + Variable var = (Variable) selector.getExpression(); + mainInputParams.add(new VariableDeclaration(var.getType(), var.getName())); + } else if (selector.getExpression() instanceof Term) { + Term var = (Term) selector.getExpression(); + mainInputParams.add(new VariableDeclaration(var.getType(), "v" + v)); + } + v++; + } + } MethodDeclaration input = null; - if (resParams.size() > 0) { + if (resInputParams.size() > 0) { input = new MethodDeclaration( ((Variable) cm.getStateTransition().getMessageExpression()).getName(), - false, typeVoid, resParams); + false, typeVoid, resInputParams); } else { input = new MethodDeclaration( ((Variable) cm.getStateTransition().getMessageExpression()).getName(), false, typeVoid, null); } - type.addMethod(input); + if (type != null) { + // A component is created for this resource. + type.addMethod(input); + } else { + // No component is created for this resource. + inputs.add(new AbstractMap.SimpleEntry(rn.getParent().getResourceHierarchy(), input)); + } // In the main type. String str = ((Variable) cm.getStateTransition().getMessageExpression()).getName(); - input = getMethod(mainType, str, mainParams); + input = getMethod(mainType, str, mainInputParams); if (input == null) { - if (mainParams.size() > 0) { - input = new MethodDeclaration(str, false, typeVoid, mainParams); + if (mainInputParams.size() > 0) { + input = new MethodDeclaration(str, false, typeVoid, mainInputParams); } else { input = new MethodDeclaration(str, false, typeVoid, null); } @@ -353,103 +526,17 @@ } } } - } - - // Declare the field to store the state in the type of each resource. - if (((StoreAttribute) rn.getAttribute()).isStored()) { - ResourcePath res = rn.getOutSideResource(); - Set children = rn.getResourceHierarchy().getChildren(); - if (children == null || children.size() == 0) { - // leaf resource. - type.addField(new FieldDeclaration(getImplStateType(res.getResourceHierarchy()), "value", getInitializer(res))); - } else { - ResourceHierarchy child = children.iterator().next(); - if (children.size() == 1 && child.getNumParameters() > 0) { - // map or list. - type.addField(new FieldDeclaration(getImplStateType(res.getResourceHierarchy()), "value", getInitializer(res))); - } else { - // class - for (ResourceHierarchy c: children) { - String childTypeName = getComponentName(c); - Type childType = null; - if ((c.getChildren() == null || c.getChildren().size() == 0) && c.getNumParameters() == 0) { - // The child does not have a component. - childType = c.getResourceStateType(); - } else { - // The child has a component. - childType = new Type(childTypeName, childTypeName); - } - String fieldName = childTypeName.substring(0, 1).toLowerCase() + childTypeName.substring(1); - type.addField(new FieldDeclaration(childType, fieldName, getInitializer(res))); - } - } - } } - - // Declare the getter method to obtain the state in the resource. - MethodDeclaration stateGetter = new MethodDeclaration("getValue", getImplStateType(rn.getResourceHierarchy())); - type.addMethod(stateGetter); - - // Declare the getter methods to obtain a child of the resource. - for (ResourceNode child: rn.getChildren()) { - List pathParams = new ArrayList<>(); - int v = 1; - for (Selector pathParam: child.getSelectors()) { - if (pathParam.getExpression() instanceof Variable) { - Variable var = (Variable) pathParam.getExpression(); - pathParams.add(new VariableDeclaration(var.getType(), var.getName())); - } else if (pathParam.getExpression() instanceof Term) { - Term var = (Term) pathParam.getExpression(); - pathParams.add(new VariableDeclaration(var.getType(), "v" + v)); - } - v++; - } - String childTypeName = getComponentName(child.getResourceHierarchy()); - Type childType = null; - if ((child.getResourceHierarchy().getChildren() == null || child.getResourceHierarchy().getChildren().size() == 0) - && child.getResourceHierarchy().getNumParameters() == 0) { - // The child does not have a component. - childType = child.getResourceStateType(); - } else { - // The child has a component. - childType = new Type(childTypeName, childTypeName); - } - MethodDeclaration childGetter = null; - if (pathParams.size() == 0) { - childGetter = new MethodDeclaration("get" + childTypeName, childType); - } else { - childGetter = new MethodDeclaration("get" + childTypeName, false, childType, pathParams); - } - type.addMethod(childGetter); - } - - // Declare the getter accessor to obtain the resource state in the main type. - MethodDeclaration accessor = null; - List mainParams = new ArrayList<>(); - int v = 1; - for (Selector pathParam: rn.getAllSelectors()) { - if (pathParam.getExpression() instanceof Variable) { - Variable var = (Variable) pathParam.getExpression(); - mainParams.add(new VariableDeclaration(var.getType(), var.getName())); - } else if (pathParam.getExpression() instanceof Term) { - Term var = (Term) pathParam.getExpression(); - mainParams.add(new VariableDeclaration(var.getType(), "v" + v)); - } - v++; - } - if (mainParams.size() > 0) { - accessor = new MethodDeclaration("get" + getComponentName(rn.getResourceHierarchy()), - false, - getImplStateType(rn.getResourceHierarchy()), - mainParams); - } else { - accessor = new MethodDeclaration("get" + getComponentName(rn.getResourceHierarchy()), - getImplStateType(rn.getResourceHierarchy())); - } - accessor.setBody(new Block()); - Expression getState = JavaCodeGenerator.pullAccessor.getCurrentStateAccessorFor(rn.getOutSideResource(), null); - accessor.getBody().addStatement("return " + getState.toImplementation(new String[] {null}) + ";"); - mainType.addMethod(accessor); + } + + // Add leaf getter methods to the parent components. + for (Map.Entry entry: getters) { + resourceTypes.get(entry.getKey()).addMethod(entry.getValue()); + } + + // Add leaf input methods to the parent components. + for (Map.Entry entry: inputs) { + resourceTypes.get(entry.getKey()).addMethod(entry.getValue()); } // Declare the Pair class. @@ -647,6 +734,7 @@ : DataConstraintModel.typeInt); } }; + static public IResourceStateAccessor pullAccessor = new IResourceStateAccessor() { @Override public Expression getCurrentStateAccessorFor(ResourcePath target, ResourcePath from) { @@ -676,7 +764,7 @@ String typeName = getComponentName(curPath.getResourceHierarchy()); if (getter == null) { // root resource - String fieldName = typeName.substring(0, 1).toLowerCase() + typeName.substring(1); + String fieldName = toVariableName(typeName); getter = new Field(fieldName, new Type(typeName, typeName)); } else { Term newGetter = new Term(new Symbol("get" + typeName, -1, Symbol.Type.METHOD)); @@ -698,9 +786,7 @@ getter = newGetter; } } - - if (target.getResourceHierarchy().getNumParameters() > 0 - || (target.getResourceHierarchy().getChildren() != null && target.getResourceHierarchy().getChildren().size() > 0)) { + if (generatesComponent(target.getResourceHierarchy())) { Term newGetter = new Term(new Symbol("getValue", 1, Symbol.Type.METHOD)); newGetter.addChild(getter); getter = newGetter; diff --git a/AlgebraicDataflowArchitectureModel/src/generators/JavaMethodBodyGenerator.java b/AlgebraicDataflowArchitectureModel/src/generators/JavaMethodBodyGenerator.java index d44abfa..2723a82 100644 --- a/AlgebraicDataflowArchitectureModel/src/generators/JavaMethodBodyGenerator.java +++ b/AlgebraicDataflowArchitectureModel/src/generators/JavaMethodBodyGenerator.java @@ -245,7 +245,7 @@ composerSub.setType(DataConstraintModel.typeMap); for (ResourceHierarchy child: resource.getChildren()) { String childTypeName = JavaCodeGenerator.getComponentName(child); - String fieldName = childTypeName.substring(0, 1).toLowerCase() + childTypeName.substring(1); + String fieldName = JavaCodeGenerator.toVariableName(childTypeName); Term childGetter = null; if ((child.getChildren() == null || child.getChildren().size() == 0) && child.getNumParameters() == 0) { // the child is not a class @@ -298,84 +298,99 @@ childGetter.addStatement("return " + returnValue+ ";"); } else { String fieldName = JavaCodeGenerator.getComponentName(child); - String returnValue = fieldName.substring(0, 1).toLowerCase() + fieldName.substring(1); + String returnValue = JavaCodeGenerator.toVariableName(fieldName); childGetter.addStatement("return this." + returnValue + ";"); } } } } - - // methods for input events - Map> ioChannelsAndMembers = getIOChannelsAndMembers(resource, model); - for (Map.Entry> entry: ioChannelsAndMembers.entrySet()) { - Set outs = entry.getValue(); - for (ChannelMember out: outs) { - MethodDeclaration input = getInputMethod(type, out); - if (input != null) { - // In each resource - String[] sideEffects = new String[] {""}; - Expression updateExp = entry.getKey().deriveUpdateExpressionOf(out, JavaCodeGenerator.pushAccessor); - String newState = updateExp.toImplementation(sideEffects); - if (resource.getNumParameters() == 0 || resource.getChildren() == null || resource.getChildren().size() == 0) { - String updateStatement; - if (updateExp instanceof Term && ((Term) updateExp).getSymbol().isImplWithSideEffect()) { - updateStatement = sideEffects[0]; - } else { - updateStatement = sideEffects[0] + "this.value = " + newState + ";"; + } + + // methods for input events + Map> ioChannelsAndMembers = getIOChannelsAndMembers(resource, model); + for (Map.Entry> entry: ioChannelsAndMembers.entrySet()) { + Set outs = entry.getValue(); + for (ChannelMember out: outs) { + MethodDeclaration input = null; + if (JavaCodeGenerator.generatesComponent(resource)) { + // A component is generated for this resource. + input = getInputMethod(type, out); + } else { + // No component is generated for this resource. + ResourceHierarchy parent = resource.getParent(); + if (parent != null) { + TypeDeclaration parentType = typeMap.get(JavaCodeGenerator.getComponentName(parent)); + input = getInputMethod(parentType, out); + } + } + if (input != null) { + // In each resource + String[] sideEffects = new String[] {""}; + Expression updateExp = entry.getKey().deriveUpdateExpressionOf(out, JavaCodeGenerator.pushAccessor); + String newState = updateExp.toImplementation(sideEffects); + if (JavaCodeGenerator.generatesComponent(resource)) { + String updateStatement; + if (updateExp instanceof Term && ((Term) updateExp).getSymbol().isImplWithSideEffect()) { + updateStatement = sideEffects[0]; + } else { + updateStatement = sideEffects[0] + "this.value = " + newState + ";"; + } + if (input.getBody() == null || !input.getBody().getStatements().contains(updateStatement)) { + input.addFirstStatement(updateStatement); + } + } else { + String updateStatement = null; + if (updateExp instanceof Term && ((Term) updateExp).getSymbol().isImplWithSideEffect()) { + // ToDo. + updateStatement = sideEffects[0]; + } else { + if (DataConstraintModel.typeList.isAncestorOf(resource.getParent().getResourceStateType())) { + Term selector = new Term(DataConstraintModel.set); + selector.addChild(new Field("value")); + selector.addChild(new Variable(input.getParameters().get(input.getParameters().size() - 2).getName())); + selector.addChild(new Constant(newState)); + String[] sideEffects2 = new String[] {""}; + String newList = selector.toImplementation(sideEffects2); + updateStatement = sideEffects[0] + sideEffects2[0]; + } else if (DataConstraintModel.typeMap.isAncestorOf(resource.getParent().getResourceStateType())) { + Term selector = new Term(DataConstraintModel.set); + selector.addChild(new Field("value")); + selector.addChild(new Variable(input.getParameters().get(input.getParameters().size() - 2).getName())); + selector.addChild(new Constant(newState)); + String[] sideEffects2 = new String[] {""}; + String newList = selector.toImplementation(sideEffects2); + updateStatement = sideEffects[0] + sideEffects2[0]; } - if (input.getBody() == null || !input.getBody().getStatements().contains(updateStatement)) { + if (updateStatement != null && (input.getBody() == null || !input.getBody().getStatements().contains(updateStatement))) { input.addFirstStatement(updateStatement); } - } else { - String updateStatement = null; - if (updateExp instanceof Term && ((Term) updateExp).getSymbol().isImplWithSideEffect()) { - // ToDo. - updateStatement = sideEffects[0]; - } else { - if (DataConstraintModel.typeList.isAncestorOf(resource.getParent().getResourceStateType())) { - Term selector = new Term(DataConstraintModel.set); - selector.addChild(new Field("value")); - selector.addChild(new Variable(input.getParameters().get(input.getParameters().size() - 2).getName())); - selector.addChild(new Constant(newState)); - String[] sideEffects2 = new String[] {""}; - String newList = selector.toImplementation(sideEffects2); - updateStatement = sideEffects[0] + sideEffects2[0]; - } else if (DataConstraintModel.typeMap.isAncestorOf(resource.getParent().getResourceStateType())) { - Term selector = new Term(DataConstraintModel.set); - selector.addChild(new Field("value")); - selector.addChild(new Variable(input.getParameters().get(input.getParameters().size() - 2).getName())); - selector.addChild(new Constant(newState)); - String[] sideEffects2 = new String[] {""}; - String newList = selector.toImplementation(sideEffects2); - updateStatement = sideEffects[0] + sideEffects2[0]; - } - if (updateStatement != null && (input.getBody() == null || !input.getBody().getStatements().contains(updateStatement))) { - input.addFirstStatement(updateStatement); - } - } } - - // In the main type - if (mainType != null) { - MethodDeclaration inputAccessor = getMethod(mainType, input.getName()); - if (inputAccessor != null) { - Expression resExp = JavaCodeGenerator.pullAccessor.getCurrentStateAccessorFor(out.getResource(), null); - if (resExp instanceof Term) { - // remove '.getValue()' - resExp = ((Term) resExp).getChild(0); + } + + // In the main type + if (mainType != null) { + MethodDeclaration inputAccessor = getMethod(mainType, input.getName()); + if (inputAccessor != null) { + Expression resExp = JavaCodeGenerator.pullAccessor.getCurrentStateAccessorFor(out.getResource(), null); + String args = ""; + String delimiter = ""; + if (resExp instanceof Term) { + // to access the parent + if (((Term) resExp).getChildren().size() > 1 && ((Term) resExp).getChild(1) instanceof Variable) { + args += delimiter + ((Variable)((Term) resExp).getChild(1)).getName(); + delimiter = ", "; } - String resourceAccess = resExp.toImplementation(new String[] {null}); - String args = ""; - String delimiter = ""; - if (out.getStateTransition().getMessageExpression() instanceof Term) { - Term message = (Term) out.getStateTransition().getMessageExpression(); - for (Variable var: message.getVariables().values()) { - args += delimiter + var.getName(); - delimiter = ", "; - } - } - inputAccessor.addStatement(resourceAccess + "." + input.getName() + "(" + args + ");"); + resExp = ((Term) resExp).getChild(0); } + String resourceAccess = resExp.toImplementation(new String[] {null}); + if (out.getStateTransition().getMessageExpression() instanceof Term) { + Term message = (Term) out.getStateTransition().getMessageExpression(); + for (Variable var: message.getVariables().values()) { + args += delimiter + var.getName(); + delimiter = ", "; + } + } + inputAccessor.addStatement(resourceAccess + "." + input.getName() + "(" + args + ");"); } } } diff --git a/AlgebraicDataflowArchitectureModel/src/generators/JerseyCodeGenerator.java b/AlgebraicDataflowArchitectureModel/src/generators/JerseyCodeGenerator.java index 3a6fea5..855de3b 100644 --- a/AlgebraicDataflowArchitectureModel/src/generators/JerseyCodeGenerator.java +++ b/AlgebraicDataflowArchitectureModel/src/generators/JerseyCodeGenerator.java @@ -1,5 +1,6 @@ package generators; +import java.util.AbstractMap; import java.util.ArrayList; import java.util.Collection; import java.util.HashMap; @@ -81,6 +82,10 @@ return name.substring(0, 1).toUpperCase() + name.substring(1); } + public static String toVariableName(String name) { + return name.substring(0, 1).toLowerCase() + name.substring(1); + } + public static Type getImplStateType(ResourceHierarchy res) { Set children = res.getChildren(); if (children == null || children.size() == 0) { @@ -92,10 +97,18 @@ // map or list. if (DataConstraintModel.typeList.isAncestorOf(res.getResourceStateType())) { // list. - return new Type("List", "ArrayList<>", "List<" + getComponentName(child) + ">", DataConstraintModel.typeList); + if (generatesComponent(child)) { + return new Type("List", "ArrayList<>", "List<" + getComponentName(child) + ">", DataConstraintModel.typeList); + } else { + return new Type("List", "ArrayList<>", "List<" + getImplStateType(child).getImplementationTypeName() + ">", DataConstraintModel.typeList); + } } else if (DataConstraintModel.typeMap.isAncestorOf(res.getResourceStateType())) { // map. - return new Type("Map", "HashMap<>", "Map", DataConstraintModel.typeMap); + if (generatesComponent(child)) { + return new Type("Map", "HashMap<>", "Map", DataConstraintModel.typeMap); + } else { + return new Type("Map", "HashMap<>", "Map", DataConstraintModel.typeMap); + } } return null; } else { @@ -105,277 +118,208 @@ } } + public static boolean generatesComponent(ResourceHierarchy res) { + return res.getParent() == null || !(res.getChildren() == null || res.getChildren().size() == 0); +// Type resType = res.getResourceStateType(); +// return DataConstraintModel.typeJson.isAncestorOf(resType) || DataConstraintModel.typeList.isAncestorOf(resType) || DataConstraintModel.typeMap.isAncestorOf(resType); + } static public ArrayList doGenerate(DataFlowGraph graph, DataTransferModel model) { ArrayList codes = new ArrayList<>(); // ArrayList resources = StoreResourceCheck(graph); Collection resources = graph.getResourceNodes(); Map resourceTypes = new HashMap<>(); + List> getters = new ArrayList<>(); + List> inputs = new ArrayList<>(); Map getterAccessors = new HashMap<>(); Map inputAccessors = new HashMap<>(); // For each resource node. for (Node n : resources) { - ResourceNode rn = (ResourceNode) n; - if (rn.getResourceHierarchy().getChildren().size() == 0 && rn.getResourceHierarchy().getNumParameters() == 0) { - // Don't create new component for a simple leaf resource. - continue; - } - String resourceName = getComponentName(rn.getResourceHierarchy()); - - TypeDeclaration type = resourceTypes.get(rn.getResourceHierarchy()); - if (type == null) { - // Add compilation unit for each resource. - type = new TypeDeclaration(resourceName); - if (rn.getResourceHierarchy().getParent() == null) { - // For a root node. - type.addAnnotation(new Annotation("Component")); - type.addAnnotation(new Annotation("Path", "\"/" + rn.getResourceName() + "\"")); - } - resourceTypes.put(rn.getResourceHierarchy(), type); - - CompilationUnit cu = new CompilationUnit(type); - cu.addImport(new ImportDeclaration("java.util.*")); - if (rn.getResourceHierarchy().getParent() == null) { - // For a root node. - cu.addImport(new ImportDeclaration("javax.ws.rs.*")); - cu.addImport(new ImportDeclaration("javax.ws.rs.client.*")); - cu.addImport(new ImportDeclaration("javax.ws.rs.core.*")); - cu.addImport(new ImportDeclaration("org.springframework.stereotype.Component")); - cu.addImport(new ImportDeclaration("com.fasterxml.jackson.databind.ObjectMapper")); - cu.addImport(new ImportDeclaration("com.fasterxml.jackson.core.JsonProcessingException")); - } - codes.add(cu); - } - - // Declare a client field and update methods from other resources. - if (rn.getResourceHierarchy().getParent() == null) { - // For a root resource - boolean bDeclareClientField = false; - for (Edge resToCh: rn.getOutEdges()) { - DataFlowEdge re = (DataFlowEdge) resToCh; - if (!bDeclareClientField && ((PushPullAttribute) re.getAttribute()).getOptions().get(0) == PushPullValue.PUSH) { - // Declare a client field to connect to the destination resource of push transfer. - type.addField(new FieldDeclaration(typeClient, "client", "ClientBuilder.newClient()")); - bDeclareClientField = true; + ResourceNode rn = (ResourceNode) n; + TypeDeclaration type = null; + if (generatesComponent(rn.getResourceHierarchy())) { + String resourceName = getComponentName(rn.getResourceHierarchy()); + + type = resourceTypes.get(rn.getResourceHierarchy()); + if (type == null) { + // Add compilation unit for each resource. + type = new TypeDeclaration(resourceName); + if (rn.getResourceHierarchy().getParent() == null) { + // For a root node. + type.addAnnotation(new Annotation("Component")); + type.addAnnotation(new Annotation("Path", "\"/" + rn.getResourceName() + "\"")); } + resourceTypes.put(rn.getResourceHierarchy(), type); + + CompilationUnit cu = new CompilationUnit(type); + cu.addImport(new ImportDeclaration("java.util.*")); + if (rn.getResourceHierarchy().getParent() == null) { + // For a root node. + cu.addImport(new ImportDeclaration("javax.ws.rs.*")); + cu.addImport(new ImportDeclaration("javax.ws.rs.client.*")); + cu.addImport(new ImportDeclaration("javax.ws.rs.core.*")); + cu.addImport(new ImportDeclaration("org.springframework.stereotype.Component")); + cu.addImport(new ImportDeclaration("com.fasterxml.jackson.databind.ObjectMapper")); + cu.addImport(new ImportDeclaration("com.fasterxml.jackson.core.JsonProcessingException")); + } + codes.add(cu); } - for (Edge chToRes : rn.getInEdges()) { - for (Edge resToCh: chToRes.getSource().getInEdges()) { + + // Declare a client field and update methods from other resources. + if (rn.getResourceHierarchy().getParent() == null) { + // For a root resource + boolean bDeclareClientField = false; + for (Edge resToCh: rn.getOutEdges()) { DataFlowEdge re = (DataFlowEdge) resToCh; - ResourcePath srcRes = ((ResourceNode) re.getSource()).getOutSideResource(); - String srcResName = getComponentName(srcRes.getResourceHierarchy()); - if (((PushPullAttribute) re.getAttribute()).getOptions().get(0) != PushPullValue.PUSH) { - if (!bDeclareClientField) { - // Declare a client field to connect to the source resource of pull transfer. - type.addField(new FieldDeclaration(typeClient, "client", "ClientBuilder.newClient()")); - bDeclareClientField = true; - } - } else { - // Declare an update method in the type of the destination resource. - ArrayList vars = new ArrayList<>(); - String srcName = srcRes.getResourceName(); - Type srcType = srcRes.getResourceStateType(); - VariableDeclaration param = new VariableDeclaration(srcType, srcName); - param.addAnnotation(new Annotation("FormParam", "\"" + srcName + "\"")); - vars.add(param); - for (ResourcePath refRes: ((ChannelNode) re.getDestination()).getChannel().getReferenceResources()) { - if (!refRes.equals(rn.getOutSideResource())) { - param = new VariableDeclaration(refRes.getResourceStateType(), refRes.getResourceName()); - param.addAnnotation(new Annotation("FormParam", "\"" + refRes.getResourceName() + "\"")); - vars.add(param); + if (!bDeclareClientField && ((PushPullAttribute) re.getAttribute()).getOptions().get(0) == PushPullValue.PUSH) { + // Declare a client field to connect to the destination resource of push transfer. + type.addField(new FieldDeclaration(typeClient, "client", "ClientBuilder.newClient()")); + bDeclareClientField = true; + } + } + for (Edge chToRes : rn.getInEdges()) { + for (Edge resToCh: chToRes.getSource().getInEdges()) { + DataFlowEdge re = (DataFlowEdge) resToCh; + ResourcePath srcRes = ((ResourceNode) re.getSource()).getOutSideResource(); + String srcResName = getComponentName(srcRes.getResourceHierarchy()); + if (((PushPullAttribute) re.getAttribute()).getOptions().get(0) != PushPullValue.PUSH) { + if (!bDeclareClientField) { + // Declare a client field to connect to the source resource of pull transfer. + type.addField(new FieldDeclaration(typeClient, "client", "ClientBuilder.newClient()")); + bDeclareClientField = true; } - } - MethodDeclaration update = new MethodDeclaration("update" + srcResName, false, typeVoid, vars); - for (ChannelMember cm: ((ChannelNode) re.getDestination()).getChannel().getOutputChannelMembers()) { - if (rn.getInSideResources().contains(cm.getResource())) { - if (cm.getStateTransition().isRightUnary()) { - update.addAnnotation(new Annotation("PUT")); - } else { - update.addAnnotation(new Annotation("POST")); + } else { + // Declare an update method in the type of the destination resource. + ArrayList vars = new ArrayList<>(); + String srcName = srcRes.getResourceName(); + Type srcType = srcRes.getResourceStateType(); + VariableDeclaration param = new VariableDeclaration(srcType, srcName); + param.addAnnotation(new Annotation("FormParam", "\"" + srcName + "\"")); + vars.add(param); + for (ResourcePath refRes: ((ChannelNode) re.getDestination()).getChannel().getReferenceResources()) { + if (!refRes.equals(rn.getOutSideResource())) { + 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: ((ChannelNode) re.getDestination()).getChannel().getOutputChannelMembers()) { + if (rn.getInSideResources().contains(cm.getResource())) { + if (cm.getStateTransition().isRightUnary()) { + update.addAnnotation(new Annotation("PUT")); + } else { + update.addAnnotation(new Annotation("POST")); + } + } + } + if (re.getDestination().getIndegree() > 1) { + // 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. + ResourcePath cashRes = ((ResourceNode) re.getSource()).getOutSideResource(); + type.addField(new FieldDeclaration(cashRes.getResourceStateType(), srcName, getInitializer(cashRes))); + } + type.addMethod(update); } - if (re.getDestination().getIndegree() > 1) { - // 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. - ResourcePath cashRes = ((ResourceNode) re.getSource()).getOutSideResource(); - type.addField(new FieldDeclaration(cashRes.getResourceStateType(), srcName, getInitializer(cashRes))); - } - type.addMethod(update); } } } - } - -// // Declare a client field to connect to the source resource of reference transfer. -// if (!bDeclareClientField) { -// for (ChannelGenerator cg : model.getChannelGenerators()) { -// DataflowChannelGenerator dcg = ((DataflowChannelGenerator) cg); -// for (ChannelMember cm : dcg.getOutputChannelMembers()) { -// if (cm.getIdentifierTemplate().getResourceName().equals(type.getTypeName().toLowerCase())) { -// if (dcg.getReferenceChannelMembers().size() > 0) { -// // If there exists one or more reference channel member. -// type.addField(new FieldDeclaration(typeClient, "client", "ClientBuilder.newClient()")); -// bDeclareClientField = true; -// break; + +// // Declare a client field to connect to the source resource of reference transfer. +// if (!bDeclareClientField) { +// for (ChannelGenerator cg : model.getChannelGenerators()) { +// DataflowChannelGenerator dcg = ((DataflowChannelGenerator) cg); +// for (ChannelMember cm : dcg.getOutputChannelMembers()) { +// if (cm.getIdentifierTemplate().getResourceName().equals(type.getTypeName().toLowerCase())) { +// if (dcg.getReferenceChannelMembers().size() > 0) { +// // If there exists one or more reference channel member. +// type.addField(new FieldDeclaration(typeClient, "client", "ClientBuilder.newClient()")); +// bDeclareClientField = true; +// break; +// } // } // } +// if (bDeclareClientField) break; // } -// if (bDeclareClientField) break; // } -// } - - // Declare input methods in resources. - for (Channel ch : model.getIOChannels()) { - for (ChannelMember cm : ((DataTransferChannel) ch).getOutputChannelMembers()) { - if (rn.getInSideResources().contains(cm.getResource())) { - Expression message = cm.getStateTransition().getMessageExpression(); - if (message instanceof Term) { - // In each resource. - ArrayList rootParams = new ArrayList<>(); - String resourcePath = "\""; - int v = 1; - for (Selector selector: rn.getAllSelectors()) { - if (selector.getExpression() instanceof Variable) { - Variable var = (Variable) selector.getExpression(); - String paramName = var.getName(); - VariableDeclaration param = new VariableDeclaration(var.getType(), paramName); - param.addAnnotation(new Annotation("PathParam", "\"" + paramName + "\"")); - rootParams.add(param); - resourcePath += "/{" + paramName + "}"; - } else if (selector.getExpression() instanceof Term) { - Term var = (Term) selector.getExpression(); - String paramName = "v" + v; - VariableDeclaration param = new VariableDeclaration(var.getType(), paramName); - param.addAnnotation(new Annotation("PathParam", "\"" + paramName + "\"")); - rootParams.add(param); - resourcePath += "/{" + paramName + "}"; - } - v++; - } - resourcePath += "\""; - ArrayList resParams = new ArrayList<>(); - for (Variable var: message.getVariables().values()) { - String paramName = var.getName(); - VariableDeclaration param = new VariableDeclaration(var.getType(), paramName); - resParams.add(param); - param = new VariableDeclaration(var.getType(), paramName); - param.addAnnotation(new Annotation("FormParam", "\"" + paramName + "\"")); - rootParams.add(param); - } - - if (rn.getResourceHierarchy().getParent() != null) { - MethodDeclaration input = new MethodDeclaration(((Term) cm.getStateTransition().getMessageExpression()).getSymbol().getImplName(), - false, typeVoid, resParams); - type.addMethod(input); - } - - // For the root resource. - String str = ((Term) cm.getStateTransition().getMessageExpression()).getSymbol().getImplName(); - MethodDeclaration inputAccessor = new MethodDeclaration(str, false, typeVoid, rootParams); - if (cm.getStateTransition().isRightUnary()) { - inputAccessor.addAnnotation(new Annotation("PUT")); - } else { - inputAccessor.addAnnotation(new Annotation("POST")); - } - if (ch.getAllSelectors().size() > 0) { - inputAccessor.addAnnotation(new Annotation("Path", resourcePath)); - } - inputAccessors.put(rn.getResourceHierarchy(), inputAccessor); - } else if (message instanceof Variable) { - // In each resource. - if (rn.getResourceHierarchy().getParent() != null) { - MethodDeclaration input = new MethodDeclaration(((Variable) cm.getStateTransition().getMessageExpression()).getName(), - false, typeVoid, null); - type.addMethod(input); - } - - // For the root resource. - ArrayList rootParams = new ArrayList<>(); - String resourcePath = "\""; - int v = 1; - for (Selector selector: rn.getAllSelectors()) { - if (selector.getExpression() instanceof Variable) { - Variable var = (Variable) selector.getExpression(); - String paramName = var.getName(); - VariableDeclaration param = new VariableDeclaration(var.getType(), paramName); - param.addAnnotation(new Annotation("PathParam", "\"" + paramName + "\"")); - rootParams.add(param); - resourcePath += "/{" + paramName + "}"; - } else if (selector.getExpression() instanceof Term) { - Term var = (Term) selector.getExpression(); - String paramName = "v" + v; - VariableDeclaration param = new VariableDeclaration(var.getType(), paramName); - param.addAnnotation(new Annotation("PathParam", "\"" + paramName + "\"")); - rootParams.add(param); - resourcePath += "/{" + paramName + "}"; - } - v++; - } - resourcePath += "\""; - String str = ((Term) cm.getStateTransition().getMessageExpression()).getSymbol().getImplName(); - MethodDeclaration inputAccessor = new MethodDeclaration(str, false, typeVoid, rootParams); - if (cm.getStateTransition().isRightUnary()) { - inputAccessor.addAnnotation(new Annotation("PUT")); - } else { - inputAccessor.addAnnotation(new Annotation("POST")); - } - if (ch.getAllSelectors().size() > 0) { - inputAccessor.addAnnotation(new Annotation("Path", resourcePath)); - } - inputAccessors.put(rn.getResourceHierarchy(), inputAccessor); - } - } - } - } - - // Declare the field to store the state in the type of each resource. - if (((StoreAttribute) rn.getAttribute()).isStored()) { - ResourcePath res = rn.getOutSideResource(); - Set children = rn.getResourceHierarchy().getChildren(); - if (children == null || children.size() == 0) { - // leaf resource. - type.addField(new FieldDeclaration(getImplStateType(res.getResourceHierarchy()), "value", getInitializer(res))); - } else { - ResourceHierarchy child = children.iterator().next(); - if (children.size() == 1 && child.getNumParameters() > 0) { - // map or list. + + // Declare the field to store the state in the type of each resource. + if (((StoreAttribute) rn.getAttribute()).isStored()) { + ResourcePath res = rn.getOutSideResource(); + Set children = rn.getResourceHierarchy().getChildren(); + if (children == null || children.size() == 0) { + // leaf resource. type.addField(new FieldDeclaration(getImplStateType(res.getResourceHierarchy()), "value", getInitializer(res))); } else { - // class - for (ResourceHierarchy c: children) { - String childTypeName = getComponentName(c); - Type childType = null; - if ((c.getChildren() == null || c.getChildren().size() == 0) && c.getNumParameters() == 0) { - // The child does not have a component. - childType = c.getResourceStateType(); - } else { - // The child has a component. - childType = new Type(childTypeName, childTypeName); + ResourceHierarchy child = children.iterator().next(); + if (children.size() == 1 && child.getNumParameters() > 0) { + // map or list. + type.addField(new FieldDeclaration(getImplStateType(res.getResourceHierarchy()), "value", getInitializer(res))); + } else { + // class + for (ResourceHierarchy c: children) { + String childTypeName = getComponentName(c); + Type childType = null; + if ((c.getChildren() == null || c.getChildren().size() == 0) && c.getNumParameters() == 0) { + // The child does not have a component. + childType = c.getResourceStateType(); + } else { + // The child has a component. + childType = new Type(childTypeName, childTypeName); + } + String fieldName = toVariableName(childTypeName); + type.addField(new FieldDeclaration(childType, fieldName, getInitializer(res))); } - String fieldName = childTypeName.substring(0, 1).toLowerCase() + childTypeName.substring(1); - type.addField(new FieldDeclaration(childType, fieldName, getInitializer(res))); } } } + + // Declare the getter methods to obtain the children resources. + for (ResourceNode child: rn.getChildren()) { + if (generatesComponent(child.getResourceHierarchy())) { + // The child generates a component. + List pathParams = new ArrayList<>(); + int v = 1; + for (Selector pathParam: child.getSelectors()) { + if (pathParam.getExpression() instanceof Variable) { + Variable var = (Variable) pathParam.getExpression(); + pathParams.add(new VariableDeclaration(var.getType(), var.getName())); + } else if (pathParam.getExpression() instanceof Term) { + Term var = (Term) pathParam.getExpression(); + pathParams.add(new VariableDeclaration(var.getType(), "v" + v)); + } + v++; + } + String childCompName = getComponentName(child.getResourceHierarchy()); + Type childType = new Type(childCompName, childCompName); + MethodDeclaration childGetter = null; + if (pathParams.size() == 0) { + childGetter = new MethodDeclaration("get" + childCompName, childType); + } else { + childGetter = new MethodDeclaration("get" + childCompName, false, childType, pathParams); + } + type.addMethod(childGetter); + } + } } - // Declare the getter method to obtain the state in the type of each resource. - MethodDeclaration stateGetter = new MethodDeclaration("getValue", getImplStateType(rn.getResourceHierarchy())); - if (rn.getResourceHierarchy().getParent() == null) { - // Since this getter is also an accessor. - stateGetter.addAnnotation(new Annotation("Produces", "MediaType.APPLICATION_JSON")); - stateGetter.addAnnotation(new Annotation("GET")); - } - type.addMethod(stateGetter); - - // Declare the getter methods to obtain a child of the resource. - for (ResourceNode child: rn.getChildren()) { + // Declare the getter method to obtain the resource state in the component of each resource. + if (type != null) { + // A component is created for this resource. + MethodDeclaration stateGetter = new MethodDeclaration("getValue", getImplStateType(rn.getResourceHierarchy())); + if (rn.getResourceHierarchy().getParent() == null) { + // Since this getter is also an accessor. + stateGetter.addAnnotation(new Annotation("Produces", "MediaType.APPLICATION_JSON")); + stateGetter.addAnnotation(new Annotation("GET")); + } + type.addMethod(stateGetter); + } else { + // No component is created for this resource. List pathParams = new ArrayList<>(); int v = 1; - for (Selector pathParam: child.getSelectors()) { + for (Selector pathParam: rn.getSelectors()) { if (pathParam.getExpression() instanceof Variable) { Variable var = (Variable) pathParam.getExpression(); pathParams.add(new VariableDeclaration(var.getType(), var.getName())); @@ -385,30 +329,22 @@ } v++; } - String childTypeName = getComponentName(child.getResourceHierarchy()); - Type childType = null; - if ((child.getResourceHierarchy().getChildren() == null || child.getResourceHierarchy().getChildren().size() == 0) - && child.getResourceHierarchy().getNumParameters() == 0) { - // The child does not have a component. - childType = child.getResourceStateType(); - } else { - // The child has a component. - childType = new Type(childTypeName, childTypeName); - } - MethodDeclaration childGetter = null; + String resCompName = getComponentName(rn.getResourceHierarchy()); + Type resType = getImplStateType(rn.getResourceHierarchy()); + MethodDeclaration stateGetter = null; if (pathParams.size() == 0) { - childGetter = new MethodDeclaration("get" + childTypeName, childType); + stateGetter = new MethodDeclaration("get" + resCompName, resType); } else { - childGetter = new MethodDeclaration("get" + childTypeName, false, childType, pathParams); + stateGetter = new MethodDeclaration("get" + resCompName, false, resType, pathParams); } - type.addMethod(childGetter); + getters.add(new AbstractMap.SimpleEntry(rn.getParent().getResourceHierarchy(), stateGetter)); } - // Declare the getter accessor to obtain the resource state in the root resource. + // Declare the getter accessor in the root resource. if (rn.getResourceHierarchy().getParent() != null) { // For a non-root resource MethodDeclaration getterAccessor = null; - List params = new ArrayList<>(); + List mainGetterParams = new ArrayList<>(); String resourcePath = "\""; int v = 1; for (Selector pathParam: rn.getAllSelectors()) { @@ -417,24 +353,24 @@ String paramName = var.getName(); VariableDeclaration param = new VariableDeclaration(var.getType(), paramName); param.addAnnotation(new Annotation("PathParam", "\"" + paramName + "\"")); - params.add(param); + mainGetterParams.add(param); resourcePath += "/{" + paramName + "}"; } else if (pathParam.getExpression() instanceof Term) { Term var = (Term) pathParam.getExpression(); String paramName = "v" + v; VariableDeclaration param = new VariableDeclaration(var.getType(), paramName); param.addAnnotation(new Annotation("PathParam", "\"" + paramName + "\"")); - params.add(param); + mainGetterParams.add(param); resourcePath += "/{" + paramName + "}"; } v++; } resourcePath += "\""; - if (params.size() > 0) { + if (mainGetterParams.size() > 0) { getterAccessor = new MethodDeclaration("get" + getComponentName(rn.getResourceHierarchy()) + "Value", false, getImplStateType(rn.getResourceHierarchy()), - params); + mainGetterParams); } else { getterAccessor = new MethodDeclaration("get" + getComponentName(rn.getResourceHierarchy()) + "Value", getImplStateType(rn.getResourceHierarchy())); @@ -450,8 +386,175 @@ } getterAccessors.put(rn.getResourceHierarchy(), getterAccessor); } + + // Declare the input method in each resource and the root resource. + for (Channel ch : model.getIOChannels()) { + for (ChannelMember cm : ((DataTransferChannel) ch).getOutputChannelMembers()) { + if (rn.getInSideResources().contains(cm.getResource())) { + Expression message = cm.getStateTransition().getMessageExpression(); + if (message instanceof Term) { + // In each resource. + ArrayList resInputParams = new ArrayList<>(); + ArrayList rootInputParams = new ArrayList<>(); + String resourcePath = "\""; + int v = 1; + for (Selector selector: rn.getSelectors()) { + if (selector.getExpression() instanceof Variable) { + Variable var = (Variable) selector.getExpression(); + String paramName = var.getName(); + VariableDeclaration param = new VariableDeclaration(var.getType(), paramName); + resInputParams.add(param); + param = new VariableDeclaration(var.getType(), paramName); + param.addAnnotation(new Annotation("PathParam", "\"" + paramName + "\"")); + rootInputParams.add(param); + resourcePath += "/{" + paramName + "}"; + } else if (selector.getExpression() instanceof Term) { + Term var = (Term) selector.getExpression(); + String paramName = "v" + v; + VariableDeclaration param = new VariableDeclaration(var.getType(), paramName); + resInputParams.add(param); + param = new VariableDeclaration(var.getType(), paramName); + param.addAnnotation(new Annotation("PathParam", "\"" + paramName + "\"")); + rootInputParams.add(param); + resourcePath += "/{" + paramName + "}"; + } + v++; + } + if (rn.getParent() != null) { + for (Selector selector: rn.getParent().getAllSelectors()) { + if (selector.getExpression() instanceof Variable) { + Variable var = (Variable) selector.getExpression(); + String paramName = var.getName(); + VariableDeclaration param = new VariableDeclaration(var.getType(), paramName); + param.addAnnotation(new Annotation("PathParam", "\"" + paramName + "\"")); + rootInputParams.add(param); + resourcePath += "/{" + paramName + "}"; + } else if (selector.getExpression() instanceof Term) { + Term var = (Term) selector.getExpression(); + String paramName = "v" + v; + VariableDeclaration param = new VariableDeclaration(var.getType(), paramName); + param.addAnnotation(new Annotation("PathParam", "\"" + paramName + "\"")); + rootInputParams.add(param); + resourcePath += "/{" + paramName + "}"; + } + v++; + } + } + resourcePath += "\""; + for (Variable var: message.getVariables().values()) { + String paramName = var.getName(); + VariableDeclaration param = new VariableDeclaration(var.getType(), paramName); + resInputParams.add(param); + param = new VariableDeclaration(var.getType(), paramName); + param.addAnnotation(new Annotation("FormParam", "\"" + paramName + "\"")); + rootInputParams.add(param); + } + + if (rn.getResourceHierarchy().getParent() != null && rn.getResourceHierarchy().getParent().getParent() != null) { + MethodDeclaration input = new MethodDeclaration(((Term) cm.getStateTransition().getMessageExpression()).getSymbol().getImplName(), + false, typeVoid, resInputParams); + if (type != null) { + // A component is created for this resource. + type.addMethod(input); + } else { + // No component is created for this resource. + inputs.add(new AbstractMap.SimpleEntry(rn.getParent().getResourceHierarchy(), input)); + } + } + + // For the root resource. + String str = ((Term) cm.getStateTransition().getMessageExpression()).getSymbol().getImplName(); + MethodDeclaration inputAccessor = new MethodDeclaration(str, false, typeVoid, rootInputParams); + if (cm.getStateTransition().isRightUnary()) { + inputAccessor.addAnnotation(new Annotation("PUT")); + } else { + inputAccessor.addAnnotation(new Annotation("POST")); + } + if (ch.getAllSelectors().size() > 0) { + inputAccessor.addAnnotation(new Annotation("Path", resourcePath)); + } + inputAccessors.put(rn.getResourceHierarchy(), inputAccessor); + } else if (message instanceof Variable) { + // In each resource. + ArrayList resInputParams = new ArrayList<>(); + int v = 1; + for (Selector selector: rn.getSelectors()) { + if (selector.getExpression() instanceof Variable) { + Variable var = (Variable) selector.getExpression(); + String paramName = var.getName(); + VariableDeclaration param = new VariableDeclaration(var.getType(), paramName); + resInputParams.add(param); + } else if (selector.getExpression() instanceof Term) { + Term var = (Term) selector.getExpression(); + String paramName = "v" + v; + VariableDeclaration param = new VariableDeclaration(var.getType(), paramName); + resInputParams.add(param); + } + v++; + } + if (rn.getResourceHierarchy().getParent() != null && rn.getResourceHierarchy().getParent().getParent() != null) { + MethodDeclaration input = new MethodDeclaration(((Variable) cm.getStateTransition().getMessageExpression()).getName(), + false, typeVoid, null); + if (type != null) { + // A component is created for this resource. + type.addMethod(input); + } else { + // No component is created for this resource. + inputs.add(new AbstractMap.SimpleEntry(rn.getParent().getResourceHierarchy(), input)); + } + } + + // For the root resource. + ArrayList rootInputParams = new ArrayList<>(); + String resourcePath = "\""; + v = 1; + for (Selector selector: rn.getAllSelectors()) { + if (selector.getExpression() instanceof Variable) { + Variable var = (Variable) selector.getExpression(); + String paramName = var.getName(); + VariableDeclaration param = new VariableDeclaration(var.getType(), paramName); + param.addAnnotation(new Annotation("PathParam", "\"" + paramName + "\"")); + rootInputParams.add(param); + resourcePath += "/{" + paramName + "}"; + } else if (selector.getExpression() instanceof Term) { + Term var = (Term) selector.getExpression(); + String paramName = "v" + v; + VariableDeclaration param = new VariableDeclaration(var.getType(), paramName); + param.addAnnotation(new Annotation("PathParam", "\"" + paramName + "\"")); + rootInputParams.add(param); + resourcePath += "/{" + paramName + "}"; + } + v++; + } + resourcePath += "\""; + String str = ((Term) cm.getStateTransition().getMessageExpression()).getSymbol().getImplName(); + MethodDeclaration inputAccessor = new MethodDeclaration(str, false, typeVoid, rootInputParams); + if (cm.getStateTransition().isRightUnary()) { + inputAccessor.addAnnotation(new Annotation("PUT")); + } else { + inputAccessor.addAnnotation(new Annotation("POST")); + } + if (ch.getAllSelectors().size() > 0) { + inputAccessor.addAnnotation(new Annotation("Path", resourcePath)); + } + inputAccessors.put(rn.getResourceHierarchy(), inputAccessor); + } + } + } + } } + // Add leaf getter methods to the parent components. + for (Map.Entry entry: getters) { + resourceTypes.get(entry.getKey()).addMethod(entry.getValue()); + } + + // Add leaf input methods to the parent components. + for (Map.Entry entry: inputs) { + resourceTypes.get(entry.getKey()).addMethod(entry.getValue()); + } + + // Add accessors. for (ResourceHierarchy rootRes: model.getResourceHierarchies()) { if (rootRes.getParent() == null) { // root resource @@ -462,7 +565,7 @@ rootType.addMethod(getterAccessors.get(res)); } } - // Add inout accessors. + // Add input accessors. for (ResourceHierarchy res: inputAccessors.keySet()) { if (rootRes.isAncestorOf(res)) { rootType.addMethod(inputAccessors.get(res)); @@ -624,7 +727,7 @@ String typeName = getComponentName(curPath.getResourceHierarchy()); if (getter == null && from == null) { // root resource - String fieldName = typeName.substring(0, 1).toLowerCase() + typeName.substring(1); + String fieldName = toVariableName(typeName); getter = new Field(fieldName, new Type(typeName, typeName)); } else { Term newGetter = new Term(new Symbol("get" + typeName, -1, Symbol.Type.METHOD)); @@ -647,8 +750,7 @@ } } - if (target.getResourceHierarchy().getNumParameters() > 0 - || (target.getResourceHierarchy().getChildren() != null && target.getResourceHierarchy().getChildren().size() > 0)) { + if (generatesComponent(target.getResourceHierarchy())) { Term newGetter = new Term(new Symbol("getValue", 1, Symbol.Type.METHOD)); newGetter.addChild(getter); getter = newGetter; diff --git a/AlgebraicDataflowArchitectureModel/src/generators/JerseyMethodBodyGenerator.java b/AlgebraicDataflowArchitectureModel/src/generators/JerseyMethodBodyGenerator.java index 11c07fa..b239cc9 100644 --- a/AlgebraicDataflowArchitectureModel/src/generators/JerseyMethodBodyGenerator.java +++ b/AlgebraicDataflowArchitectureModel/src/generators/JerseyMethodBodyGenerator.java @@ -348,7 +348,7 @@ composerSub.setType(DataConstraintModel.typeMap); for (ResourceHierarchy child: resource.getChildren()) { String childTypeName = JerseyCodeGenerator.getComponentName(child); - String fieldName = childTypeName.substring(0, 1).toLowerCase() + childTypeName.substring(1); + String fieldName = JerseyCodeGenerator.toVariableName(childTypeName); Term childGetter = null; if ((child.getChildren() == null || child.getChildren().size() == 0) && child.getNumParameters() == 0) { // the child is not a class @@ -401,84 +401,99 @@ childGetter.addStatement("return " + returnValue+ ";"); } else { String fieldName = JerseyCodeGenerator.getComponentName(child); - String returnValue = fieldName.substring(0, 1).toLowerCase() + fieldName.substring(1); + String returnValue = JerseyCodeGenerator.toVariableName(fieldName); childGetter.addStatement("return this." + returnValue + ";"); } } } - } - - // methods for input events - Map> ioChannelsAndMembers = getIOChannelsAndMembers(resource, model); - for (Map.Entry> entry: ioChannelsAndMembers.entrySet()) { - Set outs = entry.getValue(); - for (ChannelMember out: outs) { - MethodDeclaration input = getInputMethod(type, out); - if (input != null) { - // In each resource - Expression updateExp = entry.getKey().deriveUpdateExpressionOf(out, JerseyCodeGenerator.pushAccessor); - String[] sideEffects = new String[] {""}; - String newState = updateExp.toImplementation(sideEffects); - if (resource.getNumParameters() == 0 || resource.getChildren() == null || resource.getChildren().size() == 0) { - String updateStatement; - if (updateExp instanceof Term && ((Term) updateExp).getSymbol().isImplWithSideEffect()) { - updateStatement = sideEffects[0]; - } else { - updateStatement = sideEffects[0] + "this.value = " + newState + ";"; + } + } + + // methods for input events + Map> ioChannelsAndMembers = getIOChannelsAndMembers(resource, model); + for (Map.Entry> entry: ioChannelsAndMembers.entrySet()) { + Set outs = entry.getValue(); + for (ChannelMember out: outs) { + MethodDeclaration input = null; + if (JavaCodeGenerator.generatesComponent(resource)) { + // A component is generated for this resource. + input = getInputMethod(type, out); + } else { + // No component is generated for this resource. + ResourceHierarchy parent = resource.getParent(); + if (parent != null) { + TypeDeclaration parentType = typeMap.get(JavaCodeGenerator.getComponentName(parent)); + input = getInputMethod(parentType, out); + } + } + if (input != null) { + // In each resource + Expression updateExp = entry.getKey().deriveUpdateExpressionOf(out, JerseyCodeGenerator.pushAccessor); + String[] sideEffects = new String[] {""}; + String newState = updateExp.toImplementation(sideEffects); + if (JavaCodeGenerator.generatesComponent(resource)) { + String updateStatement; + if (updateExp instanceof Term && ((Term) updateExp).getSymbol().isImplWithSideEffect()) { + updateStatement = sideEffects[0]; + } else { + updateStatement = sideEffects[0] + "this.value = " + newState + ";"; + } + if (input.getBody() == null || !input.getBody().getStatements().contains(updateStatement)) { + input.addFirstStatement(updateStatement); + } + } else { + String updateStatement = null; + if (updateExp instanceof Term && ((Term) updateExp).getSymbol().isImplWithSideEffect()) { + // ToDo. + updateStatement = sideEffects[0]; + } else { + if (DataConstraintModel.typeList.isAncestorOf(resource.getParent().getResourceStateType())) { + Term selector = new Term(DataConstraintModel.set); + selector.addChild(new Field("value")); + selector.addChild(new Variable(input.getParameters().get(input.getParameters().size() - 2).getName())); + selector.addChild(new Constant(newState)); + String[] sideEffects2 = new String[] {""}; + String newList = selector.toImplementation(sideEffects2); + updateStatement = sideEffects[0] + sideEffects2[0]; + } else if (DataConstraintModel.typeMap.isAncestorOf(resource.getParent().getResourceStateType())) { + Term selector = new Term(DataConstraintModel.set); + selector.addChild(new Field("value")); + selector.addChild(new Variable(input.getParameters().get(input.getParameters().size() - 2).getName())); + selector.addChild(new Constant(newState)); + String[] sideEffects2 = new String[] {""}; + String newList = selector.toImplementation(sideEffects2); + updateStatement = sideEffects[0] + sideEffects2[0]; } - if (input.getBody() == null || !input.getBody().getStatements().contains(updateStatement)) { + if (updateStatement != null && (input.getBody() == null || !input.getBody().getStatements().contains(updateStatement))) { input.addFirstStatement(updateStatement); } - } else { - String updateStatement = null; - if (updateExp instanceof Term && ((Term) updateExp).getSymbol().isImplWithSideEffect()) { - // ToDo. - updateStatement = sideEffects[0]; - } else { - if (DataConstraintModel.typeList.isAncestorOf(resource.getParent().getResourceStateType())) { - Term selector = new Term(DataConstraintModel.set); - selector.addChild(new Field("value")); - selector.addChild(new Variable(input.getParameters().get(input.getParameters().size() - 2).getName())); - selector.addChild(new Constant(newState)); - String[] sideEffects2 = new String[] {""}; - String newList = selector.toImplementation(sideEffects2); - updateStatement = sideEffects[0] + sideEffects2[0]; - } else if (DataConstraintModel.typeMap.isAncestorOf(resource.getParent().getResourceStateType())) { - Term selector = new Term(DataConstraintModel.set); - selector.addChild(new Field("value")); - selector.addChild(new Variable(input.getParameters().get(input.getParameters().size() - 2).getName())); - selector.addChild(new Constant(newState)); - String[] sideEffects2 = new String[] {""}; - String newList = selector.toImplementation(sideEffects2); - updateStatement = sideEffects[0] + sideEffects2[0]; - } - if (updateStatement != null && (input.getBody() == null || !input.getBody().getStatements().contains(updateStatement))) { - input.addFirstStatement(updateStatement); - } - } } - - if (out.getResource().getParent() != null) { - // In the root resource - MethodDeclaration inputAccessor = getMethod(typeMap.get(JerseyCodeGenerator.getComponentName(resource.getRoot())), input.getName()); - if (inputAccessor != null) { - Expression resExp = JerseyCodeGenerator.pullAccessor.getCurrentStateAccessorFor(out.getResource(), out.getResource().getRoot()); - if (resExp instanceof Term) { - // remove '.getValue()' - resExp = ((Term) resExp).getChild(0); + } + + if (out.getResource().getParent() != null && out.getResource().getParent().getParent() != null) { + // In the root resource + MethodDeclaration inputAccessor = getMethod(typeMap.get(JerseyCodeGenerator.getComponentName(resource.getRoot())), input.getName()); + if (inputAccessor != null) { + Expression resExp = JerseyCodeGenerator.pullAccessor.getCurrentStateAccessorFor(out.getResource(), out.getResource().getRoot()); + String args = ""; + String delimiter = ""; + if (resExp instanceof Term) { + // to access the parent + if (((Term) resExp).getChildren().size() > 1 && ((Term) resExp).getChild(1) instanceof Variable) { + args += delimiter + ((Variable)((Term) resExp).getChild(1)).getName(); + delimiter = ", "; } - String resourceAccess = resExp.toImplementation(new String[] {null}); - String args = ""; - String delimiter = ""; - if (out.getStateTransition().getMessageExpression() instanceof Term) { - Term message = (Term) out.getStateTransition().getMessageExpression(); - for (Variable var: message.getVariables().values()) { - args += delimiter + var.getName(); - delimiter = ", "; - } - } - inputAccessor.addStatement(resourceAccess + "." + input.getName() + "(" + args + ");"); + resExp = ((Term) resExp).getChild(0); } + String resourceAccess = resExp.toImplementation(new String[] {null}); + if (out.getStateTransition().getMessageExpression() instanceof Term) { + Term message = (Term) out.getStateTransition().getMessageExpression(); + for (Variable var: message.getVariables().values()) { + args += delimiter + var.getName(); + delimiter = ", "; + } + } + inputAccessor.addStatement(resourceAccess + "." + input.getName() + "(" + args + ");"); } } }