diff --git a/AlgebraicDataflowArchitectureModel/src/generators/CodeGenerator.java b/AlgebraicDataflowArchitectureModel/src/generators/CodeGenerator.java index eb84521..13c6394 100644 --- a/AlgebraicDataflowArchitectureModel/src/generators/CodeGenerator.java +++ b/AlgebraicDataflowArchitectureModel/src/generators/CodeGenerator.java @@ -392,12 +392,12 @@ protected void declareAccessorInMainComponent(TypeDeclaration mainComponent, ResourceNode accessRes, MethodDeclaration stateGetter, ILanguageSpecific langSpec) { List mainGetterParams = new ArrayList<>(); int v = 1; - for (Selector selector: accessRes.getAllSelectors()) { - if (selector.getExpression() instanceof Variable) { - Variable var = (Variable) selector.getExpression(); + for (Expression param: accessRes.getOutSideResource().getPathParams()) { + if (param instanceof Variable) { + Variable var = (Variable) param; mainGetterParams.add(langSpec.newVariableDeclaration(var.getType(), var.getName())); - } else if (selector.getExpression() instanceof Term) { - Term var = (Term) selector.getExpression(); + } else if (param instanceof Term) { + Term var = (Term) param; mainGetterParams.add(new VariableDeclaration(var.getType(), "v" + v)); } v++; diff --git a/AlgebraicDataflowArchitectureModel/src/generators/CodeGeneratorFromDataFlowGraph.java b/AlgebraicDataflowArchitectureModel/src/generators/CodeGeneratorFromDataFlowGraph.java index c18bfc2..5c7a65b 100644 --- a/AlgebraicDataflowArchitectureModel/src/generators/CodeGeneratorFromDataFlowGraph.java +++ b/AlgebraicDataflowArchitectureModel/src/generators/CodeGeneratorFromDataFlowGraph.java @@ -76,8 +76,8 @@ CompilationUnit cu = langSpec.newCompilationUnit(component); codes.add(cu); - // Declare the constructor and the fields to refer to other resources. - MethodDeclaration constructor = declareConstructorAndFieldsToReferToResources(resourceNode, component, dependedRootComponentGraph, depends, langSpec); + // Declare the constructor. + MethodDeclaration constructor = declareConstructor(resourceNode, component, dependedRootComponentGraph, depends, langSpec); if (resourceNode.getResourceHierarchy().getParent() == null) { // For each root resource @@ -88,7 +88,7 @@ // Declare the fields to refer to reference resources. declareFieldsToReferenceResources(model, resourceNode, component, constructor, depends, langSpec); - if (constructor.getParameters() == null) { + if (constructor.getParameters() == null || constructor.getParameters().size() == 0) { component.removeMethod(constructor); } else { resourceConstructors.put(resourceNode.getResourceHierarchy(), constructor); @@ -137,10 +137,8 @@ updateStatements.put(entry.getKey(), entry.getValue()); } - // Declare the state field and reference fields in the parent component. - if (component == null) { - declareFieldsInParentComponent(resourceNode, parentComponent, constructorParams, langSpec); - } + // Declare the fields to refer to other resources in the parent/this component, and the state field in the parent component. + declareFieldsToReferToOtherResourcesAndStateFieldInParentComponent(resourceNode, component, parentComponent, constructorParams, langSpec); // Declare the getter method in this resource to obtain the state. if (component == null) { @@ -200,7 +198,7 @@ if (constructor == null) { if (resourceComponents.get(resource) != null) { String resourceName = getComponentName(resource, langSpec); - constructor = new MethodDeclaration(resourceName, true); + constructor = langSpec.newMethodDeclaration(resourceName, true, null, null); Block body = new Block(); constructor.setBody(body); resourceComponents.get(resource).addMethod(constructor); @@ -267,42 +265,47 @@ method.addFirstStatement(updateStatement); } - private MethodDeclaration declareConstructorAndFieldsToReferToResources(ResourceNode resourceNode, TypeDeclaration component, Map> dependedRootComponentGraph, + private MethodDeclaration declareConstructor(ResourceNode resourceNode, TypeDeclaration component, Map> dependedRootComponentGraph, List depends, ILanguageSpecific langSpec) { // Declare a constructor in each component. - MethodDeclaration constructor = component.createConstructor(); + String resourceName = getComponentName(resourceNode.getResourceHierarchy(), langSpec); + MethodDeclaration constructor = langSpec.newMethodDeclaration(resourceName, true, null, null); Block block = new Block(); constructor.setBody(block); + component.addMethod(constructor); - // Declare fields in each component. (for data-flow graph) for (Edge resToCh: resourceNode.getOutEdges()) { DataTransferChannel ch = ((ChannelNode) resToCh.getDestination()).getChannel(); // Check if the input resource is outside of the channel scope. boolean outsideInputResource = false; for (ChannelMember cm: ch.getInputChannelMembers()) { - if (cm.getResource().getResourceHierarchy().equals(resourceNode.getResourceHierarchy()) && cm.isOutside()) { + if (cm.getResource().equals(resourceNode.getOutSideResource()) && cm.isOutside()) { outsideInputResource = true; // Regarded as pull transfer. break; } } - // Check if the output resource is outside of the channel scope. - boolean outsideOutputResource = false; - for (ChannelMember cm: ch.getOutputChannelMembers()) { - if (cm.getResource().getResourceHierarchy().equals(resourceNode.getOutSideResource().getResourceHierarchy()) && cm.isOutside()) { - outsideOutputResource = true; // Regarded as push transfer. - break; - } - } - if (((PushPullAttribute) ((DataFlowEdge) resToCh).getAttribute()).getOptions().get(0) == PushPullValue.PUSH && !outsideInputResource) { - for (Edge chToRes: resToCh.getDestination().getOutEdges()) { - // for PUSH transfer - if (chToRes.getDestination() instanceof ResourceNode) { - ResourceHierarchy dstRes = addReference(component, constructor, ((ResourceNode) chToRes.getDestination()).getOutSideResource().getResourceHierarchy(), langSpec); - if (outsideOutputResource) { - if (dstRes != null && dstRes.getParent() != null) { - // Reference to root resource. - addReference(component, constructor, dstRes.getRoot(), langSpec); - } + for (Edge chToRes: resToCh.getDestination().getOutEdges()) { + if (chToRes.getDestination() instanceof ResourceNode) { + ResourceHierarchy dstRes = ((ResourceNode) chToRes.getDestination()).getOutSideResource().getResourceHierarchy(); + // Check if the output resource is outside of the channel scope. + boolean outsideOutputResource = false; + for (ChannelMember cm: ch.getOutputChannelMembers()) { + if (((ResourceNode) chToRes.getDestination()).getInSideResources().contains(cm.getResource()) && cm.isOutside()) { + outsideOutputResource = true; // Regarded as push transfer. + break; + } + } + if ((((PushPullAttribute) ((DataFlowEdge) resToCh).getAttribute()).getOptions().get(0) == PushPullValue.PUSH && !outsideInputResource) || outsideOutputResource) { + // for PUSH transfer +// ResourceHierarchy dstRes = addReference(component, constructor, ((ResourceNode) chToRes.getDestination()).getOutSideResource().getResourceHierarchy(), langSpec); +// if (outsideOutputResource) { +// if (dstRes != null && dstRes.getParent() != null) { +// // Reference to root resource. +// addReference(component, constructor, dstRes.getRoot(), langSpec); +// } +// } + if (!generatesComponent(dstRes)) { + dstRes = dstRes.getParent(); } if (!depends.contains(dstRes)) depends.add(dstRes); } @@ -316,7 +319,7 @@ // Check if the input resource is outside of the channel scope. boolean outsideInputResource = false; for (ChannelMember cm: ch.getInputChannelMembers()) { - if (cm.getResource().getResourceHierarchy().equals(srcRes) && cm.isOutside()) { + if (cm.getResource().equals(((ResourceNode) resToCh.getSource()).getOutSideResource()) && cm.isOutside()) { outsideInputResource = true; // Regarded as pull transfer. break; } @@ -324,19 +327,22 @@ // Check if the output resource is outside of the channel scope. boolean outsideOutputResource = false; for (ChannelMember cm: ch.getOutputChannelMembers()) { - if (cm.getResource().getResourceHierarchy().equals(resourceNode.getOutSideResource().getResourceHierarchy()) && cm.isOutside()) { + if (resourceNode.getInSideResources().contains(cm.getResource()) && cm.isOutside()) { outsideOutputResource = true; // Regarded as push transfer. break; } } if ((((PushPullAttribute) ((DataFlowEdge) resToCh).getAttribute()).getOptions().get(0) != PushPullValue.PUSH && !outsideOutputResource) || outsideInputResource) { // for PULL transfer - srcRes = addReference(component, constructor, ((ResourceNode) resToCh.getSource()).getOutSideResource().getResourceHierarchy(), langSpec); - if (outsideInputResource) { - if (srcRes != null & srcRes.getParent() != null) { - // Reference to root resource. - addReference(component, constructor, srcRes.getRoot(), langSpec); - } +// srcRes = addReference(component, constructor, ((ResourceNode) resToCh.getSource()).getOutSideResource().getResourceHierarchy(), langSpec); +// if (outsideInputResource) { +// if (srcRes != null & srcRes.getParent() != null) { +// // Reference to root resource. +// addReference(component, constructor, srcRes.getRoot(), langSpec); +// } +// } + if (!generatesComponent(srcRes)) { + srcRes = srcRes.getParent(); } if (!depends.contains(srcRes)) depends.add(srcRes); } @@ -387,52 +393,99 @@ } } - private void declareFieldsInParentComponent(ResourceNode resourceNode, TypeDeclaration parentComponent, List> constructorParams, ILanguageSpecific langSpec) { - // Declare reference fields for push/pull data transfer. + private void declareFieldsToReferToOtherResourcesAndStateFieldInParentComponent(ResourceNode resourceNode, TypeDeclaration component, TypeDeclaration parentComponent, List> constructorParams, ILanguageSpecific langSpec) { + // Declare reference fields for push data transfer. boolean noPullTransfer = true; for (Edge resToCh : resourceNode.getOutEdges()) { DataFlowEdge re = (DataFlowEdge) resToCh; DataTransferChannel ch = ((ChannelNode) re.getDestination()).getChannel(); - for (Edge chToRes: re.getDestination().getOutEdges()) { - ResourcePath dstRes = ((ResourceNode) chToRes.getDestination()).getOutSideResource(); - // Check if the destination resource is outside of the channel scope. - boolean outsideOutputResource = false; - for (ChannelMember cm: ch.getOutputChannelMembers()) { - if (cm.getResource().getResourceHierarchy().equals(dstRes.getResourceHierarchy()) && cm.isOutside()) { - outsideOutputResource = true; // Regarded as push transfer. - break; - } + // Check if the source resource is outside of the channel scope. + boolean outsideInputResource = false; + for (ChannelMember cm: ch.getInputChannelMembers()) { + if (cm.getResource().equals(resourceNode.getOutSideResource()) && cm.isOutside()) { + outsideInputResource = true; // Regarded as pull transfer. + break; } - if (outsideOutputResource) { - // Declare a field in the parent component to refer to the destination resource of push transfer. - String dstResName = null; - if (!generatesComponent(dstRes.getResourceHierarchy())) { - dstRes = dstRes.getParent(); + } + for (Edge chToRes: re.getDestination().getOutEdges()) { + if (chToRes.getDestination() instanceof ResourceNode) { + ResourcePath dstRes = ((ResourceNode) chToRes.getDestination()).getOutSideResource(); + // Check if the destination resource is outside of the channel scope. + boolean outsideOutputResource = false; + for (ChannelMember cm: ch.getOutputChannelMembers()) { + if (((ResourceNode) chToRes.getDestination()).getInSideResources().contains(cm.getResource()) && cm.isOutside()) { + outsideOutputResource = true; // Regarded as push transfer. + break; + } } - dstResName = getComponentName(dstRes.getResourceHierarchy(), langSpec); - FieldDeclaration refFieldForPush = langSpec.newFieldDeclaration(new Type(dstResName, dstResName), langSpec.toVariableName(dstResName)); - parentComponent.addField(refFieldForPush); - if (dstRes.getParent() != null) { - // Reference to root resource. - String dstRootResName = getComponentName(dstRes.getRoot().getResourceHierarchy(), langSpec); - Type dstRootResType = new Type(dstRootResName, dstRootResName); - dstRootResName = langSpec.toVariableName(dstRootResName); - FieldDeclaration refRootFieldForPush = langSpec.newFieldDeclaration(dstRootResType, dstRootResName); - boolean existsField = false; - for (FieldDeclaration field: parentComponent.getFields()) { - if (dstRootResName.equals(field.getName())) { - existsField = true; - break; + if ((((PushPullAttribute) re.getAttribute()).getOptions().get(0) == PushPullValue.PUSH && !outsideInputResource) || outsideOutputResource) { + // Declare a field in the parent component to refer to the destination resource of push transfer. + if (!generatesComponent(dstRes.getResourceHierarchy())) { + dstRes = dstRes.getParent(); + } + String dstResName = getComponentName(dstRes.getResourceHierarchy(), langSpec); + FieldDeclaration refFieldForPush = langSpec.newFieldDeclaration(new Type(dstResName, dstResName), langSpec.toVariableName(dstResName)); + VariableDeclaration refVarForPush = langSpec.newVariableDeclaration(new Type(dstResName, dstResName), langSpec.toVariableName(dstResName)); + if (component != null) { + // A component is created for this resource. + if (resourceNode.getResourceHierarchy() != dstRes.getResourceHierarchy()) { + component.addField(refFieldForPush); + if (!outsideOutputResource) { + constructorParams.add(new AbstractMap.SimpleEntry<>(resourceNode.getResourceHierarchy(), refVarForPush)); + } + } + } else { + // No component is created for this resource. + if (resourceNode.getParent().getResourceHierarchy() != dstRes.getResourceHierarchy()) { + parentComponent.addField(refFieldForPush); + if (!outsideOutputResource) { + constructorParams.add(new AbstractMap.SimpleEntry<>(resourceNode.getParent().getResourceHierarchy(), refVarForPush)); + } } } - if (!existsField) { - parentComponent.addField(refRootFieldForPush); + if (outsideOutputResource) { + // When the reference to the destination resource can vary. + if (dstRes.getParent() != null) { + // Reference to its root resource. + String dstRootResName = getComponentName(dstRes.getRoot().getResourceHierarchy(), langSpec); + Type dstRootResType = new Type(dstRootResName, dstRootResName); + dstRootResName = langSpec.toVariableName(dstRootResName); + FieldDeclaration refRootFieldForPush = langSpec.newFieldDeclaration(dstRootResType, dstRootResName); + VariableDeclaration refRootVarForPush = langSpec.newVariableDeclaration(dstRootResType, dstRootResName); + if (component != null) { + // A component is created for this resource. + boolean existsField = false; + for (FieldDeclaration field: component.getFields()) { + if (dstRootResName.equals(field.getName())) { + existsField = true; + break; + } + } + if (!existsField) { + component.addField(refRootFieldForPush); + constructorParams.add(new AbstractMap.SimpleEntry<>(resourceNode.getResourceHierarchy(), refRootVarForPush)); + } + } else { + // No component is created for this resource. + boolean existsField = false; + for (FieldDeclaration field: parentComponent.getFields()) { + if (dstRootResName.equals(field.getName())) { + existsField = true; + break; + } + } + if (!existsField) { + parentComponent.addField(refRootFieldForPush); + constructorParams.add(new AbstractMap.SimpleEntry<>(resourceNode.getParent().getResourceHierarchy(), refRootVarForPush)); + } + } + } } - constructorParams.add(new AbstractMap.SimpleEntry<>(resourceNode.getParent().getResourceHierarchy(), langSpec.newVariableDeclaration(dstRootResType, dstRootResName))); } } } } + // Declare reference fields for pull data transfer. for (Edge chToRes : resourceNode.getInEdges()) { for (Edge resToCh: chToRes.getSource().getInEdges()) { DataFlowEdge re = (DataFlowEdge) resToCh; @@ -441,49 +494,104 @@ // Check if the source resource is outside of the channel scope. boolean outsideInputResource = false; for (ChannelMember cm: ch.getInputChannelMembers()) { - if (cm.getResource().getResourceHierarchy().equals(srcRes.getResourceHierarchy()) && cm.isOutside()) { + if (cm.getResource().equals(srcRes) && cm.isOutside()) { outsideInputResource = true; // Regarded as pull transfer. break; } } - if (outsideInputResource) { - // Declare a field in the parent component to refer to the source resource of pull transfer. - String srcResName = null; + // Check if the output resource is outside of the channel scope. + boolean outsideOutputResource = false; + for (ChannelMember cm: ch.getOutputChannelMembers()) { + if (resourceNode.getInSideResources().contains(cm.getResource()) && cm.isOutside()) { + outsideOutputResource = true; // Regarded as push transfer. + break; + } + } + if ((((PushPullAttribute) re.getAttribute()).getOptions().get(0) != PushPullValue.PUSH && !outsideOutputResource) || outsideInputResource) { + noPullTransfer = false; + // Declare a field in the parent/this component to refer to the source resource of pull transfer. if (!generatesComponent(srcRes.getResourceHierarchy())) { srcRes = srcRes.getParent(); } - srcResName = getComponentName(srcRes.getResourceHierarchy(), langSpec); + String srcResName = getComponentName(srcRes.getResourceHierarchy(), langSpec); FieldDeclaration refFieldForPull = langSpec.newFieldDeclaration(new Type(srcResName, srcResName), langSpec.toVariableName(srcResName)); - parentComponent.addField(refFieldForPull); - if (srcRes.getParent() != null) { - // Reference to root resource. - String srcRootResName = getComponentName(srcRes.getRoot().getResourceHierarchy(), langSpec); - Type srcRootResType = new Type(srcRootResName, srcRootResName); - srcRootResName = langSpec.toVariableName(srcRootResName); - FieldDeclaration refRootFieldForPull = langSpec.newFieldDeclaration(srcRootResType, srcRootResName); - boolean existsField = false; - for (FieldDeclaration field: parentComponent.getFields()) { - if (srcRootResName.equals(field.getName())) { - existsField = true; - break; + VariableDeclaration refVarForPull = langSpec.newVariableDeclaration(new Type(srcResName, srcResName), langSpec.toVariableName(srcResName)); + if (component != null) { + // A component is created for this resource. + if (resourceNode.getResourceHierarchy() != srcRes.getResourceHierarchy()) { + component.addField(refFieldForPull); + if (!outsideInputResource) { + constructorParams.add(new AbstractMap.SimpleEntry<>(resourceNode.getResourceHierarchy(), refVarForPull)); } } - if (!existsField) { - parentComponent.addField(refRootFieldForPull); + } else { + // No component is created for this resource. + if (resourceNode.getParent().getResourceHierarchy() != srcRes.getResourceHierarchy()) { + parentComponent.addField(refFieldForPull); + if (!outsideInputResource) { + constructorParams.add(new AbstractMap.SimpleEntry<>(resourceNode.getParent().getResourceHierarchy(), refVarForPull)); + } } - constructorParams.add(new AbstractMap.SimpleEntry<>(resourceNode.getParent().getResourceHierarchy(), langSpec.newVariableDeclaration(srcRootResType, srcRootResName))); } - noPullTransfer = false; + if (outsideInputResource) { + // When the reference to the source resource can vary. + if (srcRes.getParent() != null) { + // Reference to its root resource. + String srcRootResName = getComponentName(srcRes.getRoot().getResourceHierarchy(), langSpec); + Type srcRootResType = new Type(srcRootResName, srcRootResName); + srcRootResName = langSpec.toVariableName(srcRootResName); + FieldDeclaration refRootFieldForPull = langSpec.newFieldDeclaration(srcRootResType, srcRootResName); + VariableDeclaration refRootVarForPull = langSpec.newVariableDeclaration(srcRootResType, srcRootResName); + if (component != null) { + // A component is created for this resource. + boolean existsField = false; + for (FieldDeclaration field: component.getFields()) { + if (srcRootResName.equals(field.getName())) { + existsField = true; + break; + } + } + if (!existsField) { + component.addField(refRootFieldForPull); + constructorParams.add(new AbstractMap.SimpleEntry<>(resourceNode.getResourceHierarchy(), refRootVarForPull)); + } + } else { + // No component is created for this resource. + boolean existsField = false; + for (FieldDeclaration field: parentComponent.getFields()) { + if (srcRootResName.equals(field.getName())) { + existsField = true; + break; + } + } + if (!existsField) { + parentComponent.addField(refRootFieldForPull); + constructorParams.add(new AbstractMap.SimpleEntry<>(resourceNode.getParent().getResourceHierarchy(), refRootVarForPull)); + } + } + } + } } } } // Declare the state field in the parent component. - ResourceHierarchy res = resourceNode.getOutSideResource().getResourceHierarchy(); - if (((StoreAttribute) resourceNode.getAttribute()).isStored() && noPullTransfer && res.getNumParameters() == 0) { - String resName = getComponentName(res, langSpec); - FieldDeclaration stateField = langSpec.newFieldDeclaration(res.getResourceStateType(), langSpec.toVariableName(resName)); - parentComponent.addField(stateField); - constructorParams.add(new AbstractMap.SimpleEntry<>(resourceNode.getParent().getResourceHierarchy(), langSpec.newVariableDeclaration(res.getResourceStateType(), langSpec.toVariableName(resName)))); + if (component == null) { + ResourceHierarchy res = resourceNode.getOutSideResource().getResourceHierarchy(); + if (((StoreAttribute) resourceNode.getAttribute()).isStored() && noPullTransfer && res.getNumParameters() == 0) { + String resName = langSpec.toVariableName(getComponentName(res, langSpec)); + boolean existsField = false; + for (FieldDeclaration field: parentComponent.getFields()) { + if (resName.equals(field.getName())) { + existsField = true; + break; + } + } + if (!existsField) { + FieldDeclaration stateField = langSpec.newFieldDeclaration(res.getResourceStateType(), resName); + parentComponent.addField(stateField); + constructorParams.add(new AbstractMap.SimpleEntry<>(resourceNode.getParent().getResourceHierarchy(), langSpec.newVariableDeclaration(res.getResourceStateType(), resName))); + } + } } } @@ -648,12 +756,20 @@ // Check if the input resource is outside of the channel scope. boolean outsideInputResource = false; for (ChannelMember cm: ch.getInputChannelMembers()) { - if (cm.getResource().getResourceHierarchy().equals(srcRes.getResourceHierarchy()) && cm.isOutside()) { + if (cm.getResource().equals(srcRes) && cm.isOutside()) { outsideInputResource = true; // Regarded as pull transfer. break; } } - if (((PushPullAttribute) re.getAttribute()).getOptions().get(0) == PushPullValue.PUSH && !outsideInputResource) { + // Check if the output resource is outside of the channel scope. + boolean outsideOutputResource = false; + for (ChannelMember cm: ch.getOutputChannelMembers()) { + if (resourceNode.getInSideResources().contains(cm.getResource()) && cm.isOutside()) { + outsideOutputResource = true; // Regarded as push transfer. + break; + } + } + if ((((PushPullAttribute) re.getAttribute()).getOptions().get(0) == PushPullValue.PUSH && !outsideInputResource) || outsideOutputResource) { // for push data transfer // Declare an update method in the type of the destination resource. @@ -667,11 +783,27 @@ } MethodDeclaration update = null; if (component != null) { - update = langSpec.newMethodDeclaration(updateMethodPrefix + from + srcResComponentName, false, null, vars); - component.addMethod(update); + for (MethodDeclaration method: component.getMethods()) { + if (method.getName().equals(updateMethodPrefix + from + srcResComponentName)) { + update = method; + break; + } + } + if (update == null) { + update = langSpec.newMethodDeclaration(updateMethodPrefix + from + srcResComponentName, false, null, vars); + component.addMethod(update); + } } else if (parentComponent != null) { - update = langSpec.newMethodDeclaration(updateMethodPrefix + resComponentName + from + srcResComponentName, false, null, vars); - parentComponent.addMethod(update); + for (MethodDeclaration method: parentComponent.getMethods()) { + if (method.getName().equals(updateMethodPrefix + resComponentName + from + srcResComponentName)) { + update = method; + break; + } + } + if (update == null) { + update = langSpec.newMethodDeclaration(updateMethodPrefix + resComponentName + from + srcResComponentName, false, null, vars); + parentComponent.addMethod(update); + } } // Add a statement to update the state field @@ -845,7 +977,7 @@ for (ChannelMember cm: ch2.getInputChannelMembers()) { if (cm.isOutside()) { outsideInputMembers2.add(cm); - if (cm.getResource().getResourceHierarchy().equals(resourceNode.getResourceHierarchy())) { + if (cm.getResource().equals(resourceNode.getOutSideResource())) { outsideInputResource2 = true; // Regarded as pull transfer. } } @@ -1048,13 +1180,30 @@ if (((DataTransferChannel) ch).getOutputChannelMembers().size() > 1) { inputMethodName += _for + getComponentName(out.getResource().getResourceHierarchy(), langSpec); } - input = langSpec.newMethodDeclaration(inputMethodName, false, null, resInputParams); if (component != null) { // A component is created for this resource. - component.addMethod(input); + for (MethodDeclaration method: component.getMethods()) { + if (method.getName().equals(inputMethodName)) { + input = method; + break; + } + } + if (input == null) { + input = langSpec.newMethodDeclaration(inputMethodName, false, null, resInputParams); + component.addMethod(input); + } } else if (parentComponent != null) { // No component is created for this resource. - parentComponent.addMethod(input); + for (MethodDeclaration method: parentComponent.getMethods()) { + if (method.getName().equals(inputMethodName)) { + input = method; + break; + } + } + if (input == null) { + input = langSpec.newMethodDeclaration(inputMethodName, false, null, resInputParams); + parentComponent.addMethod(input); + } } // Declare the accessor in the main component to call the input method. @@ -1111,17 +1260,38 @@ if (((DataTransferChannel) ch).getOutputChannelMembers().size() > 1) { inputMethodName += _for + getComponentName(out.getResource().getResourceHierarchy(), langSpec); } - if (resInputParams.size() == 0) { - input = langSpec.newMethodDeclaration(inputMethodName, null); - } else { - input = langSpec.newMethodDeclaration(inputMethodName, false, null, resInputParams); - } if (component != null) { // A component is created for this resource. - component.addMethod(input); + for (MethodDeclaration method: component.getMethods()) { + if (method.getName().equals(inputMethodName)) { + input = method; + break; + } + } + if (input == null) { + if (resInputParams.size() == 0) { + input = langSpec.newMethodDeclaration(inputMethodName, null); + } else { + input = langSpec.newMethodDeclaration(inputMethodName, false, null, resInputParams); + } + component.addMethod(input); + } } else if (parentComponent != null) { // No component is created for this resource. - parentComponent.addMethod(input); + for (MethodDeclaration method: parentComponent.getMethods()) { + if (method.getName().equals(inputMethodName)) { + input = method; + break; + } + } + if (input == null) { + if (resInputParams.size() == 0) { + input = langSpec.newMethodDeclaration(inputMethodName, null); + } else { + input = langSpec.newMethodDeclaration(inputMethodName, false, null, resInputParams); + } + parentComponent.addMethod(input); + } } // Declare the accessor in the main component to call the input method. @@ -1254,7 +1424,7 @@ for (ChannelMember cm: ch2.getInputChannelMembers()) { if (cm.isOutside()) { outsideInputMembers2.add(cm); - if (cm.getResource().getResourceHierarchy().equals(resourceNode.getResourceHierarchy())) { + if (cm.getResource().equals(resourceNode.getOutSideResource())) { outsideInputResource2 = true; // Regarded as pull transfer. } } diff --git a/AlgebraicDataflowArchitectureModel/src/generators/JavaCodeGenerator.java b/AlgebraicDataflowArchitectureModel/src/generators/JavaCodeGenerator.java index 871630a..502b883 100644 --- a/AlgebraicDataflowArchitectureModel/src/generators/JavaCodeGenerator.java +++ b/AlgebraicDataflowArchitectureModel/src/generators/JavaCodeGenerator.java @@ -307,72 +307,82 @@ } } - // Declare the state field and reference fields in the parent component. + // Declare the state field in the parent component. if (component == null) { // Declare reference fields for push/pull data transfer. boolean noPullTransfer = true; - for (Edge resToCh : resourceNode.getOutEdges()) { - DataFlowEdge re = (DataFlowEdge) resToCh; - DataTransferChannel ch = ((ChannelNode) re.getDestination()).getChannel(); - for (Edge chToRes: re.getDestination().getOutEdges()) { - ResourcePath dstRes = ((ResourceNode) chToRes.getDestination()).getOutSideResource(); - boolean outsideOutputResource = false; - for (ChannelMember cm: ch.getOutputChannelMembers()) { - if (cm.getResource().getResourceHierarchy().equals(dstRes.getResourceHierarchy()) && cm.isOutside()) { - outsideOutputResource = true; // Regarded as push transfer. - break; - } - } - if (outsideOutputResource) { // This logic may be incorrect. (ToDo) - // Declare a field in the parent component to refer to the destination resource of push transfer. - if (!generatesComponent(dstRes.getResourceHierarchy())) { - dstRes = dstRes.getParent(); - } - String dstResName = getComponentName(dstRes.getResourceHierarchy()); - FieldDeclaration refFieldForPush = new FieldDeclaration(new Type(dstResName, dstResName), toVariableName(dstResName)); - fields.add(new AbstractMap.SimpleEntry<>(resourceNode.getParent().getResourceHierarchy(), refFieldForPush)); - if (dstRes.getParent() != null) { - // Reference to root resource. - ResourcePath dstRootRes = dstRes.getRoot(); - String dstRootResName = getComponentName(dstRootRes.getResourceHierarchy()); - Type dstRootResType = new Type(dstRootResName, dstRootResName); - FieldDeclaration refRootFieldForPush = new FieldDeclaration(dstRootResType, toVariableName(dstRootResName)); - fields.add(new AbstractMap.SimpleEntry<>(resourceNode.getParent().getResourceHierarchy(), refRootFieldForPush)); - constructorParams.add(new AbstractMap.SimpleEntry<>(resourceNode.getParent().getResourceHierarchy(), new VariableDeclaration(dstRootResType, toVariableName(dstRootResName)))); - } - } - } - } +// for (Edge resToCh : resourceNode.getOutEdges()) { +// DataFlowEdge re = (DataFlowEdge) resToCh; +// DataTransferChannel ch = ((ChannelNode) re.getDestination()).getChannel(); +// for (Edge chToRes: re.getDestination().getOutEdges()) { +// ResourcePath dstRes = ((ResourceNode) chToRes.getDestination()).getOutSideResource(); +// // Check if the output resource is outside of the channel scope. +// boolean outsideOutputResource = false; +// for (ChannelMember cm: ch.getOutputChannelMembers()) { +// if (cm.getResource().getResourceHierarchy().equals(dstRes.getResourceHierarchy()) && cm.isOutside()) { +// outsideOutputResource = true; // Regarded as push transfer. +// break; +// } +// } +// if (outsideOutputResource) { // This logic may be incorrect. (ToDo) +// // Declare a field in the parent component to refer to the destination resource of push transfer. +// if (!generatesComponent(dstRes.getResourceHierarchy())) { +// dstRes = dstRes.getParent(); +// } +// String dstResName = getComponentName(dstRes.getResourceHierarchy()); +// FieldDeclaration refFieldForPush = new FieldDeclaration(new Type(dstResName, dstResName), toVariableName(dstResName)); +// fields.add(new AbstractMap.SimpleEntry<>(resourceNode.getParent().getResourceHierarchy(), refFieldForPush)); +// if (dstRes.getParent() != null) { +// // Reference to root resource. +// ResourcePath dstRootRes = dstRes.getRoot(); +// String dstRootResName = getComponentName(dstRootRes.getResourceHierarchy()); +// Type dstRootResType = new Type(dstRootResName, dstRootResName); +// FieldDeclaration refRootFieldForPush = new FieldDeclaration(dstRootResType, toVariableName(dstRootResName)); +// fields.add(new AbstractMap.SimpleEntry<>(resourceNode.getParent().getResourceHierarchy(), refRootFieldForPush)); +// constructorParams.add(new AbstractMap.SimpleEntry<>(resourceNode.getParent().getResourceHierarchy(), new VariableDeclaration(dstRootResType, toVariableName(dstRootResName)))); +// } +// } +// } +// } for (Edge chToRes : resourceNode.getInEdges()) { for (Edge resToCh: chToRes.getSource().getInEdges()) { DataFlowEdge re = (DataFlowEdge) resToCh; ResourcePath srcRes = ((ResourceNode) re.getSource()).getOutSideResource(); DataTransferChannel ch = ((ChannelNode) re.getDestination()).getChannel(); + // Check if the input resource is outside of the channel scope. boolean outsideInputResource = false; for (ChannelMember cm: ch.getInputChannelMembers()) { - if (cm.getResource().getResourceHierarchy().equals(srcRes.getResourceHierarchy()) && cm.isOutside()) { + if (cm.getResource().equals(srcRes) && cm.isOutside()) { outsideInputResource = true; // Regarded as pull transfer. break; } } - if (outsideInputResource) { // This logic may be incorrect. (ToDo) - // Declare a field in the parent component to refer to the source resource of pull transfer. - if (!generatesComponent(srcRes.getResourceHierarchy())) { - srcRes = srcRes.getParent(); + // Check if the output resource is outside of the channel scope. + boolean outsideOutputResource = false; + for (ChannelMember cm: ch.getOutputChannelMembers()) { + if (resourceNode.getInSideResources().contains(cm.getResource()) && cm.isOutside()) { + outsideOutputResource = true; // Regarded as push transfer. + break; } - String srcResName = getComponentName(srcRes.getResourceHierarchy()); - FieldDeclaration refFieldForPull = new FieldDeclaration(new Type(srcResName, srcResName), toVariableName(srcResName)); - fields.add(new AbstractMap.SimpleEntry<>(resourceNode.getParent().getResourceHierarchy(), refFieldForPull)); - if (srcRes.getParent() != null) { - // Reference to root resource. - ResourcePath srcRootRes = srcRes.getRoot(); - String srcRootResName = getComponentName(srcRootRes.getResourceHierarchy()); - Type srcRootResType = new Type(srcRootResName, srcRootResName); - FieldDeclaration refRootFieldForPull = new FieldDeclaration(srcRootResType, toVariableName(srcRootResName)); - fields.add(new AbstractMap.SimpleEntry<>(resourceNode.getParent().getResourceHierarchy(), refRootFieldForPull)); - constructorParams.add(new AbstractMap.SimpleEntry<>(resourceNode.getParent().getResourceHierarchy(), new VariableDeclaration(srcRootResType, toVariableName(srcRootResName)))); - } + } + if ((((PushPullAttribute) re.getAttribute()).getOptions().get(0) != PushPullValue.PUSH && !outsideOutputResource) || outsideInputResource) { noPullTransfer = false; +// // Declare a field in the parent component to refer to the source resource of pull transfer. +// if (!generatesComponent(srcRes.getResourceHierarchy())) { +// srcRes = srcRes.getParent(); +// } +// String srcResName = getComponentName(srcRes.getResourceHierarchy()); +// FieldDeclaration refFieldForPull = new FieldDeclaration(new Type(srcResName, srcResName), toVariableName(srcResName)); +// fields.add(new AbstractMap.SimpleEntry<>(resourceNode.getParent().getResourceHierarchy(), refFieldForPull)); +// if (srcRes.getParent() != null) { +// // Reference to root resource. +// ResourcePath srcRootRes = srcRes.getRoot(); +// String srcRootResName = getComponentName(srcRootRes.getResourceHierarchy()); +// Type srcRootResType = new Type(srcRootResName, srcRootResName); +// FieldDeclaration refRootFieldForPull = new FieldDeclaration(srcRootResType, toVariableName(srcRootResName)); +// fields.add(new AbstractMap.SimpleEntry<>(resourceNode.getParent().getResourceHierarchy(), refRootFieldForPull)); +// constructorParams.add(new AbstractMap.SimpleEntry<>(resourceNode.getParent().getResourceHierarchy(), new VariableDeclaration(srcRootResType, toVariableName(srcRootResName)))); +// } } } } @@ -424,30 +434,31 @@ } } - // Declare fields and update methods in the type of each resource. + // Declare reference fields and update methods in the type of each resource. + // Declare reference fields for push data transfer. for (Edge resToCh : resourceNode.getOutEdges()) { DataFlowEdge re = (DataFlowEdge) resToCh; DataTransferChannel ch = ((ChannelNode) re.getDestination()).getChannel(); // Check if the input resource is outside of the channel scope. boolean outsideInputResource = false; for (ChannelMember cm: ch.getInputChannelMembers()) { - if (cm.getResource().getResourceHierarchy().equals(resourceNode.getResourceHierarchy()) && cm.isOutside()) { + if (cm.getResource().equals(resourceNode.getOutSideResource()) && cm.isOutside()) { outsideInputResource = true; // Regarded as pull transfer. break; } } - // Check if the output resource is outside of the channel scope. - boolean outsideOutputResource = false; - for (ChannelMember cm: ch.getOutputChannelMembers()) { - if (cm.getResource().getResourceHierarchy().equals(resourceNode.getOutSideResource().getResourceHierarchy()) && cm.isOutside()) { - outsideOutputResource = true; // Regarded as push transfer. - break; + for (Edge chToRes: re.getDestination().getOutEdges()) { + ResourcePath dstRes = ((ResourceNode) chToRes.getDestination()).getOutSideResource(); + // Check if the output resource is outside of the channel scope. + boolean outsideOutputResource = false; + for (ChannelMember cm: ch.getOutputChannelMembers()) { + if (((ResourceNode) chToRes.getDestination()).getInSideResources().contains(cm.getResource()) && cm.isOutside()) { + outsideOutputResource = true; // Regarded as push transfer. + break; + } } - } - if (((PushPullAttribute) re.getAttribute()).getOptions().get(0) == PushPullValue.PUSH && !outsideInputResource) { - // Declare a field to refer to the destination resource of push transfer. - for (Edge chToRes: re.getDestination().getOutEdges()) { - ResourcePath dstRes = ((ResourceNode) chToRes.getDestination()).getOutSideResource(); + if ((((PushPullAttribute) re.getAttribute()).getOptions().get(0) == PushPullValue.PUSH && !outsideInputResource) || outsideOutputResource) { + // Declare a field to refer to the destination resource of push transfer. if (!generatesComponent(dstRes.getResourceHierarchy())) { dstRes = dstRes.getParent(); } @@ -457,14 +468,23 @@ VariableDeclaration dstRefVar = new VariableDeclaration(new Type(dstResName, dstResName), toVariableName(dstResName)); if (component != null) { // A component is created for this resource. - component.addField(dstRefField); - constructorParams.add(new AbstractMap.SimpleEntry<>(resourceNode.getResourceHierarchy(), dstRefVar)); + if (resourceNode.getResourceHierarchy() != dstRes.getResourceHierarchy()) { + component.addField(dstRefField); + if (!outsideOutputResource) { + constructorParams.add(new AbstractMap.SimpleEntry<>(resourceNode.getResourceHierarchy(), dstRefVar)); + } + } } else { // No component is created for this resource. - fields.add(new AbstractMap.SimpleEntry<>(resourceNode.getParent().getResourceHierarchy(), dstRefField)); - constructorParams.add(new AbstractMap.SimpleEntry<>(resourceNode.getParent().getResourceHierarchy(), dstRefVar)); + if (resourceNode.getParent().getResourceHierarchy() != dstRes.getResourceHierarchy()) { + fields.add(new AbstractMap.SimpleEntry<>(resourceNode.getParent().getResourceHierarchy(), dstRefField)); + if (!outsideOutputResource) { + constructorParams.add(new AbstractMap.SimpleEntry<>(resourceNode.getParent().getResourceHierarchy(), dstRefVar)); + } + } } if (outsideOutputResource) { + // When the reference to the destination resource can vary. if (dstRes.getParent() != null) { // Reference to root resource. ResourcePath dstRootRes = dstRes.getRoot(); @@ -485,6 +505,7 @@ } } } + // Declare reference fields for pull data transfer. for (Edge chToRes : resourceNode.getInEdges()) { for (Edge resToCh: chToRes.getSource().getInEdges()) { DataFlowEdge re = (DataFlowEdge) resToCh; @@ -493,7 +514,7 @@ // Check if the input resource is outside of the channel scope. boolean outsideInputResource = false; for (ChannelMember cm: ch.getInputChannelMembers()) { - if (cm.getResource().getResourceHierarchy().equals(srcRes.getResourceHierarchy()) && cm.isOutside()) { + if (cm.getResource().equals(srcRes) && cm.isOutside()) { outsideInputResource = true; // Regarded as pull transfer. break; } @@ -501,33 +522,44 @@ // Check if the output resource is outside of the channel scope. boolean outsideOutputResource = false; for (ChannelMember cm: ch.getOutputChannelMembers()) { - if (cm.getResource().getResourceHierarchy().equals(resourceNode.getOutSideResource().getResourceHierarchy()) && cm.isOutside()) { + if (resourceNode.getInSideResources().contains(cm.getResource()) && cm.isOutside()) { outsideOutputResource = true; // Regarded as push transfer. break; } } String srcResName = getComponentName(srcRes.getResourceHierarchy()); ResourcePath srcRes2 = srcRes; + String srcResName2 = srcResName; if (!generatesComponent(srcRes.getResourceHierarchy())) { srcRes2 = srcRes.getParent(); + srcResName2 = getComponentName(srcRes2.getResourceHierarchy()); } if ((((PushPullAttribute) re.getAttribute()).getOptions().get(0) != PushPullValue.PUSH && !outsideOutputResource) || outsideInputResource) { // Declare a field to refer to the source resource of pull transfer. depends.add(srcRes2.getResourceHierarchy()); - FieldDeclaration srcRefField = new FieldDeclaration(new Type(srcResName, srcResName), toVariableName(srcResName)); - VariableDeclaration srcRefVar = new VariableDeclaration(new Type(srcResName, srcResName), toVariableName(srcResName)); + FieldDeclaration srcRefField = new FieldDeclaration(new Type(srcResName2, srcResName2), toVariableName(srcResName2)); + VariableDeclaration srcRefVar = new VariableDeclaration(new Type(srcResName2, srcResName2), toVariableName(srcResName2)); if (component != null) { // A component is created for this resource. - component.addField(srcRefField); - constructorParams.add(new AbstractMap.SimpleEntry<>(resourceNode.getResourceHierarchy(), srcRefVar)); + if (resourceNode.getResourceHierarchy() != srcRes2.getResourceHierarchy()) { + component.addField(srcRefField); + if (!outsideInputResource) { + constructorParams.add(new AbstractMap.SimpleEntry<>(resourceNode.getResourceHierarchy(), srcRefVar)); + } + } } else { // No component is created for this resource. - fields.add(new AbstractMap.SimpleEntry<>(resourceNode.getParent().getResourceHierarchy(), srcRefField)); - constructorParams.add(new AbstractMap.SimpleEntry<>(resourceNode.getParent().getResourceHierarchy(), srcRefVar)); + if (resourceNode.getParent().getResourceHierarchy() != srcRes2.getResourceHierarchy()) { + fields.add(new AbstractMap.SimpleEntry<>(resourceNode.getParent().getResourceHierarchy(), srcRefField)); + if (!outsideInputResource) { + constructorParams.add(new AbstractMap.SimpleEntry<>(resourceNode.getParent().getResourceHierarchy(), srcRefVar)); + } + } } if (outsideInputResource) { + // When the reference to the source resource can vary. if (srcRes2.getParent() != null) { - // Reference to root resource. + // Reference to its root resource. ResourcePath srcRootRes = srcRes2.getRoot(); String srcRootResName = getComponentName(srcRootRes.getResourceHierarchy()); FieldDeclaration srcRootRefField = new FieldDeclaration(new Type(srcRootResName, srcRootResName), toVariableName(srcRootResName)); @@ -976,12 +1008,12 @@ MethodDeclaration getterAccessor = null; List mainGetterParams = new ArrayList<>(); int v = 1; - for (Selector param: resourceNode.getAllSelectors()) { - if (param.getExpression() instanceof Variable) { - Variable var = (Variable) param.getExpression(); + for (Expression param: resourceNode.getOutSideResource().getPathParams()) { + if (param instanceof Variable) { + Variable var = (Variable) param; mainGetterParams.add(new VariableDeclaration(var.getType(), var.getName())); - } else if (param.getExpression() instanceof Term) { - Term var = (Term) param.getExpression(); + } else if (param instanceof Term) { + Term var = (Term) param; mainGetterParams.add(new VariableDeclaration(var.getType(), "v" + v)); } v++; diff --git a/AlgebraicDataflowArchitectureModel/src/generators/JavaMethodBodyGenerator.java b/AlgebraicDataflowArchitectureModel/src/generators/JavaMethodBodyGenerator.java index 3d51562..8e8466e 100644 --- a/AlgebraicDataflowArchitectureModel/src/generators/JavaMethodBodyGenerator.java +++ b/AlgebraicDataflowArchitectureModel/src/generators/JavaMethodBodyGenerator.java @@ -186,12 +186,25 @@ if (getter.getBody() == null || getter.getBody().getStatements().size() == 0) { Type resourceType = dst.getResourceStateType(); if (dst.getResourceHierarchy().getNumParameters() == 0) { - if (model.isPrimitiveType(resourceType)) { - getter.addStatement("return value;"); + if (JavaCodeGenerator.generatesComponent(dst.getResourceHierarchy())) { + // dst has a component. + if (model.isPrimitiveType(resourceType)) { + getter.addStatement("return value;"); + } else { + // copy the current state to be returned as a 'value' + String implTypeName = resourceType.getImplementationTypeName(); + getter.addStatement("return new " + implTypeName + "(value);"); + } } else { - // copy the current state to be returned as a 'value' - String implTypeName = resourceType.getImplementationTypeName(); - getter.addStatement("return new " + implTypeName + "(value);"); + // dst has no component. + String dstResName = JavaCodeGenerator.toVariableName(JavaCodeGenerator.getComponentName(dst.getResourceHierarchy())); + if (model.isPrimitiveType(resourceType)) { + getter.addStatement("return " + dstResName + ";"); + } else { + // copy the current state to be returned as a 'value' + String implTypeName = resourceType.getImplementationTypeName(); + getter.addStatement("return new " + implTypeName + "(" + dstResName + ");"); + } } } else { String[] sideEffects = new String[] {""}; diff --git a/AlgebraicDataflowArchitectureModel/src/generators/JerseyCodeGenerator.java b/AlgebraicDataflowArchitectureModel/src/generators/JerseyCodeGenerator.java index 26cb8c8..88e747f 100644 --- a/AlgebraicDataflowArchitectureModel/src/generators/JerseyCodeGenerator.java +++ b/AlgebraicDataflowArchitectureModel/src/generators/JerseyCodeGenerator.java @@ -228,12 +228,12 @@ children.add(child.getResourceHierarchy()); List pathParams = new ArrayList<>(); int v = 1; - for (Selector pathParam: child.getSelectors()) { - if (pathParam.getExpression() instanceof Variable) { - Variable var = (Variable) pathParam.getExpression(); + for (Expression pathParam: child.getOutSideResource().getPathParams()) { + if (pathParam instanceof Variable) { + Variable var = (Variable) pathParam; pathParams.add(new VariableDeclaration(var.getType(), var.getName())); - } else if (pathParam.getExpression() instanceof Term) { - Term var = (Term) pathParam.getExpression(); + } else if (pathParam instanceof Term) { + Term var = (Term) pathParam; pathParams.add(new VariableDeclaration(var.getType(), "v" + v)); } v++; @@ -281,21 +281,20 @@ DataTransferChannel ch = ((ChannelNode) re.getDestination()).getChannel(); for (Edge chToRes: re.getDestination().getOutEdges()) { ResourcePath dstRes = ((ResourceNode) chToRes.getDestination()).getOutSideResource(); + // Check if the output resource is outside of the channel scope. boolean outsideOutputResource = false; for (ChannelMember cm: ch.getOutputChannelMembers()) { - if (cm.getResource().getResourceHierarchy().equals(dstRes.getResourceHierarchy()) && cm.isOutside()) { + if (((ResourceNode) chToRes.getDestination()).getInSideResources().contains(cm.getResource()) && cm.isOutside()) { outsideOutputResource = true; // Regarded as push transfer. break; } } if (outsideOutputResource) { // Declare a field in the parent component to refer to the destination resource of push transfer. - String dstResName = null; - if (generatesComponent(dstRes.getResourceHierarchy())) { - dstResName = getComponentName(dstRes.getResourceHierarchy()); - } else { - dstResName = getComponentName(dstRes.getResourceHierarchy().getParent()); + if (!generatesComponent(dstRes.getResourceHierarchy())) { + dstRes = dstRes.getParent(); } + String dstResName = getComponentName(dstRes.getResourceHierarchy()); if (resourceNode.getOutSideResource().getCommonPrefix(dstRes) == null && differentTreesAsDifferentServices) { // Inter-service if (!bDeclareClientField) { @@ -307,8 +306,10 @@ } else { // Inner-service // Declare a field to directly refer to the destination resource of push transfer. - FieldDeclaration refFieldForPush = new FieldDeclaration(new Type(dstResName, dstResName), toVariableName(dstResName)); - fields.add(new AbstractMap.SimpleEntry<>(resourceNode.getParent().getResourceHierarchy(), refFieldForPush)); + if (resourceNode.getParent().getResourceHierarchy() != dstRes.getResourceHierarchy()) { + FieldDeclaration refFieldForPush = new FieldDeclaration(new Type(dstResName, dstResName), toVariableName(dstResName)); + fields.add(new AbstractMap.SimpleEntry<>(resourceNode.getParent().getResourceHierarchy(), refFieldForPush)); + } } } } @@ -318,21 +319,20 @@ DataFlowEdge re = (DataFlowEdge) resToCh; ResourcePath srcRes = ((ResourceNode) re.getSource()).getOutSideResource(); DataTransferChannel ch = ((ChannelNode) re.getDestination()).getChannel(); + // Check if the input resource is outside of the channel scope. boolean outsideInputResource = false; for (ChannelMember cm: ch.getInputChannelMembers()) { - if (cm.getResource().getResourceHierarchy().equals(srcRes.getResourceHierarchy()) && cm.isOutside()) { + if (cm.getResource().equals(srcRes) && cm.isOutside()) { outsideInputResource = true; // Regarded as pull transfer. break; } } if (outsideInputResource) { // Declare a field in the parent component to refer to the source resource of pull transfer. - String srcResName = null; - if (generatesComponent(srcRes.getResourceHierarchy())) { - srcResName = getComponentName(srcRes.getResourceHierarchy()); - } else { - srcResName = getComponentName(srcRes.getResourceHierarchy().getParent()); + if (!generatesComponent(srcRes.getResourceHierarchy())) { + srcRes = srcRes.getParent(); } + String srcResName = getComponentName(srcRes.getResourceHierarchy()); if (resourceNode.getOutSideResource().getCommonPrefix(srcRes) == null && differentTreesAsDifferentServices) { // Inter-service if (!bDeclareClientField) { @@ -344,10 +344,12 @@ } else { // Inner-service // Declare a field to directly refer to the source resource of pull transfer. - FieldDeclaration refFieldForPull = new FieldDeclaration(new Type(srcResName, srcResName), toVariableName(srcResName)); - fields.add(new AbstractMap.SimpleEntry<>(resourceNode.getParent().getResourceHierarchy(), refFieldForPull)); - noPullTransfer = false; + if (resourceNode.getParent().getResourceHierarchy() != srcRes.getResourceHierarchy()) { + FieldDeclaration refFieldForPull = new FieldDeclaration(new Type(srcResName, srcResName), toVariableName(srcResName)); + fields.add(new AbstractMap.SimpleEntry<>(resourceNode.getParent().getResourceHierarchy(), refFieldForPull)); + } } + noPullTransfer = false; } } } @@ -445,20 +447,20 @@ // Check if the input resource is outside of the channel scope. boolean outsideInputResource = false; for (ChannelMember cm: ch.getInputChannelMembers()) { - if (cm.getResource().getResourceHierarchy().equals(resourceNode.getResourceHierarchy()) && cm.isOutside()) { + if (cm.getResource().equals(resourceNode.getOutSideResource()) && cm.isOutside()) { outsideInputResource = true; // Regarded as pull transfer. break; } } - if (!bDeclareClientField && ((PushPullAttribute) re.getAttribute()).getOptions().get(0) == PushPullValue.PUSH && !outsideInputResource) { - for (ChannelMember cm: ch.getOutputChannelMembers()) { - ResourcePath dstRes = cm.getResource(); - String dstResName = null; - if (generatesComponent(dstRes.getResourceHierarchy())) { - dstResName = getComponentName(dstRes.getResourceHierarchy()); - } else { - dstResName = getComponentName(dstRes.getResourceHierarchy().getParent()); + for (ChannelMember cm: ch.getOutputChannelMembers()) { + ResourcePath dstRes = cm.getResource(); + // Check if the output resource is outside of the channel scope. + boolean outsideOutputResource = cm.isOutside(); + if (!bDeclareClientField && ((((PushPullAttribute) re.getAttribute()).getOptions().get(0) == PushPullValue.PUSH && !outsideInputResource) || outsideOutputResource)) { + if (!generatesComponent(dstRes.getResourceHierarchy())) { + dstRes = dstRes.getParent(); } + String dstResName = getComponentName(dstRes.getResourceHierarchy()); if (resourceNode.getOutSideResource().getCommonPrefix(dstRes) == null && differentTreesAsDifferentServices) { // Inter-service if (!bDeclareClientField) { @@ -479,10 +481,14 @@ FieldDeclaration dstRefField = new FieldDeclaration(new Type(dstResName, dstResName), toVariableName(dstResName)); if (component != null) { // A component is created for this resource. - component.addField(dstRefField); + if (resourceNode.getResourceHierarchy() != dstRes.getResourceHierarchy()) { + component.addField(dstRefField); + } } else { // No component is created for this resource. - fields.add(new AbstractMap.SimpleEntry<>(resourceNode.getParent().getResourceHierarchy(), dstRefField)); + if (resourceNode.getParent().getResourceHierarchy() != dstRes.getResourceHierarchy()) { + fields.add(new AbstractMap.SimpleEntry<>(resourceNode.getParent().getResourceHierarchy(), dstRefField)); + } } } } @@ -493,22 +499,26 @@ DataFlowEdge re = (DataFlowEdge) resToCh; ResourcePath srcRes = ((ResourceNode) re.getSource()).getOutSideResource(); DataTransferChannel ch = ((ChannelNode) re.getDestination()).getChannel(); - // Check if the input and output resources are outside of the channel scope. + // Check if the input resource is outside of the channel scope. boolean outsideInputResource = false; for (ChannelMember cm: ch.getInputChannelMembers()) { - if (cm.getResource().getResourceHierarchy().equals(srcRes.getResourceHierarchy()) && cm.isOutside()) { + if (cm.getResource().equals(srcRes) && cm.isOutside()) { outsideInputResource = true; // Regarded as pull transfer. break; } } + // Check if the output resource is outside of the channel scope. boolean outsideOutputResource = false; for (ChannelMember cm: ch.getOutputChannelMembers()) { - if (cm.getResource().getResourceHierarchy().equals(resourceNode.getOutSideResource().getResourceHierarchy()) && cm.isOutside()) { + if (resourceNode.getInSideResources().contains(cm.getResource()) && cm.isOutside()) { outsideOutputResource = true; // Regarded as push transfer. break; } } String srcResName = getComponentName(srcRes.getResourceHierarchy()); + if (!generatesComponent(srcRes.getResourceHierarchy())) { + srcRes = srcRes.getParent(); + } if ((((PushPullAttribute) re.getAttribute()).getOptions().get(0) != PushPullValue.PUSH && !outsideOutputResource) || outsideInputResource) { if (resourceNode.getOutSideResource().getCommonPrefix(srcRes) == null && differentTreesAsDifferentServices) { // Inter-service @@ -530,10 +540,14 @@ FieldDeclaration srcRefField = new FieldDeclaration(new Type(srcResName, srcResName), toVariableName(srcResName)); if (component != null) { // A component is created for this resource. - component.addField(srcRefField); + if (resourceNode.getResourceHierarchy() != srcRes.getResourceHierarchy()) { + component.addField(srcRefField); + } } else { // No component is created for this resource. - fields.add(new AbstractMap.SimpleEntry<>(resourceNode.getParent().getResourceHierarchy(), srcRefField)); + if (resourceNode.getParent().getResourceHierarchy() != srcRes.getResourceHierarchy()) { + fields.add(new AbstractMap.SimpleEntry<>(resourceNode.getParent().getResourceHierarchy(), srcRefField)); + } } } } else { diff --git a/AlgebraicDataflowArchitectureModel/src/generators/JerseyMethodBodyGenerator.java b/AlgebraicDataflowArchitectureModel/src/generators/JerseyMethodBodyGenerator.java index fd766cc..4254cab 100644 --- a/AlgebraicDataflowArchitectureModel/src/generators/JerseyMethodBodyGenerator.java +++ b/AlgebraicDataflowArchitectureModel/src/generators/JerseyMethodBodyGenerator.java @@ -268,7 +268,14 @@ } if (getter.getBody() == null || getter.getBody().getStatements().size() == 0) { if (dst.getResourceHierarchy().getNumParameters() == 0) { - getter.addStatement("return value;"); + if (JerseyCodeGenerator.generatesComponent(dst.getResourceHierarchy())) { + // dst has a component. + getter.addStatement("return value;"); + } else { + // dst has no component. + String dstResName = JerseyCodeGenerator.toVariableName(JerseyCodeGenerator.getComponentName(dst.getResourceHierarchy())); + getter.addStatement("return " + dstResName + ";"); + } } else { if (DataConstraintModel.typeList.isAncestorOf(dst.getParent().getResourceStateType())) { Term selector = new Term(DataConstraintModel.get); diff --git a/AlgebraicDataflowArchitectureModel/src/models/dataConstraintModel/Channel.java b/AlgebraicDataflowArchitectureModel/src/models/dataConstraintModel/Channel.java index 7f418be..f27e54c 100644 --- a/AlgebraicDataflowArchitectureModel/src/models/dataConstraintModel/Channel.java +++ b/AlgebraicDataflowArchitectureModel/src/models/dataConstraintModel/Channel.java @@ -103,7 +103,11 @@ channelMember.setOutside(true); } } else { - channelMember.setOutside(true); + if (channelMember.getResource().getPathParams().size() == 0) { + channelMember.setOutside(false); + } else { + channelMember.setOutside(true); + } } }