diff --git a/AlgebraicDataflowArchitectureModel/src/generators/CodeGeneratorFromDataFlowGraph.java b/AlgebraicDataflowArchitectureModel/src/generators/CodeGeneratorFromDataFlowGraph.java index ae86204..722a4a7 100644 --- a/AlgebraicDataflowArchitectureModel/src/generators/CodeGeneratorFromDataFlowGraph.java +++ b/AlgebraicDataflowArchitectureModel/src/generators/CodeGeneratorFromDataFlowGraph.java @@ -66,6 +66,7 @@ if (generatesComponent(resourceNode.getResourceHierarchy())) { // A component will be generated for this resource. String resourceName = getComponentName(resourceNode.getResourceHierarchy(), langSpec); + Type resStateType = getImplStateType(resourceNode.getResourceHierarchy(), langSpec); component = resourceComponents.get(resourceNode.getResourceHierarchy()); List depends = new ArrayList<>(); if (component == null) { @@ -92,6 +93,20 @@ } else { resourceConstructors.put(resourceNode.getResourceHierarchy(), constructor); } + + // Declare the field to store the state in this resource. + if (((StoreAttribute) resourceNode.getAttribute()).isStored()) { + declareStateField(resourceNode, resourceName, component, resStateType, constructorParams, langSpec); + } + + // Declare the getter method in this resource to obtain the state. + MethodDeclaration stateGetter = declareStateGetterMethod(resourceNode, component, resStateType, langSpec); + + // Declare the accessor method in the main component to call the getter method. + declareAccessorInMainComponent(mainComponent, resourceNode, stateGetter, langSpec); + + // Declare the getter methods in this resource to obtain the children resources. + declareChildGetterMethod(resourceNode, component, langSpec); } } } @@ -104,16 +119,7 @@ TypeDeclaration component = null; TypeDeclaration parentComponent = null; if (generatesComponent(resourceNode.getResourceHierarchy())) { - String resourceName = getComponentName(resourceNode.getResourceHierarchy(), langSpec); - component = resourceComponents.get(resourceNode.getResourceHierarchy()); - - // Declare the field in this resource to store the state. - if (((StoreAttribute) resourceNode.getAttribute()).isStored()) { - declareStateField(resourceNode, resourceName, component, resStateType, constructorParams, langSpec); - } - - // Declare the getter methods in this resource to obtain the children resources. - declareChildGetterMethod(resourceNode, component, langSpec); + component = resourceComponents.get(resourceNode.getResourceHierarchy()); } if (resourceNode.getResourceHierarchy().getParent() != null) { parentComponent = resourceComponents.get(resourceNode.getResourceHierarchy().getParent()); @@ -137,10 +143,14 @@ } // Declare the getter method in this resource to obtain the state. - MethodDeclaration stateGetter = declareStateGetterMethod(resourceNode, component, parentComponent, resStateType, langSpec); - - // Declare the accessor method in the main component to call the getter method. - declareAccessorInMainComponent(mainComponent, resourceNode, stateGetter, langSpec); + if (component == null) { + MethodDeclaration stateGetter = declareStateGetterMethodInParent(resourceNode, parentComponent, resStateType, langSpec); + + if (stateGetter != null) { + // Declare the accessor method in the main component to call the getter method. + declareAccessorInMainComponent(mainComponent, resourceNode, stateGetter, langSpec); + } + } // Declare input methods in this component and the main component. Map.Entry, Map>> initStatementsAndInputUpdates = declareInputMethodsInThisAndMainComponents(resourceNode, component, parentComponent, mainComponent, model, langSpec); @@ -477,132 +487,148 @@ } } - private MethodDeclaration declareStateGetterMethod(ResourceNode resourceNode, TypeDeclaration component, TypeDeclaration parentComponent, Type resStateType, ILanguageSpecific langSpec) { + + private MethodDeclaration declareStateGetterMethod(ResourceNode resourceNode, TypeDeclaration component, Type resStateType, ILanguageSpecific langSpec) { // Declare the getter method of the resource state. - 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 (parentComponent != null) { - parentComponent.addMethod(stateGetter); - } - } + MethodDeclaration stateGetter = langSpec.newMethodDeclaration(getterOfResourceState, resStateType); + component.addMethod(stateGetter); if (((StoreAttribute) resourceNode.getAttribute()).isStored()) { - if (component != null) { - // A component is created for this resource. - fillStateGetterMethod(stateGetter, resourceNode.getResourceHierarchy(), resStateType, langSpec); - } else { - // No component is created for this resource. - fillChildGetterMethod(stateGetter, resourceNode.getResourceHierarchy(), resourceNode.getResourceHierarchy().getParent().getResourceStateType(), langSpec); - } + 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()) { - DataTransferChannel ch2 = ((ChannelNode) chToRes.getSource()).getChannel(); - for (Edge resToCh: chToRes.getSource().getInEdges()) { - DataFlowEdge dIn = (DataFlowEdge) resToCh; - ChannelMember in = null; - for (ChannelMember cm: ch2.getInputChannelMembers()) { - if (cm.getResource().equals(((ResourceNode) dIn.getSource()).getOutSideResource())) { - in = cm; - break; - } - } - if (((PushPullAttribute) dIn.getAttribute()).getOptions().get(0) == PushPullValue.PUSH) { - // PUSH transfer - isContainedPush = true; - inputResourceToStateAccessor.put(in, getPushAccessor()); - } else { - // PULL transfer - inputResourceToStateAccessor.put(in, getPullAccessor()); - ch = ((ChannelNode) resToCh.getDestination()).getChannel(); // pull containing input side channel is always one. - } - } - } - // for reference channel members. - for (ChannelMember c: ch.getReferenceChannelMembers()) { - inputResourceToStateAccessor.put(c, 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(); - } + addOtherGetterInvocationsToStateGatter(stateGetter, resourceNode, langSpec); } return stateGetter; } + private MethodDeclaration declareStateGetterMethodInParent(ResourceNode resourceNode, TypeDeclaration parentComponent, Type resStateType, ILanguageSpecific langSpec) { + // Check duplication. + String getterName = getterPrefix + getComponentName(resourceNode.getResourceHierarchy(), langSpec); + for (MethodDeclaration method: parentComponent.getMethods()) { + if (method.getName().equals(getterName)) return null; + } + + // Declare the getter method of the resource state. + 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++; + } + MethodDeclaration stateGetter = null; + if (getterParams.size() == 0) { + stateGetter = new MethodDeclaration(getterName, resStateType); + } else { + stateGetter = new MethodDeclaration(getterName, false, resStateType, getterParams); + } + if (parentComponent != null) { + parentComponent.addMethod(stateGetter); + } + + if (((StoreAttribute) resourceNode.getAttribute()).isStored()) { + fillChildGetterMethod(stateGetter, resourceNode.getResourceHierarchy(), resourceNode.getResourceHierarchy().getParent().getResourceStateType(), langSpec); + } else { + addOtherGetterInvocationsToStateGatter(stateGetter, resourceNode, langSpec); + } + + return stateGetter; + } + + private void addOtherGetterInvocationsToStateGatter(MethodDeclaration stateGetter, ResourceNode resourceNode, + ILanguageSpecific langSpec) { + boolean isContainedPush = false; + DataTransferChannel ch = null; + HashMap inputResourceToStateAccessor = new HashMap<>(); + for (Edge chToRes: resourceNode.getInEdges()) { + DataTransferChannel ch2 = ((ChannelNode) chToRes.getSource()).getChannel(); + for (Edge resToCh: chToRes.getSource().getInEdges()) { + DataFlowEdge dIn = (DataFlowEdge) resToCh; + ChannelMember in = null; + for (ChannelMember cm: ch2.getInputChannelMembers()) { + if (cm.getResource().equals(((ResourceNode) dIn.getSource()).getOutSideResource())) { + in = cm; + break; + } + } + if (((PushPullAttribute) dIn.getAttribute()).getOptions().get(0) == PushPullValue.PUSH) { + // PUSH transfer + isContainedPush = true; + inputResourceToStateAccessor.put(in, getPushAccessor()); + } else { + // PULL transfer + inputResourceToStateAccessor.put(in, getPullAccessor()); + ch = ((ChannelNode) resToCh.getDestination()).getChannel(); // pull containing input side channel is always one. + } + } + } + // for reference channel members. + for (ChannelMember c: ch.getReferenceChannelMembers()) { + inputResourceToStateAccessor.put(c, 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(); + } + } + private void declareChildGetterMethod(ResourceNode resourceNode, TypeDeclaration component, ILanguageSpecific langSpec) { // Declare the getter methods in this resource to obtain the children resources. + Set children = new HashSet<>(); for (ResourceNode child: resourceNode.getChildren()) { if (generatesComponent(child.getResourceHierarchy())) { // A component for the child is generated. - 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)); + if (!children.contains(child.getResourceHierarchy())) { + children.add(child.getResourceHierarchy()); + 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 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); } } }