diff --git a/AlgebraicDataflowArchitectureModel/src/generators/CodeGenerator.java b/AlgebraicDataflowArchitectureModel/src/generators/CodeGenerator.java index ae6acca..0e03b38 100644 --- a/AlgebraicDataflowArchitectureModel/src/generators/CodeGenerator.java +++ b/AlgebraicDataflowArchitectureModel/src/generators/CodeGenerator.java @@ -377,7 +377,7 @@ 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); + Expression getState = getPullAccessor().getDirectStateAccessorFor(accessRes.getOutSideResource(), null); block.addStatement(langSpec.getReturnStatement(getState.toImplementation(new String[] {null})) + langSpec.getStatementDelimiter()); // if (stateGetter.getParameters() == null || stateGetter.getParameters().size() == 0) { // block.addStatement(langSpec.getReturnStatement(langSpec.getMethodInvocation(accessRes.getResourceName(), stateGetter.getName())) + langSpec.getStatementDelimiter()); @@ -448,22 +448,38 @@ protected IResourceStateAccessor getPushAccessor() { return new IResourceStateAccessor() { @Override - public Expression getCurrentStateAccessorFor(ResourcePath target, ResourcePath from) { - if (target.equals(from)) { + public Expression getCurrentStateAccessorFor(ChannelMember target, ChannelMember from) { + ResourcePath targetRes= target.getResource(); + ResourcePath fromRes= from.getResource(); + if (targetRes.equals(fromRes)) { return new Field(fieldOfResourceState, - target.getResourceStateType() != null ? target.getResourceStateType() + targetRes.getResourceStateType() != null ? targetRes.getResourceStateType() : DataConstraintModel.typeInt); } // for reference channel member - return new Parameter(target.getResourceName(), - target.getResourceStateType() != null ? target.getResourceStateType() + return new Parameter(targetRes.getResourceName(), + targetRes.getResourceStateType() != null ? targetRes.getResourceStateType() : DataConstraintModel.typeInt); } @Override - public Expression getNextStateAccessorFor(ResourcePath target, ResourcePath from) { - return new Parameter(target.getResourceName(), - target.getResourceStateType() != null ? target.getResourceStateType() + public Expression getNextStateAccessorFor(ChannelMember target, ChannelMember from) { + ResourcePath targerRes= target.getResource(); + return new Parameter(targerRes.getResourceName(), + targerRes.getResourceStateType() != null ? targerRes.getResourceStateType() + : DataConstraintModel.typeInt); + } + + @Override + public Expression getDirectStateAccessorFor(ResourcePath targetRes, ResourcePath fromRes) { + if (fromRes != null && targetRes.equals(fromRes)) { + return new Field(fieldOfResourceState, + targetRes.getResourceStateType() != null ? targetRes.getResourceStateType() + : DataConstraintModel.typeInt); + } + // for reference channel member + return new Parameter(targetRes.getResourceName(), + targetRes.getResourceStateType() != null ? targetRes.getResourceStateType() : DataConstraintModel.typeInt); } }; @@ -472,21 +488,71 @@ protected IResourceStateAccessor getPullAccessor() { return new IResourceStateAccessor() { @Override - public Expression getCurrentStateAccessorFor(ResourcePath target, ResourcePath from) { + public Expression getCurrentStateAccessorFor(ChannelMember target, ChannelMember from) { + ResourcePath targetRes= target.getResource(); if (from != null) { - if (target.equals(from)) { + ResourcePath fromRes= from.getResource(); + if (!target.isOutside()) { + return getDirectStateAccessorFor(targetRes, fromRes); + } + Term getter = null; + String targetComponentName = getComponentName(targetRes.getResourceHierarchy(), langSpec); + if (generatesComponent(targetRes.getResourceHierarchy())) { + getter = new Term(new Symbol(getterOfResourceState, 1, Symbol.Type.METHOD)); + getter.addChild(new Field(langSpec.toVariableName(targetComponentName), targetRes.getResourceStateType())); + } else { + String parentName = langSpec.toVariableName(getComponentName(targetRes.getResourceHierarchy().getParent(), langSpec)); + Type parentType = targetRes.getResourceHierarchy().getParent().getResourceStateType(); + getter = new Term(new Symbol(getterPrefix + targetComponentName, 1, Symbol.Type.METHOD)); + getter.addChild(new Field(parentName, parentType)); + } + return getter; + } else { + return getDirectStateAccessorFor(targetRes, null); + } + } + + @Override + public Expression getNextStateAccessorFor(ChannelMember target, ChannelMember from) { + ResourcePath targetRes= target.getResource(); + if (from != null) { + ResourcePath fromRes= from.getResource(); + if (!target.isOutside()) { + return getDirectStateAccessorFor(targetRes, fromRes); + } + Term getter = null; + String targetComponentName = getComponentName(targetRes.getResourceHierarchy(), langSpec); + if (generatesComponent(targetRes.getResourceHierarchy())) { + getter = new Term(new Symbol(getterOfResourceState, 1, Symbol.Type.METHOD)); + getter.addChild(new Field(langSpec.toVariableName(targetComponentName), targetRes.getResourceStateType())); + } else { + String parentName = langSpec.toVariableName(getComponentName(targetRes.getResourceHierarchy().getParent(), langSpec)); + Type parentType = targetRes.getResourceHierarchy().getParent().getResourceStateType(); + getter = new Term(new Symbol(getterPrefix + targetComponentName, 1, Symbol.Type.METHOD)); + getter.addChild(new Field(parentName, parentType)); + } + return getter; + } else { + return getDirectStateAccessorFor(targetRes, null); + } + } + + @Override + public Expression getDirectStateAccessorFor(ResourcePath targetRes, ResourcePath fromRes) { + if (fromRes != null) { + if (targetRes.equals(fromRes)) { return new Field(fieldOfResourceState, - target.getResourceStateType() != null ? target.getResourceStateType() + targetRes.getResourceStateType() != null ? targetRes.getResourceStateType() : DataConstraintModel.typeInt); } // for reference channel member Term getter = new Term(new Symbol(getterOfResourceState, 1, Symbol.Type.METHOD)); - getter.addChild(new Field(target.getResourceName(), target.getResourceStateType())); + getter.addChild(new Field(targetRes.getResourceName(), targetRes.getResourceStateType())); return getter; } else { // access from the outside of the hierarchy Stack pathStack = new Stack<>(); - ResourcePath curPath = target; + ResourcePath curPath = targetRes; do { pathStack.push(curPath); curPath = curPath.getParent(); @@ -522,7 +588,7 @@ } } - if (generatesComponent(target.getResourceHierarchy())) { + if (generatesComponent(targetRes.getResourceHierarchy())) { Term newGetter = new Term(new Symbol(getterOfResourceState, 1, Symbol.Type.METHOD)); newGetter.addChild(getter); getter = newGetter; @@ -530,13 +596,6 @@ return getter; } } - - @Override - public Expression getNextStateAccessorFor(ResourcePath target, ResourcePath from) { - Term getter = new Term(new Symbol(getterOfResourceState, 1, Symbol.Type.METHOD)); - getter.addChild(new Field(target.getResourceName(), target.getResourceStateType())); - return getter; - } }; } } diff --git a/AlgebraicDataflowArchitectureModel/src/generators/CodeGeneratorFromDataFlowGraph.java b/AlgebraicDataflowArchitectureModel/src/generators/CodeGeneratorFromDataFlowGraph.java index 7b4edb8..1e37236 100644 --- a/AlgebraicDataflowArchitectureModel/src/generators/CodeGeneratorFromDataFlowGraph.java +++ b/AlgebraicDataflowArchitectureModel/src/generators/CodeGeneratorFromDataFlowGraph.java @@ -152,16 +152,10 @@ DataTransferChannel ch = ((ChannelNode) resToCh.getDestination()).getChannel(); // Check if the input resource is outside of the channel scope. boolean outsideInputResource = false; - if (ch.getAllSelectors().size() > 0) { - Set params = new HashSet<>(); - for (Selector s: ch.getAllSelectors()) { - params.add(s.getExpression()); - } - for (ChannelMember cm: ch.getInputChannelMembers()) { - if (cm.getResource().getResourceHierarchy().equals(resourceNode.getResourceHierarchy()) && !params.containsAll(cm.getResource().getPathParams())) { - outsideInputResource = true; // Regarded as pull transfer. - break; - } + for (ChannelMember cm: ch.getInputChannelMembers()) { + if (cm.getResource().getResourceHierarchy().equals(resourceNode.getResourceHierarchy()) && cm.isOutside()) { + outsideInputResource = true; // Regarded as pull transfer. + break; } } if (((PushPullAttribute) ((DataFlowEdge) resToCh).getAttribute()).getOptions().get(0) == PushPullValue.PUSH && !outsideInputResource) { @@ -179,23 +173,17 @@ DataTransferChannel ch = ((ChannelNode) resToCh.getDestination()).getChannel(); // Check if the input and output resources are outside of the channel scope. boolean outsideInputResource = false; + for (ChannelMember cm: ch.getInputChannelMembers()) { + if (cm.getResource().getResourceHierarchy().equals(srcRes.getResourceHierarchy()) && cm.isOutside()) { + outsideInputResource = true; // Regarded as pull transfer. + break; + } + } boolean outsideOutputResource = false; - if (ch.getAllSelectors().size() > 0) { - Set params = new HashSet<>(); - for (Selector s: ch.getAllSelectors()) { - params.add(s.getExpression()); - } - for (ChannelMember cm: ch.getInputChannelMembers()) { - if (cm.getResource().getResourceHierarchy().equals(srcRes.getResourceHierarchy()) && !params.containsAll(cm.getResource().getPathParams())) { - outsideInputResource = true; // Regarded as pull transfer. - break; - } - } - for (ChannelMember cm: ch.getOutputChannelMembers()) { - if (cm.getResource().getResourceHierarchy().equals(resourceNode.getOutSideResource().getResourceHierarchy()) && !params.containsAll(cm.getResource().getPathParams())) { - outsideOutputResource = true; // Regarded as push transfer. - break; - } + 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 && !outsideOutputResource) || outsideInputResource) { @@ -247,16 +235,10 @@ ResourcePath dstRes = ((ResourceNode) chToRes.getDestination()).getOutSideResource(); // Check if the destination resource is outside of the channel scope. boolean outsideOutputResource = false; - if (ch.getAllSelectors().size() > 0) { - Set params = new HashSet<>(); - for (Selector s: ch.getAllSelectors()) { - params.add(s.getExpression()); - } - for (ChannelMember cm: ch.getOutputChannelMembers()) { - if (cm.getResource().getResourceHierarchy().equals(dstRes.getResourceHierarchy()) && !params.containsAll(cm.getResource().getPathParams())) { - outsideOutputResource = true; // Regarded as push transfer. - break; - } + for (ChannelMember cm: ch.getOutputChannelMembers()) { + if (cm.getResource().getResourceHierarchy().equals(dstRes.getResourceHierarchy()) && cm.isOutside()) { + outsideOutputResource = true; // Regarded as push transfer. + break; } } if (outsideOutputResource) { @@ -279,16 +261,10 @@ DataTransferChannel ch = ((ChannelNode) re.getDestination()).getChannel(); // Check if the source resource is outside of the channel scope. boolean outsideInputResource = false; - if (ch.getAllSelectors().size() > 0) { - Set params = new HashSet<>(); - for (Selector s: ch.getAllSelectors()) { - params.add(s.getExpression()); - } - for (ChannelMember cm: ch.getInputChannelMembers()) { - if (cm.getResource().getResourceHierarchy().equals(srcRes.getResourceHierarchy()) && !params.containsAll(cm.getResource().getPathParams())) { - outsideInputResource = true; // Regarded as pull transfer. - break; - } + for (ChannelMember cm: ch.getInputChannelMembers()) { + if (cm.getResource().getResourceHierarchy().equals(srcRes.getResourceHierarchy()) && cm.isOutside()) { + outsideInputResource = true; // Regarded as pull transfer. + break; } } if (outsideInputResource) { @@ -343,59 +319,67 @@ } } - if (component != null) { - // A component is created for this resource. - if (((StoreAttribute) resourceNode.getAttribute()).isStored()) { + if (((StoreAttribute) resourceNode.getAttribute()).isStored()) { + if (component != null) { + // A component is created for this resource. 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()); - } 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()); - } + } else { + // No component is created for this resource. + fillChildGetterMethod(stateGetter, resourceNode.getResourceHierarchy(), resourceNode.getResourceHierarchy().getParent().getResourceStateType(), 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; } } - } catch (ParameterizedIdentifierIsFutureWork | ResolvingMultipleDefinitionIsFutureWork - | InvalidMessage | UnificationFailed | ValueUndefined e) { - e.printStackTrace(); + 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. + } } } - } else { - // No component is created for this resource. - fillChildGetterMethod(stateGetter, resourceNode.getResourceHierarchy(), resourceNode.getResourceHierarchy().getParent().getResourceStateType(), langSpec); + // 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(); + } } return stateGetter; @@ -439,18 +423,26 @@ List updateMethods = new ArrayList<>(); for (Edge chToRes: resourceNode.getInEdges()) { for (Edge resToCh: chToRes.getSource().getInEdges()) { + DataTransferChannel ch = ((ChannelNode) resToCh.getDestination()).getChannel(); DataFlowEdge re = (DataFlowEdge) resToCh; ResourcePath srcRes = ((ResourceNode) re.getSource()).getOutSideResource(); String srcResName = srcRes.getResourceName(); String srcResComponentName = langSpec.toComponentName(srcResName); - if (((PushPullAttribute) re.getAttribute()).getOptions().get(0) == PushPullValue.PUSH) { + // 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()) { + outsideInputResource = true; // Regarded as pull transfer. + break; + } + } + if (((PushPullAttribute) re.getAttribute()).getOptions().get(0) == PushPullValue.PUSH && !outsideInputResource) { // for push data transfer // Declare an update method in the type of the destination resource. ArrayList vars = new ArrayList<>(); vars.add(langSpec.newVariableDeclaration(srcRes.getResourceStateType(), srcRes.getResourceName())); // For the refs. - DataTransferChannel ch = ((ChannelNode) resToCh.getDestination()).getChannel(); for (ResourcePath ref: ch.getReferenceResources()) { if (!resourceNode.getInSideResources().contains(ref)) { vars.add(langSpec.newVariableDeclaration(ref.getResourceStateType(), ref.getResourceName())); @@ -463,9 +455,9 @@ // Add a statement to update the state field if (((StoreAttribute) resourceNode.getAttribute()).isStored()) { try { - for (ChannelMember out: ((ChannelNode) resToCh.getDestination()).getChannel().getOutputChannelMembers()) { + for (ChannelMember out: ch.getOutputChannelMembers()) { if (resourceNode.getInSideResources().contains(out.getResource())) { - Expression updateExp = ((ChannelNode) resToCh.getDestination()).getChannel().deriveUpdateExpressionOf(out, getPushAccessor()); + Expression updateExp = ch.deriveUpdateExpressionOf(out, getPushAccessor()); String[] sideEffects = new String[] {""}; String curState = updateExp.toImplementation(sideEffects); String updateStatement; @@ -499,7 +491,7 @@ } // Update the cache field. - String cashStatement = langSpec.getFieldAccessor(srcResName) + langSpec.getAssignment() + srcResName + langSpec.getStatementDelimiter(); + String cashStatement = langSpec.getFieldAccessor(langSpec.toVariableName(srcResName)) + langSpec.getAssignment() + langSpec.toVariableName(srcResName) + langSpec.getStatementDelimiter(); if (update.getBody() == null || !update.getBody().getStatements().contains(cashStatement)) { update.addFirstStatement(cashStatement); } @@ -508,14 +500,30 @@ // Add an invocation to another update method (for a chain of update method invocations). for (Edge resToCh2: resourceNode.getOutEdges()) { DataFlowEdge dOut = (DataFlowEdge) resToCh2; - if (((PushPullAttribute) dOut.getAttribute()).getOptions().get(0) == PushPullValue.PUSH) { + DataTransferChannel ch2 = ((ChannelNode) resToCh2.getDestination()).getChannel(); + // Check if the input resource is outside of the channel scope. + boolean outsideInputResource2 = false; + for (ChannelMember cm: ch2.getInputChannelMembers()) { + if (cm.getResource().getResourceHierarchy().equals(resourceNode.getResourceHierarchy()) && cm.isOutside()) { + outsideInputResource2 = true; // Regarded as pull transfer. + break; + } + } + if (((PushPullAttribute) dOut.getAttribute()).getOptions().get(0) == PushPullValue.PUSH && !outsideInputResource2) { for (Edge chToRes2: resToCh2.getDestination().getOutEdges()) { // PUSH transfer + ChannelMember in = null; + for (ChannelMember cm: ch2.getInputChannelMembers()) { + if (cm.getResource().equals(resourceNode.getOutSideResource())) { + in = cm; + break; + } + } Map> referredResources = new HashMap<>(); List params = new ArrayList<>(); params.add(langSpec.getFieldAccessor(fieldOfResourceState)); Set referredSet = referredResources.get(update); - for (ChannelMember rc: ((ChannelNode) resToCh.getDestination()).getChannel().getReferenceChannelMembers()) { + for (ChannelMember rc: ch2.getReferenceChannelMembers()) { // to get the value of reference member. ResourcePath ref = rc.getResource(); if (referredSet == null) { @@ -526,7 +534,7 @@ String refVarName = ref.getResourceName(); if (!referredSet.contains(ref)) { referredSet.add(ref); - Expression refGetter = getPullAccessor().getCurrentStateAccessorFor(ref, ((ResourceNode) resToCh2.getSource()).getOutSideResource()); + Expression refGetter = getPullAccessor().getCurrentStateAccessorFor(rc, in); String[] sideEffects = new String[] {""}; String refExp = refGetter.toImplementation(sideEffects); String refTypeName = ref.getResourceStateType().getInterfaceTypeName(); @@ -678,7 +686,7 @@ // Add an invocation to the accessor method. if (inputAccessor != null) { - Expression resExp = getPullAccessor().getCurrentStateAccessorFor(out.getResource(), null); + Expression resExp = getPullAccessor().getDirectStateAccessorFor(out.getResource(), null); List args = new ArrayList<>(); if (resExp instanceof Term) { // to access the parent @@ -748,14 +756,29 @@ // Add an invocation to an update method (for a chain of update method invocations). for (Edge resToCh: resourceNode.getOutEdges()) { DataFlowEdge dOut = (DataFlowEdge) resToCh; - if (((PushPullAttribute) dOut.getAttribute()).getOptions().get(0) == PushPullValue.PUSH) { + DataTransferChannel ch2 = ((ChannelNode) resToCh.getDestination()).getChannel(); + boolean outsideInputResource2 = false; + for (ChannelMember cm: ch2.getInputChannelMembers()) { + if (cm.getResource().getResourceHierarchy().equals(resourceNode.getResourceHierarchy()) && cm.isOutside()) { + outsideInputResource2 = true; // Regarded as pull transfer. + break; + } + } + if (((PushPullAttribute) dOut.getAttribute()).getOptions().get(0) == PushPullValue.PUSH && !outsideInputResource2) { for (Edge chToRes: resToCh.getDestination().getOutEdges()) { // PUSH transfer + ChannelMember in = null; + for (ChannelMember cm: ch2.getInputChannelMembers()) { + if (cm.getResource().equals(resourceNode.getOutSideResource())) { + in = cm; + break; + } + } Map> referredResources = new HashMap<>(); List params = new ArrayList<>(); params.add(langSpec.getFieldAccessor(fieldOfResourceState)); Set referredSet = referredResources.get(input); - for (ChannelMember rc: ((DataTransferChannel) ch).getReferenceChannelMembers()) { + for (ChannelMember rc: ch2.getReferenceChannelMembers()) { // to get the value of reference member. ResourcePath ref = rc.getResource(); if (referredSet == null) { @@ -766,7 +789,7 @@ String refVarName = ref.getResourceName(); if (!referredSet.contains(ref)) { referredSet.add(ref); - Expression refGetter = getPullAccessor().getCurrentStateAccessorFor(ref, ((ResourceNode) resToCh.getSource()).getOutSideResource()); + Expression refGetter = getPullAccessor().getCurrentStateAccessorFor(rc, in); String[] sideEffects = new String[] {""}; String refExp = refGetter.toImplementation(sideEffects); String refTypeName = ref.getResourceStateType().getInterfaceTypeName(); diff --git a/AlgebraicDataflowArchitectureModel/src/generators/JavaCodeGenerator.java b/AlgebraicDataflowArchitectureModel/src/generators/JavaCodeGenerator.java index 2833000..b9cf60e 100644 --- a/AlgebraicDataflowArchitectureModel/src/generators/JavaCodeGenerator.java +++ b/AlgebraicDataflowArchitectureModel/src/generators/JavaCodeGenerator.java @@ -125,33 +125,33 @@ static public ArrayList doGenerate(DataFlowGraph graph, DataTransferModel model) { ArrayList codes = new ArrayList<>(); ArrayList resources = determineResourceOrder(graph); - Map resourceTypes = new HashMap<>(); + Map resourceComponents = new HashMap<>(); List> getters = new ArrayList<>(); List> inputs = new ArrayList<>(); List> fields = new ArrayList<>(); - TypeDeclaration mainType = new TypeDeclaration(mainTypeName); - CompilationUnit mainCU = new CompilationUnit(mainType); + TypeDeclaration mainComponent = new TypeDeclaration(mainTypeName); + CompilationUnit mainCU = new CompilationUnit(mainComponent); mainCU.addImport(new ImportDeclaration("java.util.*")); codes.add(mainCU); // Declare the constructor of the main type. MethodDeclaration mainConstructor = new MethodDeclaration(mainTypeName, true); - mainType.addMethod(mainConstructor); + mainComponent.addMethod(mainConstructor); // For each resource node. for (ResourceNode rn: resources) { - TypeDeclaration type = null; + TypeDeclaration component = null; if (generatesComponent(rn.getResourceHierarchy())) { boolean f = false; String resourceName = getComponentName(rn.getResourceHierarchy()); - type = resourceTypes.get(rn.getResourceHierarchy()); - if (type == null) { + component = resourceComponents.get(rn.getResourceHierarchy()); + if (component == null) { // Add compilation unit for each resource. - type = new TypeDeclaration(resourceName); - resourceTypes.put(rn.getResourceHierarchy(), type); - CompilationUnit cu = new CompilationUnit(type); + component = new TypeDeclaration(resourceName); + resourceComponents.put(rn.getResourceHierarchy(), component); + CompilationUnit cu = new CompilationUnit(component); cu.addImport(new ImportDeclaration("java.util.*")); codes.add(cu); @@ -186,7 +186,7 @@ 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( + component.addField(new FieldDeclaration( cashRes.getResourceStateType(), ((ResourceNode) re.getSource()).getOutSideResource().getResourceName(), getInitializer(cashRes))); } } @@ -208,7 +208,7 @@ if (f) fieldInitializer = fieldInitializer.substring(0, fieldInitializer.length() - 1); fieldInitializer += ")"; FieldDeclaration field = new FieldDeclaration(new Type(resourceName, resourceName), rn.getResourceName()); - mainType.addField(field); + mainComponent.addField(field); Block mainConstructorBody = mainConstructor.getBody(); if (mainConstructorBody == null) { mainConstructorBody = new Block(); @@ -226,16 +226,10 @@ DataTransferChannel ch = ((ChannelNode) re.getDestination()).getChannel(); // Check if the input resource is outside of the channel scope. boolean outsideInputResource = false; - if (ch.getAllSelectors().size() > 0) { - Set params = new HashSet<>(); - for (Selector s: ch.getAllSelectors()) { - params.add(s.getExpression()); - } - for (ChannelMember cm: ch.getInputChannelMembers()) { - if (cm.getResource().getResourceHierarchy().equals(rn.getResourceHierarchy()) && !params.containsAll(cm.getResource().getPathParams())) { - outsideInputResource = true; // Regarded as pull transfer. - break; - } + for (ChannelMember cm: ch.getInputChannelMembers()) { + if (cm.getResource().getResourceHierarchy().equals(rn.getResourceHierarchy()) && cm.isOutside()) { + outsideInputResource = true; // Regarded as pull transfer. + break; } } if (((PushPullAttribute) re.getAttribute()).getOptions().get(0) == PushPullValue.PUSH && !outsideInputResource) { @@ -249,7 +243,7 @@ dstResName = getComponentName(dstRes.getResourceHierarchy().getParent()); } depends.add(dstRes); - type.addField(new FieldDeclaration(new Type(dstResName, dstResName), toVariableName(dstResName))); + component.addField(new FieldDeclaration(new Type(dstResName, dstResName), toVariableName(dstResName))); constructor.addParameter(new VariableDeclaration(new Type(dstResName, dstResName), toVariableName(dstResName))); block.addStatement("this." + toVariableName(dstResName) + " = " + toVariableName(dstResName) + ";"); } @@ -262,23 +256,17 @@ DataTransferChannel ch = ((ChannelNode) re.getDestination()).getChannel(); // Check if the input and output resources are outside of the channel scope. boolean outsideInputResource = false; + for (ChannelMember cm: ch.getInputChannelMembers()) { + if (cm.getResource().getResourceHierarchy().equals(srcRes.getResourceHierarchy()) && cm.isOutside()) { + outsideInputResource = true; // Regarded as pull transfer. + break; + } + } boolean outsideOutputResource = false; - if (ch.getAllSelectors().size() > 0) { - Set params = new HashSet<>(); - for (Selector s: ch.getAllSelectors()) { - params.add(s.getExpression()); - } - for (ChannelMember cm: ch.getInputChannelMembers()) { - if (cm.getResource().getResourceHierarchy().equals(srcRes.getResourceHierarchy()) && !params.containsAll(cm.getResource().getPathParams())) { - outsideInputResource = true; // Regarded as pull transfer. - break; - } - } - for (ChannelMember cm: ch.getOutputChannelMembers()) { - if (cm.getResource().getResourceHierarchy().equals(rn.getOutSideResource().getResourceHierarchy()) && !params.containsAll(cm.getResource().getPathParams())) { - outsideOutputResource = true; // Regarded as push transfer. - break; - } + for (ChannelMember cm: ch.getOutputChannelMembers()) { + if (cm.getResource().getResourceHierarchy().equals(rn.getOutSideResource().getResourceHierarchy()) && cm.isOutside()) { + outsideOutputResource = true; // Regarded as push transfer. + break; } } String srcResName = null; @@ -290,7 +278,7 @@ 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(srcRes); - type.addField(new FieldDeclaration(new Type(srcResName, srcResName), toVariableName(srcResName))); + component.addField(new FieldDeclaration(new Type(srcResName, srcResName), toVariableName(srcResName))); constructor.addParameter(new VariableDeclaration(new Type(srcResName, srcResName), toVariableName(srcResName))); block.addStatement("this." + toVariableName(srcResName) + " = " + toVariableName(srcResName) + ";"); } else { @@ -303,7 +291,7 @@ vars.add(new VariableDeclaration(ref.getResourceStateType(), ref.getResourceName())); } } - type.addMethod(new MethodDeclaration("update" + srcResName, false, typeVoid, vars)); + component.addMethod(new MethodDeclaration("update" + srcResName, false, typeVoid, vars)); } } } @@ -316,7 +304,7 @@ 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())); + component.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() + ";"); } @@ -325,7 +313,7 @@ } constructor.setBody(block); if (constructor.getParameters() != null) - type.addMethod(constructor); + component.addMethod(constructor); } // Declare the field to store the state in the type of each resource. @@ -334,12 +322,12 @@ Set children = rn.getResourceHierarchy().getChildren(); if (children == null || children.size() == 0) { // leaf resource. - type.addField(new FieldDeclaration(getImplStateType(res.getResourceHierarchy()), "value", getInitializer(res))); + component.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))); + component.addField(new FieldDeclaration(getImplStateType(res.getResourceHierarchy()), "value", getInitializer(res))); } else { // class for (ResourceHierarchy c: children) { @@ -349,7 +337,7 @@ // The child has a component. childType = new Type(childTypeName, childTypeName); String fieldName = toVariableName(childTypeName); - type.addField(new FieldDeclaration(childType, fieldName, getInitializer(res))); + component.addField(new FieldDeclaration(childType, fieldName, getInitializer(res))); } } } @@ -380,13 +368,13 @@ } else { childGetter = new MethodDeclaration("get" + childCompName, false, childType, params); } - type.addMethod(childGetter); + component.addMethod(childGetter); } } } // Declare the state field and reference fields in the parent component. - if (type == null) { + if (component == null) { // Declare reference fields for push/pull data transfer. boolean noPullTransfer = true; for (Edge resToCh : rn.getOutEdges()) { @@ -395,16 +383,10 @@ for (Edge chToRes: re.getDestination().getOutEdges()) { ResourcePath dstRes = ((ResourceNode) chToRes.getDestination()).getOutSideResource(); boolean outsideOutputResource = false; - if (ch.getAllSelectors().size() > 0) { - Set params = new HashSet<>(); - for (Selector s: ch.getAllSelectors()) { - params.add(s.getExpression()); - } - for (ChannelMember cm: ch.getOutputChannelMembers()) { - if (cm.getResource().getResourceHierarchy().equals(dstRes.getResourceHierarchy()) && !params.containsAll(cm.getResource().getPathParams())) { - outsideOutputResource = true; // Regarded as push transfer. - break; - } + for (ChannelMember cm: ch.getOutputChannelMembers()) { + if (cm.getResource().getResourceHierarchy().equals(dstRes.getResourceHierarchy()) && cm.isOutside()) { + outsideOutputResource = true; // Regarded as push transfer. + break; } } if (outsideOutputResource) { @@ -426,16 +408,10 @@ ResourcePath srcRes = ((ResourceNode) re.getSource()).getOutSideResource(); DataTransferChannel ch = ((ChannelNode) re.getDestination()).getChannel(); boolean outsideInputResource = false; - if (ch.getAllSelectors().size() > 0) { - Set params = new HashSet<>(); - for (Selector s: ch.getAllSelectors()) { - params.add(s.getExpression()); - } - for (ChannelMember cm: ch.getInputChannelMembers()) { - if (cm.getResource().getResourceHierarchy().equals(srcRes.getResourceHierarchy()) && !params.containsAll(cm.getResource().getPathParams())) { - outsideInputResource = true; // Regarded as pull transfer. - break; - } + for (ChannelMember cm: ch.getInputChannelMembers()) { + if (cm.getResource().getResourceHierarchy().equals(srcRes.getResourceHierarchy()) && cm.isOutside()) { + outsideInputResource = true; // Regarded as pull transfer. + break; } } if (outsideInputResource) { @@ -462,10 +438,10 @@ } // Declare the getter method in this component to obtain the resource state. - if (type != null) { + if (component != null) { // A component is created for this resource. MethodDeclaration stateGetter = new MethodDeclaration("getValue", getImplStateType(rn.getResourceHierarchy())); - type.addMethod(stateGetter); + component.addMethod(stateGetter); } else { // No component is created for this resource. List getterParams = new ArrayList<>(); @@ -515,9 +491,9 @@ getImplStateType(rn.getResourceHierarchy())); } accessor.setBody(new Block()); - Expression getState = JavaCodeGenerator.pullAccessor.getCurrentStateAccessorFor(rn.getOutSideResource(), null); + Expression getState = JavaCodeGenerator.pullAccessor.getDirectStateAccessorFor(rn.getOutSideResource(), null); accessor.getBody().addStatement("return " + getState.toImplementation(new String[] {null}) + ";"); - mainType.addMethod(accessor); + mainComponent.addMethod(accessor); // Declare the input method in this component and the main component. for (Channel ch : model.getIOChannels()) { @@ -560,9 +536,9 @@ MethodDeclaration input = new MethodDeclaration( ((Term) cm.getStateTransition().getMessageExpression()).getSymbol().getImplName(), false, typeVoid, resInputParams); - if (type != null) { + if (component != null) { // A component is created for this resource. - type.addMethod(input); + component.addMethod(input); } else { // No component is created for this resource. inputs.add(new AbstractMap.SimpleEntry(rn.getParent().getResourceHierarchy(), input)); @@ -570,10 +546,10 @@ // In the main type. String str = ((Term) cm.getStateTransition().getMessageExpression()).getSymbol().getImplName(); - input = getMethod(mainType, str, mainInputParams); + input = getMethod(mainComponent, str, mainInputParams); if (input == null) { input = new MethodDeclaration(str, false, typeVoid, mainInputParams); - mainType.addMethod(input); + mainComponent.addMethod(input); } else { // Add type to a parameter without type. for (VariableDeclaration param: input.getParameters()) { @@ -625,9 +601,9 @@ ((Variable) cm.getStateTransition().getMessageExpression()).getName(), false, typeVoid, null); } - if (type != null) { + if (component != null) { // A component is created for this resource. - type.addMethod(input); + component.addMethod(input); } else { // No component is created for this resource. inputs.add(new AbstractMap.SimpleEntry(rn.getParent().getResourceHierarchy(), input)); @@ -635,14 +611,14 @@ // In the main type. String str = ((Variable) cm.getStateTransition().getMessageExpression()).getName(); - input = getMethod(mainType, str, mainInputParams); + input = getMethod(mainComponent, str, mainInputParams); if (input == null) { if (mainInputParams.size() > 0) { input = new MethodDeclaration(str, false, typeVoid, mainInputParams); } else { input = new MethodDeclaration(str, false, typeVoid, null); } - mainType.addMethod(input); + mainComponent.addMethod(input); } } } @@ -652,17 +628,17 @@ // Add leaf getter methods to the parent components. for (Map.Entry entry: getters) { - resourceTypes.get(entry.getKey()).addMethod(entry.getValue()); + resourceComponents.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()); + resourceComponents.get(entry.getKey()).addMethod(entry.getValue()); } // Add leaf reference fields to the parent components. for (Map.Entry entry: fields) { - resourceTypes.get(entry.getKey()).addField(entry.getValue()); + resourceComponents.get(entry.getKey()).addField(entry.getValue()); } // Declare the Pair class. @@ -841,43 +817,109 @@ static public IResourceStateAccessor pushAccessor = new IResourceStateAccessor() { @Override - public Expression getCurrentStateAccessorFor(ResourcePath target, ResourcePath from) { - if (target.equals(from)) { + public Expression getCurrentStateAccessorFor(ChannelMember target, ChannelMember from) { + ResourcePath targetRes = target.getResource(); + ResourcePath fromRes = from.getResource(); + if (targetRes.equals(fromRes)) { return new Field("value", - target.getResourceStateType() != null ? target.getResourceStateType() + targetRes.getResourceStateType() != null ? targetRes.getResourceStateType() : DataConstraintModel.typeInt); } // for reference channel member - return new Parameter(target.getResourceName(), - target.getResourceStateType() != null ? target.getResourceStateType() + return new Parameter(targetRes.getResourceName(), + targetRes.getResourceStateType() != null ? targetRes.getResourceStateType() : DataConstraintModel.typeInt); } @Override - public Expression getNextStateAccessorFor(ResourcePath target, ResourcePath from) { - return new Parameter(target.getResourceName(), - target.getResourceStateType() != null ? target.getResourceStateType() + public Expression getNextStateAccessorFor(ChannelMember target, ChannelMember from) { + ResourcePath targetRes = target.getResource(); + return new Parameter(targetRes.getResourceName(), + targetRes.getResourceStateType() != null ? targetRes.getResourceStateType() + : DataConstraintModel.typeInt); + } + + @Override + public Expression getDirectStateAccessorFor(ResourcePath targetRes, ResourcePath fromRes) { + if (fromRes != null && targetRes.equals(fromRes)) { + return new Field("value", + targetRes.getResourceStateType() != null ? targetRes.getResourceStateType() + : DataConstraintModel.typeInt); + } + // for reference channel member + return new Parameter(targetRes.getResourceName(), + targetRes.getResourceStateType() != null ? targetRes.getResourceStateType() : DataConstraintModel.typeInt); } }; static public IResourceStateAccessor pullAccessor = new IResourceStateAccessor() { @Override - public Expression getCurrentStateAccessorFor(ResourcePath target, ResourcePath from) { + public Expression getCurrentStateAccessorFor(ChannelMember target, ChannelMember from) { + ResourcePath targetRes = target.getResource(); if (from != null) { - if (target.equals(from)) { + ResourcePath fromRes = from.getResource(); + if (!target.isOutside()) { + return getDirectStateAccessorFor(targetRes, fromRes); + } + Term getter = null; + String targetComponentName = getComponentName(targetRes.getResourceHierarchy()); + if (generatesComponent(targetRes.getResourceHierarchy())) { + getter = new Term(new Symbol("getValue", 1, Symbol.Type.METHOD)); + getter.addChild(new Field(toVariableName(targetComponentName), targetRes.getResourceStateType())); + } else { + String parentName = toVariableName(getComponentName(targetRes.getResourceHierarchy().getParent())); + Type parentType = targetRes.getResourceHierarchy().getParent().getResourceStateType(); + getter = new Term(new Symbol("get" + targetComponentName, 1, Symbol.Type.METHOD)); + getter.addChild(new Field(parentName, parentType)); + } + return getter; + } else { + return getDirectStateAccessorFor(targetRes, null); + } + } + + @Override + public Expression getNextStateAccessorFor(ChannelMember target, ChannelMember from) { + ResourcePath targetRes = target.getResource(); + if (from != null) { + ResourcePath fromRes = from.getResource(); + if (!target.isOutside()) { + return getDirectStateAccessorFor(targetRes, fromRes); + } + Term getter = null; + String targetComponentName = getComponentName(targetRes.getResourceHierarchy()); + if (generatesComponent(targetRes.getResourceHierarchy())) { + getter = new Term(new Symbol("getValue", 1, Symbol.Type.METHOD)); + getter.addChild(new Field(toVariableName(targetComponentName), targetRes.getResourceStateType())); + } else { + String parentName = toVariableName(getComponentName(targetRes.getResourceHierarchy().getParent())); + Type parentType = targetRes.getResourceHierarchy().getParent().getResourceStateType(); + getter = new Term(new Symbol("get" + targetComponentName, 1, Symbol.Type.METHOD)); + getter.addChild(new Field(parentName, parentType)); + } + return getter; + } else { + return getDirectStateAccessorFor(targetRes, null); + } + } + + @Override + public Expression getDirectStateAccessorFor(ResourcePath targetRes, ResourcePath fromRes) { + if (fromRes != null) { + if (targetRes.equals(fromRes)) { return new Field("value", - target.getResourceStateType() != null ? target.getResourceStateType() + targetRes.getResourceStateType() != null ? targetRes.getResourceStateType() : DataConstraintModel.typeInt); } // for reference channel member Term getter = new Term(new Symbol("getValue", 1, Symbol.Type.METHOD)); - getter.addChild(new Field(target.getResourceName(), target.getResourceStateType())); + getter.addChild(new Field(targetRes.getResourceName(), targetRes.getResourceStateType())); return getter; } else { // access from the outside of the hierarchy Stack pathStack = new Stack<>(); - ResourcePath curPath = target; + ResourcePath curPath = targetRes; do { pathStack.push(curPath); curPath = curPath.getParent(); @@ -912,7 +954,7 @@ getter = newGetter; } } - if (generatesComponent(target.getResourceHierarchy())) { + if (generatesComponent(targetRes.getResourceHierarchy())) { Term newGetter = new Term(new Symbol("getValue", 1, Symbol.Type.METHOD)); newGetter.addChild(getter); getter = newGetter; @@ -920,12 +962,5 @@ return getter; } } - - @Override - public Expression getNextStateAccessorFor(ResourcePath target, ResourcePath from) { - Term getter = new Term(new Symbol("getValue", 1, Symbol.Type.METHOD)); - getter.addChild(new Field(target.getResourceName(), target.getResourceStateType())); - return getter; - } }; } diff --git a/AlgebraicDataflowArchitectureModel/src/generators/JavaMethodBodyGenerator.java b/AlgebraicDataflowArchitectureModel/src/generators/JavaMethodBodyGenerator.java index 2723a82..607c330 100644 --- a/AlgebraicDataflowArchitectureModel/src/generators/JavaMethodBodyGenerator.java +++ b/AlgebraicDataflowArchitectureModel/src/generators/JavaMethodBodyGenerator.java @@ -46,10 +46,10 @@ public class JavaMethodBodyGenerator { public static ArrayList doGenerate(DataFlowGraph graph, DataTransferModel model, ArrayList codes) { // Create a map from type names (lower case) to their types. - Map typeMap = new HashMap<>(); + Map componentMap = new HashMap<>(); for (CompilationUnit code: codes) { - for (TypeDeclaration type: code.types()) { - typeMap.put(type.getTypeName(), type); + for (TypeDeclaration component: code.types()) { + componentMap.put(component.getTypeName(), component); } } @@ -65,16 +65,43 @@ ResourceNode dst = (ResourceNode) chToRes.getDestination(); String srcResourceName = JavaCodeGenerator.getComponentName(src.getResourceHierarchy()); String dstResourceName = JavaCodeGenerator.getComponentName(dst.getResourceHierarchy()); - TypeDeclaration srcType = typeMap.get(srcResourceName); - TypeDeclaration dstType = typeMap.get(dstResourceName); - for (ChannelMember out: ((ChannelNode) resToCh.getDestination()).getChannel().getOutputChannelMembers()) { + TypeDeclaration srcComponent = componentMap.get(srcResourceName); + TypeDeclaration dstComponent = componentMap.get(dstResourceName); + DataTransferChannel ch = ((ChannelNode) resToCh.getDestination()).getChannel(); + for (ChannelMember out: ch.getOutputChannelMembers()) { if (dst.getInSideResources().contains(out.getResource())) { - if (pushPull.getOptions().get(0) == PushPullValue.PUSH && srcType != null) { + // Check if the input resource is outside of the channel scope. + boolean outsideInputResource = false; + for (ChannelMember cm: ch.getInputChannelMembers()) { + if (cm.getResource().getResourceHierarchy().equals(src.getResourceHierarchy()) && 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(dst.getResourceHierarchy()) && cm.isOutside()) { + outsideOutputResource = true; // Regarded as push transfer. + break; + } + } + if (pushPull.getOptions().get(0) == PushPullValue.PUSH && !outsideInputResource) { // for push data transfer - MethodDeclaration update = getUpdateMethod(dstType, srcType); + String srcResName = null; + if (srcComponent == null) { + srcResName = srcResourceName; + } else { + srcResName = srcComponent.getTypeName(); + } + if (dstComponent == null) { + String dstParentResourceName = JavaCodeGenerator.getComponentName(dst.getResourceHierarchy().getParent()); + dstComponent = componentMap.get(dstParentResourceName); + } + MethodDeclaration update = getUpdateMethod(dstComponent, srcResName); if (((StoreAttribute) dst.getAttribute()).isStored()) { // update stored state of dst side resource (when every incoming edge is in push style) - Expression updateExp = ((ChannelNode) resToCh.getDestination()).getChannel().deriveUpdateExpressionOf(out, JavaCodeGenerator.pushAccessor); + Expression updateExp = ch.deriveUpdateExpressionOf(out, JavaCodeGenerator.pushAccessor); String[] sideEffects = new String[] {""}; String curState = updateExp.toImplementation(sideEffects); String updateStatement; @@ -89,14 +116,19 @@ } if (resToCh.getDestination().getIndegree() > 1) { // update a cash of src side resource (when incoming edges are multiple) - String cashStatement = "this." + srcResourceName + " = " + srcResourceName + ";"; + String cashStatement = "this." + JavaCodeGenerator.toVariableName(srcResourceName) + " = " + JavaCodeGenerator.toVariableName(srcResourceName) + ";"; if (update.getBody() == null || !update.getBody().getStatements().contains(cashStatement)) { update.addFirstStatement(cashStatement); } } if (((StoreAttribute) dst.getAttribute()).isStored()) { // returns the current state stored in a field. - MethodDeclaration getter = getGetterMethod(dstType, dst.getResourceStateType()); + MethodDeclaration getter = null; + if (JavaCodeGenerator.generatesComponent(dst.getResourceHierarchy())) { + getter = getMethod(dstComponent, "getValue"); + } else { + getter = getGetterMethod(dstComponent, dstResourceName); + } if (getter.getBody() == null || getter.getBody().getStatements().size() == 0) { Type resourceType = dst.getResourceStateType(); if (dst.getResourceHierarchy().getNumParameters() == 0) { @@ -123,10 +155,17 @@ } } // src side (for a chain of update method invocations) - for (MethodDeclaration srcUpdate: getUpdateMethods(srcType)) { + ChannelMember in = null; + for (ChannelMember cm: ch.getInputChannelMembers()) { + if (cm.getResource().equals(src.getOutSideResource())) { + in = cm; + break; + } + } + for (MethodDeclaration srcUpdate: getUpdateMethods(srcComponent)) { String refParams = ""; Set referredSet = referredResources.get(srcUpdate); - for (ChannelMember rc: ((ChannelNode) resToCh.getDestination()).getChannel().getReferenceChannelMembers()) { + for (ChannelMember rc: ch.getReferenceChannelMembers()) { // to get the value of reference member. ResourcePath ref = rc.getResource(); if (referredSet == null) { @@ -137,7 +176,7 @@ String refVarName = ref.getResourceName(); if (!referredSet.contains(ref)) { referredSet.add(ref); - Expression refGetter = JavaCodeGenerator.pullAccessor.getCurrentStateAccessorFor(ref, src.getOutSideResource()); + Expression refGetter = JavaCodeGenerator.pullAccessor.getCurrentStateAccessorFor(rc, in); String[] sideEffects = new String[] {""}; String refExp = refGetter.toImplementation(sideEffects); String refTypeName = ref.getResourceStateType().getInterfaceTypeName(); @@ -146,12 +185,12 @@ refParams += ", " + refVarName; } } - srcUpdate.addStatement("this." + dstResourceName + ".update" + srcType.getTypeName() + "(value" + refParams + ");"); + srcUpdate.addStatement("this." + dstResourceName + ".update" + srcComponent.getTypeName() + "(value" + refParams + ");"); } - for (MethodDeclaration srcInput: getInputMethods(srcType, src, model)) { + for (MethodDeclaration srcInput: getInputMethods(srcComponent, src, model)) { String refParams = ""; Set referredSet = referredResources.get(srcInput); - for (ChannelMember rc: ((ChannelNode) resToCh.getDestination()).getChannel().getReferenceChannelMembers()) { + for (ChannelMember rc: ch.getReferenceChannelMembers()) { // to get the value of reference member. ResourcePath ref = rc.getResource(); if (referredSet == null) { @@ -162,7 +201,7 @@ String refVarName = ref.getResourceName(); if (!referredSet.contains(ref)) { referredSet.add(ref); - Expression refGetter = JavaCodeGenerator.pullAccessor.getCurrentStateAccessorFor(ref, src.getOutSideResource()); + Expression refGetter = JavaCodeGenerator.pullAccessor.getCurrentStateAccessorFor(rc, in); String[] sideEffects = new String[] {""}; String refExp = refGetter.toImplementation(sideEffects); String refTypeName = ref.getResourceStateType().getInterfaceTypeName(); @@ -171,59 +210,74 @@ refParams += ", " + refVarName; } } - srcInput.addStatement("this." + dstResourceName + ".update" + srcType.getTypeName() + "(value" + refParams + ");"); + srcInput.addStatement("this." + dstResourceName + ".update" + srcComponent.getTypeName() + "(value" + refParams + ");"); } - } else { + } else if ((pushPull.getOptions().get(0) != PushPullValue.PUSH && !outsideOutputResource) || outsideInputResource) { // for pull (or push/pull) data transfer - if (dst.getNumberOfParameters() == 0) { - MethodDeclaration getter = getGetterMethod(dstType, dst.getResourceStateType()); - if (getter.getBody() == null || getter.getBody().getStatements().size() == 0) { - boolean isContainedPush = false; - HashMap inputResourceToStateAccessor = new HashMap<>(); - for (Edge chToRes2: dst.getInEdges()) { - for (Edge resToCh2: chToRes2.getSource().getInEdges()) { - DataFlowEdge dIn = (DataFlowEdge) resToCh2; - if (((PushPullAttribute) dIn.getAttribute()).getOptions().get(0) == PushPullValue.PUSH) { - isContainedPush = true; - inputResourceToStateAccessor.put(((ResourceNode) dIn.getSource()).getOutSideResource(), JavaCodeGenerator.pushAccessor); - } else { - inputResourceToStateAccessor.put(((ResourceNode) dIn.getSource()).getOutSideResource(), JavaCodeGenerator.pullAccessor); + if (dstComponent == null) { + String dstParentResourceName = JavaCodeGenerator.getComponentName(dst.getResourceHierarchy().getParent()); + dstComponent = componentMap.get(dstParentResourceName); + } + MethodDeclaration getter = null; + if (JavaCodeGenerator.generatesComponent(dst.getResourceHierarchy())) { + getter = getMethod(dstComponent, "getValue"); + } else { + getter = getGetterMethod(dstComponent, dstResourceName); + } + if (getter.getBody() == null || getter.getBody().getStatements().size() == 0) { + boolean isContainedPush = false; + HashMap inputResourceToStateAccessor = new HashMap<>(); + for (Edge chToRes2: dst.getInEdges()) { + DataTransferChannel ch2 = ((ChannelNode) chToRes2.getSource()).getChannel(); + for (Edge resToCh2: chToRes2.getSource().getInEdges()) { + DataFlowEdge dIn = (DataFlowEdge) resToCh2; + ChannelMember in = null; + for (ChannelMember cm: ch2.getInputChannelMembers()) { + if (cm.getResource().equals(((ResourceNode) dIn.getSource()).getOutSideResource())) { + in = cm; + break; } } - } - // for reference channel members - for (ChannelMember c: ((ChannelNode) resToCh.getDestination()).getChannel().getReferenceChannelMembers()) { - inputResourceToStateAccessor.put(c.getResource(), JavaCodeGenerator.pullAccessor); // by pull data transfer - } - String[] sideEffects = new String[] {""}; - // generate a return statement. - if (!isContainedPush) { - // All incoming edges are in PULL style. - String curState = ((ChannelNode) resToCh.getDestination()).getChannel().deriveUpdateExpressionOf(out, JavaCodeGenerator.pullAccessor).toImplementation(sideEffects); - getter.addStatement(sideEffects[0] + "return " + curState + ";"); - } else { - // At least one incoming edge is in PUSH style. - String curState = ((ChannelNode) resToCh.getDestination()).getChannel().deriveUpdateExpressionOf(out, JavaCodeGenerator.pullAccessor, inputResourceToStateAccessor).toImplementation(sideEffects); - getter.addStatement(sideEffects[0] + "return " + curState + ";"); + if (((PushPullAttribute) dIn.getAttribute()).getOptions().get(0) == PushPullValue.PUSH) { + isContainedPush = true; + inputResourceToStateAccessor.put(in, JavaCodeGenerator.pushAccessor); + } else { + inputResourceToStateAccessor.put(in, JavaCodeGenerator.pullAccessor); + } } } + // for reference channel members + for (ChannelMember c: ch.getReferenceChannelMembers()) { + inputResourceToStateAccessor.put(c, JavaCodeGenerator.pullAccessor); // by pull data transfer + } + String[] sideEffects = new String[] {""}; + // generate a return statement. + if (!isContainedPush) { + // All incoming edges are in PULL style. + String curState = ch.deriveUpdateExpressionOf(out, JavaCodeGenerator.pullAccessor).toImplementation(sideEffects); + getter.addStatement(sideEffects[0] + "return " + curState + ";"); + } else { + // At least one incoming edge is in PUSH style. + String curState = ch.deriveUpdateExpressionOf(out, JavaCodeGenerator.pullAccessor, inputResourceToStateAccessor).toImplementation(sideEffects); + getter.addStatement(sideEffects[0] + "return " + curState + ";"); + } } - } + } } } } } } // for source nodes - TypeDeclaration mainType = typeMap.get(JavaCodeGenerator.mainTypeName); + TypeDeclaration mainComponent = componentMap.get(JavaCodeGenerator.mainTypeName); for (ResourceHierarchy resource: model.getResourceHierarchies()) { // ResourceNode resource = (ResourceNode) n; String resourceName = JavaCodeGenerator.getComponentName(resource); - TypeDeclaration type = typeMap.get(resourceName); - if (type != null) { + TypeDeclaration component = componentMap.get(resourceName); + if (component != null) { // state getter method Type resourceType = JavaCodeGenerator.getImplStateType(resource); - MethodDeclaration stateGetter = getGetterMethod(type, resourceType); + MethodDeclaration stateGetter = getMethod(component, "getValue"); if (stateGetter != null && (stateGetter.getBody() == null || stateGetter.getBody().getStatements().size() == 0)) { if (model.isPrimitiveType(resourceType)) { // primitive type @@ -276,7 +330,7 @@ if (resource.getChildren().size() > 0) { for (ResourceHierarchy child: resource.getChildren()) { String methodName = "get" + JavaCodeGenerator.getComponentName(child); - MethodDeclaration childGetter = getMethod(type, methodName); + MethodDeclaration childGetter = getMethod(component, methodName); if (childGetter != null && (childGetter.getBody() == null || childGetter.getBody().getStatements().size() == 0)) { if (DataConstraintModel.typeList.isAncestorOf(resource.getResourceStateType())) { Term selector = new Term(DataConstraintModel.get); @@ -314,12 +368,12 @@ MethodDeclaration input = null; if (JavaCodeGenerator.generatesComponent(resource)) { // A component is generated for this resource. - input = getInputMethod(type, out); + input = getInputMethod(component, out); } else { // No component is generated for this resource. ResourceHierarchy parent = resource.getParent(); if (parent != null) { - TypeDeclaration parentType = typeMap.get(JavaCodeGenerator.getComponentName(parent)); + TypeDeclaration parentType = componentMap.get(JavaCodeGenerator.getComponentName(parent)); input = getInputMethod(parentType, out); } } @@ -368,10 +422,10 @@ } // In the main type - if (mainType != null) { - MethodDeclaration inputAccessor = getMethod(mainType, input.getName()); + if (mainComponent != null) { + MethodDeclaration inputAccessor = getMethod(mainComponent, input.getName()); if (inputAccessor != null) { - Expression resExp = JavaCodeGenerator.pullAccessor.getCurrentStateAccessorFor(out.getResource(), null); + Expression resExp = JavaCodeGenerator.pullAccessor.getDirectStateAccessorFor(out.getResource(), null); String args = ""; String delimiter = ""; if (resExp instanceof Term) { @@ -404,16 +458,16 @@ return codes; } - private static MethodDeclaration getUpdateMethod(TypeDeclaration type, TypeDeclaration from) { - for (MethodDeclaration m: type.getMethods()) { - if (m.getName().equals("update" + from.getTypeName())) return m; + private static MethodDeclaration getUpdateMethod(TypeDeclaration component, String fromResName) { + for (MethodDeclaration m: component.getMethods()) { + if (m.getName().equals("update" + fromResName)) return m; } return null; } - private static List getUpdateMethods(TypeDeclaration type) { + private static List getUpdateMethods(TypeDeclaration component) { List updates = new ArrayList<>(); - for (MethodDeclaration m: type.getMethods()) { + for (MethodDeclaration m: component.getMethods()) { if (m.getName().startsWith("update")) { updates.add(m); } @@ -421,11 +475,9 @@ return updates; } - private static MethodDeclaration getGetterMethod(TypeDeclaration type, Type returnType) { - for (MethodDeclaration m: type.getMethods()) { - if (m.getName().startsWith("get")) { - if (m.getReturnType().getInterfaceTypeName().equals(returnType.getInterfaceTypeName())) return m; - } + private static MethodDeclaration getGetterMethod(TypeDeclaration component, String resourceName) { + for (MethodDeclaration m: component.getMethods()) { + if (m.getName().startsWith("get" + resourceName)) return m; } return null; } @@ -451,14 +503,14 @@ return ioChannelsAndMembers; } - private static List getInputMethods(TypeDeclaration type, ResourceNode resource, DataTransferModel model) { + private static List getInputMethods(TypeDeclaration component, ResourceNode resource, DataTransferModel model) { List inputs = new ArrayList<>(); for (Channel c: model.getIOChannels()) { DataTransferChannel channel = (DataTransferChannel) c; // I/O channel for (ChannelMember out: channel.getOutputChannelMembers()) { if (resource.getInSideResources().contains(out.getResource())) { - MethodDeclaration input = getInputMethod(type, out); + MethodDeclaration input = getInputMethod(component, out); inputs.add(input); } } @@ -466,20 +518,20 @@ return inputs; } - private static MethodDeclaration getInputMethod(TypeDeclaration type, ChannelMember out) { + private static MethodDeclaration getInputMethod(TypeDeclaration component, ChannelMember out) { MethodDeclaration input = null; if (out.getStateTransition().getMessageExpression() instanceof Term) { Term message = (Term) out.getStateTransition().getMessageExpression(); - input = getMethod(type, message.getSymbol().getImplName()); + input = getMethod(component, message.getSymbol().getImplName()); } else if (out.getStateTransition().getMessageExpression() instanceof Variable) { Variable message = (Variable) out.getStateTransition().getMessageExpression(); - input = getMethod(type, message.getName()); + input = getMethod(component, message.getName()); } return input; } - private static MethodDeclaration getMethod(TypeDeclaration type, String methodName) { - for (MethodDeclaration m: type.getMethods()) { + private static MethodDeclaration getMethod(TypeDeclaration component, String methodName) { + for (MethodDeclaration m: component.getMethods()) { if (m.getName().equals(methodName)) return m; } return null; diff --git a/AlgebraicDataflowArchitectureModel/src/generators/JerseyCodeGenerator.java b/AlgebraicDataflowArchitectureModel/src/generators/JerseyCodeGenerator.java index 0062119..fd97870 100644 --- a/AlgebraicDataflowArchitectureModel/src/generators/JerseyCodeGenerator.java +++ b/AlgebraicDataflowArchitectureModel/src/generators/JerseyCodeGenerator.java @@ -129,7 +129,7 @@ ArrayList codes = new ArrayList<>(); // ArrayList resources = StoreResourceCheck(graph); Collection resources = graph.getResourceNodes(); - Map resourceTypes = new HashMap<>(); + Map resourceComponents = new HashMap<>(); List> getters = new ArrayList<>(); List> inputs = new ArrayList<>(); List> fields = new ArrayList<>(); @@ -139,22 +139,22 @@ // For each resource node. for (Node n : resources) { ResourceNode rn = (ResourceNode) n; - TypeDeclaration type = null; + TypeDeclaration component = null; if (generatesComponent(rn.getResourceHierarchy())) { String resourceName = getComponentName(rn.getResourceHierarchy()); - type = resourceTypes.get(rn.getResourceHierarchy()); - if (type == null) { + component = resourceComponents.get(rn.getResourceHierarchy()); + if (component == null) { // Add compilation unit for each resource. - type = new TypeDeclaration(resourceName); + component = new TypeDeclaration(resourceName); if (rn.getResourceHierarchy().getParent() == null) { // For a root node. - type.addAnnotation(new Annotation("Component")); - type.addAnnotation(new Annotation("Path", "\"/" + rn.getResourceName() + "\"")); + component.addAnnotation(new Annotation("Component")); + component.addAnnotation(new Annotation("Path", "\"/" + rn.getResourceName() + "\"")); } - resourceTypes.put(rn.getResourceHierarchy(), type); + resourceComponents.put(rn.getResourceHierarchy(), component); - CompilationUnit cu = new CompilationUnit(type); + CompilationUnit cu = new CompilationUnit(component); cu.addImport(new ImportDeclaration("java.util.*")); if (rn.getResourceHierarchy().getParent() == null) { // For a root node. @@ -174,16 +174,10 @@ DataTransferChannel ch = ((ChannelNode) re.getDestination()).getChannel(); // Check if the input resource is outside of the channel scope. boolean outsideInputResource = false; - if (ch.getAllSelectors().size() > 0) { - Set params = new HashSet<>(); - for (Selector s: ch.getAllSelectors()) { - params.add(s.getExpression()); - } - for (ChannelMember cm: ch.getInputChannelMembers()) { - if (cm.getResource().getResourceHierarchy().equals(rn.getResourceHierarchy()) && !params.containsAll(cm.getResource().getPathParams())) { - outsideInputResource = true; // Regarded as pull transfer. - break; - } + for (ChannelMember cm: ch.getInputChannelMembers()) { + if (cm.getResource().getResourceHierarchy().equals(rn.getResourceHierarchy()) && cm.isOutside()) { + outsideInputResource = true; // Regarded as pull transfer. + break; } } if (!bDeclareClientField && ((PushPullAttribute) re.getAttribute()).getOptions().get(0) == PushPullValue.PUSH && !outsideInputResource) { @@ -199,13 +193,13 @@ // Inter-service if (bDeclareClientField) { // Declare a client field to connect to the destination resource of push transfer. - type.addField(new FieldDeclaration(typeClient, "client", "ClientBuilder.newClient()")); + component.addField(new FieldDeclaration(typeClient, "client", "ClientBuilder.newClient()")); bDeclareClientField = true; } } else { // Inner-service // Declare a field to directly refer to the destination resource of push transfer. - type.addField(new FieldDeclaration(new Type(dstResName, dstResName), toVariableName(dstResName))); + component.addField(new FieldDeclaration(new Type(dstResName, dstResName), toVariableName(dstResName))); } } } @@ -217,23 +211,17 @@ DataTransferChannel ch = ((ChannelNode) re.getDestination()).getChannel(); // Check if the input and output resources are outside of the channel scope. boolean outsideInputResource = false; + for (ChannelMember cm: ch.getInputChannelMembers()) { + if (cm.getResource().getResourceHierarchy().equals(srcRes.getResourceHierarchy()) && cm.isOutside()) { + outsideInputResource = true; // Regarded as pull transfer. + break; + } + } boolean outsideOutputResource = false; - if (ch.getAllSelectors().size() > 0) { - Set params = new HashSet<>(); - for (Selector s: ch.getAllSelectors()) { - params.add(s.getExpression()); - } - for (ChannelMember cm: ch.getInputChannelMembers()) { - if (cm.getResource().getResourceHierarchy().equals(srcRes.getResourceHierarchy()) && !params.containsAll(cm.getResource().getPathParams())) { - outsideInputResource = true; // Regarded as pull transfer. - break; - } - } - for (ChannelMember cm: ch.getOutputChannelMembers()) { - if (cm.getResource().getResourceHierarchy().equals(rn.getOutSideResource().getResourceHierarchy()) && !params.containsAll(cm.getResource().getPathParams())) { - outsideOutputResource = true; // Regarded as push transfer. - break; - } + for (ChannelMember cm: ch.getOutputChannelMembers()) { + if (cm.getResource().getResourceHierarchy().equals(rn.getOutSideResource().getResourceHierarchy()) && cm.isOutside()) { + outsideOutputResource = true; // Regarded as push transfer. + break; } } String srcResName = null; @@ -247,13 +235,13 @@ // Inter-service if (!bDeclareClientField) { // Declare a client field to connect to the source resource of pull transfer. - type.addField(new FieldDeclaration(typeClient, "client", "ClientBuilder.newClient()")); + component.addField(new FieldDeclaration(typeClient, "client", "ClientBuilder.newClient()")); bDeclareClientField = true; } } else { // Inner-service // Declare a field to directly refer to the source resource of pull transfer. - type.addField(new FieldDeclaration(new Type(srcResName, srcResName), toVariableName(srcResName))); + component.addField(new FieldDeclaration(new Type(srcResName, srcResName), toVariableName(srcResName))); } } else { // Declare an update method in the type of the destination resource. @@ -285,9 +273,9 @@ 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))); + component.addField(new FieldDeclaration(cashRes.getResourceStateType(), srcName, getInitializer(cashRes))); } - type.addMethod(update); + component.addMethod(update); } } } @@ -317,12 +305,12 @@ Set children = rn.getResourceHierarchy().getChildren(); if (children == null || children.size() == 0) { // leaf resource. - type.addField(new FieldDeclaration(getImplStateType(res.getResourceHierarchy()), "value", getInitializer(res))); + component.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))); + component.addField(new FieldDeclaration(getImplStateType(res.getResourceHierarchy()), "value", getInitializer(res))); } else { // class for (ResourceHierarchy c: children) { @@ -332,7 +320,7 @@ // The child has a component. childType = new Type(childTypeName, childTypeName); String fieldName = toVariableName(childTypeName); - type.addField(new FieldDeclaration(childType, fieldName, getInitializer(res))); + component.addField(new FieldDeclaration(childType, fieldName, getInitializer(res))); } } } @@ -363,13 +351,13 @@ } else { childGetter = new MethodDeclaration("get" + childCompName, false, childType, pathParams); } - type.addMethod(childGetter); + component.addMethod(childGetter); } } } // Declare the state field and reference fields in the parent component. - if (type == null) { + if (component == null) { // Declare reference fields for push/pull data transfer. boolean bDeclareClientField = false; boolean noPullTransfer = true; @@ -379,16 +367,10 @@ for (Edge chToRes: re.getDestination().getOutEdges()) { ResourcePath dstRes = ((ResourceNode) chToRes.getDestination()).getOutSideResource(); boolean outsideOutputResource = false; - if (ch.getAllSelectors().size() > 0) { - Set params = new HashSet<>(); - for (Selector s: ch.getAllSelectors()) { - params.add(s.getExpression()); - } - for (ChannelMember cm: ch.getOutputChannelMembers()) { - if (cm.getResource().getResourceHierarchy().equals(dstRes.getResourceHierarchy()) && !params.containsAll(cm.getResource().getPathParams())) { - outsideOutputResource = true; // Regarded as push transfer. - break; - } + for (ChannelMember cm: ch.getOutputChannelMembers()) { + if (cm.getResource().getResourceHierarchy().equals(dstRes.getResourceHierarchy()) && cm.isOutside()) { + outsideOutputResource = true; // Regarded as push transfer. + break; } } if (outsideOutputResource) { @@ -422,16 +404,10 @@ ResourcePath srcRes = ((ResourceNode) re.getSource()).getOutSideResource(); DataTransferChannel ch = ((ChannelNode) re.getDestination()).getChannel(); boolean outsideInputResource = false; - if (ch.getAllSelectors().size() > 0) { - Set params = new HashSet<>(); - for (Selector s: ch.getAllSelectors()) { - params.add(s.getExpression()); - } - for (ChannelMember cm: ch.getInputChannelMembers()) { - if (cm.getResource().getResourceHierarchy().equals(srcRes.getResourceHierarchy()) && !params.containsAll(cm.getResource().getPathParams())) { - outsideInputResource = true; // Regarded as pull transfer. - break; - } + for (ChannelMember cm: ch.getInputChannelMembers()) { + if (cm.getResource().getResourceHierarchy().equals(srcRes.getResourceHierarchy()) && cm.isOutside()) { + outsideInputResource = true; // Regarded as pull transfer. + break; } } if (outsideInputResource) { @@ -470,7 +446,7 @@ } // Declare the getter method to obtain the resource state in the component of each resource. - if (type != null) { + if (component != null) { // A component is created for this resource. MethodDeclaration stateGetter = new MethodDeclaration("getValue", getImplStateType(rn.getResourceHierarchy())); if (rn.getResourceHierarchy().getParent() == null) { @@ -478,7 +454,7 @@ stateGetter.addAnnotation(new Annotation("Produces", "MediaType.APPLICATION_JSON")); stateGetter.addAnnotation(new Annotation("GET")); } - type.addMethod(stateGetter); + component.addMethod(stateGetter); } else { // No component is created for this resource. List pathParams = new ArrayList<>(); @@ -525,7 +501,7 @@ getImplStateType(rn.getResourceHierarchy())); } getterAccessor.setBody(new Block()); - Expression getState = JerseyCodeGenerator.pullAccessor.getCurrentStateAccessorFor(rn.getOutSideResource(), rn.getOutSideResource().getRoot()); + Expression getState = JerseyCodeGenerator.pullAccessor.getDirectStateAccessorFor(rn.getOutSideResource(), rn.getOutSideResource().getRoot()); getterAccessor.getBody().addStatement("return " + getState.toImplementation(new String[] {null}) + ";"); getterAccessor.addAnnotation(new Annotation("Produces", "MediaType.APPLICATION_JSON")); @@ -563,9 +539,9 @@ 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) { + if (component != null) { // A component is created for this resource. - type.addMethod(input); + component.addMethod(input); } else { // No component is created for this resource. inputs.add(new AbstractMap.SimpleEntry(rn.getParent().getResourceHierarchy(), input)); @@ -605,9 +581,9 @@ 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) { + if (component != null) { // A component is created for this resource. - type.addMethod(input); + component.addMethod(input); } else { // No component is created for this resource. inputs.add(new AbstractMap.SimpleEntry(rn.getParent().getResourceHierarchy(), input)); @@ -641,34 +617,34 @@ // Add leaf getter methods to the parent components. for (Map.Entry entry: getters) { - resourceTypes.get(entry.getKey()).addMethod(entry.getValue()); + resourceComponents.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()); + resourceComponents.get(entry.getKey()).addMethod(entry.getValue()); } // Add leaf reference fields to the parent components. for (Map.Entry entry: fields) { - resourceTypes.get(entry.getKey()).addField(entry.getValue()); + resourceComponents.get(entry.getKey()).addField(entry.getValue()); } // Add accessors. for (ResourceHierarchy rootRes: model.getResourceHierarchies()) { if (rootRes.getParent() == null) { // root resource - TypeDeclaration rootType = resourceTypes.get(rootRes); + TypeDeclaration rootComponent = resourceComponents.get(rootRes); // Add getter accessors. for (ResourceHierarchy res: getterAccessors.keySet()) { if (rootRes.isAncestorOf(res)) { - rootType.addMethod(getterAccessors.get(res)); + rootComponent.addMethod(getterAccessors.get(res)); } } // Add input accessors. for (ResourceHierarchy res: inputAccessors.keySet()) { if (rootRes.isAncestorOf(res)) { - rootType.addMethod(inputAccessors.get(res)); + rootComponent.addMethod(inputAccessors.get(res)); } } } @@ -726,14 +702,14 @@ if (selector.getExpression() instanceof Variable) { Variable var = (Variable) selector.getExpression(); String paramName = var.getName(); - params.add(paramName); + params.add("{" + paramName + "}"); VariableDeclaration param = new VariableDeclaration(var.getType(), paramName); param.addAnnotation(new Annotation("PathParam", "\"" + paramName + "\"")); pathParams.add(param); } else if (selector.getExpression() instanceof Term) { Term var = (Term) selector.getExpression(); String paramName = "v" + v; - params.add(paramName); + params.add("{" + paramName + "}"); VariableDeclaration param = new VariableDeclaration(var.getType(), paramName); param.addAnnotation(new Annotation("PathParam", "\"" + paramName + "\"")); pathParams.add(param); @@ -751,7 +727,7 @@ if (selector.getExpression() instanceof Variable) { Variable var = (Variable) selector.getExpression(); String paramName = var.getName(); - params.add(paramName); + params.add("{" + paramName + "}"); VariableDeclaration param = new VariableDeclaration(var.getType(), paramName); resInputParams.add(param); param = new VariableDeclaration(var.getType(), paramName); @@ -760,7 +736,7 @@ } else if (selector.getExpression() instanceof Term) { Term var = (Term) selector.getExpression(); String paramName = "v" + v; - params.add(paramName); + params.add("{" + paramName + "}"); VariableDeclaration param = new VariableDeclaration(var.getType(), paramName); resInputParams.add(param); param = new VariableDeclaration(var.getType(), paramName); @@ -774,14 +750,14 @@ if (selector.getExpression() instanceof Variable) { Variable var = (Variable) selector.getExpression(); String paramName = var.getName(); - params.add(paramName); + params.add("{" + paramName + "}"); VariableDeclaration param = new VariableDeclaration(var.getType(), paramName); param.addAnnotation(new Annotation("PathParam", "\"" + paramName + "\"")); rootInputParams.add(param); } else if (selector.getExpression() instanceof Term) { Term var = (Term) selector.getExpression(); String paramName = "v" + v; - params.add(paramName); + params.add("{" + paramName + "}"); VariableDeclaration param = new VariableDeclaration(var.getType(), paramName); param.addAnnotation(new Annotation("PathParam", "\"" + paramName + "\"")); rootInputParams.add(param); @@ -854,41 +830,82 @@ static public IResourceStateAccessor pushAccessor = new IResourceStateAccessor() { @Override - public Expression getCurrentStateAccessorFor(ResourcePath target, ResourcePath from) { - if (target.equals(from)) { + public Expression getCurrentStateAccessorFor(ChannelMember target, ChannelMember from) { + ResourcePath targetRes = target.getResource(); + ResourcePath fromRes = from.getResource(); + if (targetRes.equals(fromRes)) { return new Field("value", - target.getResourceStateType() != null ? target.getResourceStateType() + targetRes.getResourceStateType() != null ? targetRes.getResourceStateType() : DataConstraintModel.typeInt); } return null; } @Override - public Expression getNextStateAccessorFor(ResourcePath target, ResourcePath from) { - return new Parameter(target.getResourceName(), - target.getResourceStateType() != null ? target.getResourceStateType() + public Expression getNextStateAccessorFor(ChannelMember target, ChannelMember from) { + ResourcePath targetRes = target.getResource(); + return new Parameter(targetRes.getResourceName(), + targetRes.getResourceStateType() != null ? targetRes.getResourceStateType() : DataConstraintModel.typeInt); } + + @Override + public Expression getDirectStateAccessorFor(ResourcePath targetRes, ResourcePath fromRes) { + if (fromRes != null && targetRes.equals(fromRes)) { + return new Field("value", + targetRes.getResourceStateType() != null ? targetRes.getResourceStateType() + : DataConstraintModel.typeInt); + } + return null; + } }; static public IResourceStateAccessor pullAccessor = new IResourceStateAccessor() { @Override - public Expression getCurrentStateAccessorFor(ResourcePath target, ResourcePath from) { - if (from != null && !from.getResourceHierarchy().isAncestorOf(target.getResourceHierarchy())) { - if (target.equals(from)) { + public Expression getCurrentStateAccessorFor(ChannelMember target, ChannelMember from) { + ResourcePath targetRes = target.getResource(); + if (from != null && !target.isOutside()) { + ResourcePath fromRes = from.getResource(); + if (targetRes.getCommonPrefix(fromRes) != null) { + return getDirectStateAccessorFor(targetRes, fromRes); + } + } + return new Parameter(targetRes.getResourceName(), + targetRes.getResourceStateType() != null ? targetRes.getResourceStateType() + : DataConstraintModel.typeInt); + } + + @Override + public Expression getNextStateAccessorFor(ChannelMember target, ChannelMember from) { + ResourcePath targetRes = target.getResource(); + if (from != null && !target.isOutside()) { + ResourcePath fromRes = from.getResource(); + if (targetRes.getCommonPrefix(fromRes) != null) { + return getDirectStateAccessorFor(targetRes, fromRes); + } + } + return new Parameter(targetRes.getResourceName(), + targetRes.getResourceStateType() != null ? targetRes.getResourceStateType() + : DataConstraintModel.typeInt); + } + + @Override + public Expression getDirectStateAccessorFor(ResourcePath targetRes, ResourcePath fromRes) { + if (fromRes != null && !fromRes.getResourceHierarchy().isAncestorOf(targetRes.getResourceHierarchy())) { + if (targetRes.equals(fromRes)) { return new Field("value", - target.getResourceStateType() != null ? target.getResourceStateType() + targetRes.getResourceStateType() != null ? targetRes.getResourceStateType() : DataConstraintModel.typeInt); } // for reference channel member - return new Parameter(target.getResourceName(), - target.getResourceStateType() != null ? target.getResourceStateType() + return new Parameter(targetRes.getResourceName(), + targetRes.getResourceStateType() != null ? targetRes.getResourceStateType() : DataConstraintModel.typeInt); } else { // access from an ancestor or outside of the hierarchy Stack pathStack = new Stack<>(); - ResourcePath curPath = target; + ResourcePath curPath = targetRes; do { - if (from != null && curPath.equals(from)) break; + if (fromRes != null && curPath.equals(fromRes)) break; pathStack.push(curPath); curPath = curPath.getParent(); } while (curPath != null); @@ -898,7 +915,7 @@ while (!pathStack.empty()) { curPath = pathStack.pop(); String typeName = getComponentName(curPath.getResourceHierarchy()); - if (getter == null && from == null) { + if (getter == null && fromRes == null) { // root resource String fieldName = toVariableName(typeName); getter = new Field(fieldName, new Type(typeName, typeName)); @@ -923,7 +940,7 @@ } } - if (generatesComponent(target.getResourceHierarchy())) { + if (generatesComponent(targetRes.getResourceHierarchy())) { Term newGetter = new Term(new Symbol("getValue", 1, Symbol.Type.METHOD)); newGetter.addChild(getter); getter = newGetter; @@ -931,12 +948,5 @@ return getter; } } - - @Override - public Expression getNextStateAccessorFor(ResourcePath target, ResourcePath from) { - return new Parameter(target.getResourceName(), - target.getResourceStateType() != null ? target.getResourceStateType() - : DataConstraintModel.typeInt); - } }; } diff --git a/AlgebraicDataflowArchitectureModel/src/generators/JerseyMethodBodyGenerator.java b/AlgebraicDataflowArchitectureModel/src/generators/JerseyMethodBodyGenerator.java index b239cc9..4920156 100644 --- a/AlgebraicDataflowArchitectureModel/src/generators/JerseyMethodBodyGenerator.java +++ b/AlgebraicDataflowArchitectureModel/src/generators/JerseyMethodBodyGenerator.java @@ -49,10 +49,10 @@ public static ArrayList doGenerate(DataFlowGraph graph, DataTransferModel model, ArrayList codes) { // Create a map from type names (lower case) to their types. - Map typeMap = new HashMap<>(); + Map componentMap = new HashMap<>(); for (CompilationUnit code: codes) { - for (TypeDeclaration type: code.types()) { - typeMap.put(type.getTypeName(), type); + for (TypeDeclaration component: code.types()) { + componentMap.put(component.getTypeName(), component); } } @@ -69,31 +69,56 @@ ResourceNode dst = (ResourceNode) chToRes.getDestination(); String srcResourceName = JerseyCodeGenerator.getComponentName(src.getResourceHierarchy()); String dstResourceName = JerseyCodeGenerator.getComponentName(dst.getResourceHierarchy()); - TypeDeclaration srcType = typeMap.get(srcResourceName); - TypeDeclaration dstType = typeMap.get(dstResourceName); - for (ChannelMember out: ((ChannelNode) resToCh.getDestination()).getChannel().getOutputChannelMembers()) { + TypeDeclaration srcComponent = componentMap.get(srcResourceName); + TypeDeclaration dstComponent = componentMap.get(dstResourceName); + DataTransferChannel ch = ((ChannelNode) resToCh.getDestination()).getChannel(); + for (ChannelMember out: ch.getOutputChannelMembers()) { if (dst.getInSideResources().contains(out.getResource())) { - if (pushPull.getOptions().get(0) == PushPullValue.PUSH && srcType != null) { + // Check if the input resource is outside of the channel scope. + boolean outsideInputResource = false; + for (ChannelMember cm: ch.getInputChannelMembers()) { + if (cm.getResource().getResourceHierarchy().equals(src.getResourceHierarchy()) && 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(dst.getResourceHierarchy()) && cm.isOutside()) { + outsideOutputResource = true; // Regarded as push transfer. + break; + } + } + if (pushPull.getOptions().get(0) == PushPullValue.PUSH && !outsideInputResource) { // for push data transfer - MethodDeclaration update = getUpdateMethod(dstType, srcType); + MethodDeclaration update = getUpdateMethod(dstComponent, srcComponent); if (((StoreAttribute) dst.getAttribute()).isStored()) { // update stored state of dst side resource (when every incoming edge is in push style) Expression updateExp = null; - if (((ChannelNode) resToCh.getDestination()).getChannel().getReferenceChannelMembers().size() == 0) { - updateExp = ((ChannelNode) resToCh.getDestination()).getChannel().deriveUpdateExpressionOf(out, JerseyCodeGenerator.pushAccessor); + if (ch.getReferenceChannelMembers().size() == 0) { + updateExp = ch.deriveUpdateExpressionOf(out, JerseyCodeGenerator.pushAccessor); } else { // if there exists one or more reference channel member. - HashMap inputResourceToStateAccessor = new HashMap<>(); + HashMap inputResourceToStateAccessor = new HashMap<>(); for (Edge chToRes2: dst.getInEdges()) { + DataTransferChannel ch2 = ((ChannelNode) chToRes2.getSource()).getChannel(); for (Edge resToCh2: chToRes2.getSource().getInEdges()) { DataFlowEdge dIn = (DataFlowEdge) resToCh2; - inputResourceToStateAccessor.put(((ResourceNode) dIn.getSource()).getOutSideResource(), JerseyCodeGenerator.pushAccessor); + ChannelMember in = null; + for (ChannelMember cm: ch2.getInputChannelMembers()) { + if (cm.getResource().equals(((ResourceNode) dIn.getSource()).getOutSideResource())) { + in = cm; + break; + } + } + inputResourceToStateAccessor.put(in, JerseyCodeGenerator.pushAccessor); } } - for (ChannelMember c: ((ChannelNode) resToCh.getDestination()).getChannel().getReferenceChannelMembers()) { - inputResourceToStateAccessor.put(c.getResource(), JerseyCodeGenerator.pullAccessor); + for (ChannelMember c: ch.getReferenceChannelMembers()) { + inputResourceToStateAccessor.put(c, JerseyCodeGenerator.pullAccessor); } - updateExp = ((ChannelNode) resToCh.getDestination()).getChannel().deriveUpdateExpressionOf(out, JerseyCodeGenerator.pushAccessor, inputResourceToStateAccessor); + updateExp = ch.deriveUpdateExpressionOf(out, JerseyCodeGenerator.pushAccessor, inputResourceToStateAccessor); } String[] sideEffects = new String[] {""}; String curState = updateExp.toImplementation(sideEffects); @@ -110,7 +135,7 @@ } if (resToCh.getDestination().getIndegree() > 1) { // update a cash of src side resource (when incoming edges are multiple) - String cashStatement = "this." + srcResourceName + " = " + srcResourceName + ";"; + String cashStatement = "this." + JerseyCodeGenerator.toVariableName(srcResourceName) + " = " + JerseyCodeGenerator.toVariableName(srcResourceName) + ";"; if (update.getBody() == null || !update.getBody().getStatements().contains(cashStatement)) { update.addFirstStatement(cashStatement); } @@ -181,7 +206,16 @@ } if (((StoreAttribute) dst.getAttribute()).isStored()) { // returns the state stored in a field. - MethodDeclaration getter = getGetterMethod(dstType, dst.getResourceStateType()); + if (dstComponent == null) { + String dstParentResourceName = JavaCodeGenerator.getComponentName(dst.getResourceHierarchy().getParent()); + dstComponent = componentMap.get(dstParentResourceName); + } + MethodDeclaration getter = null; + if (JerseyCodeGenerator.generatesComponent(dst.getResourceHierarchy())) { + getter = getMethod(dstComponent, "getValue"); + } else { + getter = getGetterMethod(dstComponent, dstResourceName); + } if (getter.getBody() == null || getter.getBody().getStatements().size() == 0) { if (dst.getResourceHierarchy().getNumParameters() == 0) { getter.addStatement("return value;"); @@ -207,12 +241,12 @@ } else { httpMethod = "post"; } - for (MethodDeclaration srcUpdate: getUpdateMethods(srcType)) { + for (MethodDeclaration srcUpdate: getUpdateMethods(srcComponent)) { if (srcUpdate != null) { List>> params = new ArrayList<>(); Set referredSet = referredResources.get(srcUpdate); - if (((ChannelNode) resToCh.getDestination()).getChannel().getReferenceChannelMembers().size() > 0) { - for (ChannelMember rc: ((ChannelNode) resToCh.getDestination()).getChannel().getReferenceChannelMembers()) { + if (ch.getReferenceChannelMembers().size() > 0) { + for (ChannelMember rc: ch.getReferenceChannelMembers()) { // For each reference channel member, get the current state of the reference side resource by pull data transfer. ResourcePath ref = rc.getResource(); if (referredSet == null) { @@ -224,7 +258,7 @@ Type refResourceType = ref.getResourceStateType(); if (!referredSet.contains(ref)) { referredSet.add(ref); - generatePullDataTransfer(srcUpdate, refResourceName, refResourceType); + generatePullDataTransfer(srcUpdate, refResourceName, refResourceName, refResourceType); } // Value of a reference side resource. params.add(new AbstractMap.SimpleEntry<>(refResourceType, new AbstractMap.SimpleEntry<>(refResourceName, refResourceName))); @@ -239,23 +273,23 @@ // The first call to an update method in this method // Value of the source side (input side) resource. params.add(0, new AbstractMap.SimpleEntry<>(src.getResourceStateType(), new AbstractMap.SimpleEntry<>(srcResourceName, "this.value"))); - srcUpdate.addStatement(getHttpMethodParamsStatement(srcType.getTypeName(), params, true)); + srcUpdate.addStatement(getHttpMethodParamsStatement(srcComponent.getTypeName(), params, true)); srcUpdate.addStatement("String result = " + getHttpMethodCallStatement(baseURL, dstResourceName, srcResName, httpMethod)); chainedCalls.add(srcUpdate); } else { // After the second time of call to update methods in this method // Value of the source side (input side) resource. params.add(0, new AbstractMap.SimpleEntry<>(src.getResourceStateType(), new AbstractMap.SimpleEntry<>(srcResourceName, "this.value"))); - srcUpdate.addStatement(getHttpMethodParamsStatement(srcType.getTypeName(), params, false)); + srcUpdate.addStatement(getHttpMethodParamsStatement(srcComponent.getTypeName(), params, false)); srcUpdate.addStatement("result = " + getHttpMethodCallStatement(baseURL, dstResourceName, srcResName, httpMethod)); } srcUpdate.addThrow("JsonProcessingException"); } } - for (MethodDeclaration srcInput: getInputMethods(srcType, src, model)) { + for (MethodDeclaration srcInput: getInputMethods(srcComponent, src, model)) { List>> params = new ArrayList<>(); Set referredSet = referredResources.get(srcInput); - for (ChannelMember rc: ((ChannelNode) resToCh.getDestination()).getChannel().getReferenceChannelMembers()) { + for (ChannelMember rc: ch.getReferenceChannelMembers()) { // For each reference channel member, get the current state of the reference side resource by pull data transfer. ResourcePath ref = rc.getResource(); if (referredSet == null) { @@ -267,7 +301,7 @@ Type refResourceType = ref.getResourceStateType(); if (!referredSet.contains(ref)) { referredSet.add(ref); - generatePullDataTransfer(srcInput, refResourceName, refResourceType); + generatePullDataTransfer(srcInput, refResourceName, refResourceName, refResourceType); } // Value of a reference side resource. params.add(new AbstractMap.SimpleEntry<>(refResourceType, new AbstractMap.SimpleEntry<>(refResourceName, refResourceName))); @@ -281,37 +315,62 @@ // First call to an update method in this method // Value of the source side (input side) resource. params.add(0, new AbstractMap.SimpleEntry<>(src.getResourceStateType(), new AbstractMap.SimpleEntry<>(srcResourceName, "this.value"))); - srcInput.addStatement(getHttpMethodParamsStatement(srcType.getTypeName(), params, true)); + srcInput.addStatement(getHttpMethodParamsStatement(srcComponent.getTypeName(), params, true)); srcInput.addStatement("String result = " + getHttpMethodCallStatement(baseURL, dstResourceName, srcResName, httpMethod)); chainedCalls.add(srcInput); } else { // After the second time of call to update methods in this method // Value of the source side (input side) resource. params.add(0, new AbstractMap.SimpleEntry<>(src.getResourceStateType(), new AbstractMap.SimpleEntry<>(srcResourceName, "this.value"))); - srcInput.addStatement(getHttpMethodParamsStatement(srcType.getTypeName(), params, false)); + srcInput.addStatement(getHttpMethodParamsStatement(srcComponent.getTypeName(), params, false)); srcInput.addStatement("result = " + getHttpMethodCallStatement(baseURL, dstResourceName, srcResName, httpMethod)); } srcInput.addThrow("JsonProcessingException"); } - } else { + } else if ((pushPull.getOptions().get(0) != PushPullValue.PUSH && !outsideOutputResource) || outsideInputResource) { // for pull (or push/pull) data transfer - if (dst.getNumberOfParameters() == 0) { - MethodDeclaration getter = getGetterMethod(dstType, dst.getResourceStateType()); - if (getter.getBody() == null || getter.getBody().getStatements().size() == 0) { - // generate a return statement. - String[] sideEffects = new String[] {""}; - String curState = ((ChannelNode) resToCh.getDestination()).getChannel().deriveUpdateExpressionOf(out, JerseyCodeGenerator.pullAccessor).toImplementation(sideEffects); // no pull data transfer is included. - getter.addStatement(sideEffects[0] + "return " + curState + ";"); - // For each reference channel member, get the current state of the reference side resource by pull data transfer. - for (ChannelMember c: ((ChannelNode) resToCh.getDestination()).getChannel().getReferenceChannelMembers()) { - String refResourceName = c.getResource().getResourceName(); - Type refResourceType = c.getResource().getResourceStateType(); - generatePullDataTransfer(getter, refResourceName, refResourceType); + if (dstComponent == null) { + String dstParentResourceName = JavaCodeGenerator.getComponentName(dst.getResourceHierarchy().getParent()); + dstComponent = componentMap.get(dstParentResourceName); + } + MethodDeclaration getter = null; + if (JerseyCodeGenerator.generatesComponent(dst.getResourceHierarchy())) { + getter = getMethod(dstComponent, "getValue"); + } else { + getter = getGetterMethod(dstComponent, dstResourceName); + } + if (getter.getBody() == null || getter.getBody().getStatements().size() == 0) { + // generate a return statement. + Map resourcePaths = new HashMap<>(); + Expression curExp = ch.deriveUpdateExpressionAndConcreteResourcePathsOf(out, JerseyCodeGenerator.pullAccessor, resourcePaths); // no pull data transfer is included. + String[] sideEffects = new String[] {""}; + String curState = curExp.toImplementation(sideEffects); + getter.addStatement(sideEffects[0] + "return " + curState + ";"); + // For each reference channel member, get the current state of the reference side resource by pull data transfer. + for (ChannelMember c: ((ChannelNode) resToCh.getDestination()).getChannel().getReferenceChannelMembers()) { + String refResourceName = c.getResource().getResourceName(); + Type refResourceType = c.getResource().getResourceStateType(); + generatePullDataTransfer(getter, refResourceName, refResourceName, refResourceType); + } + for (Map.Entry pathEnt: resourcePaths.entrySet()) { + ChannelMember cm = pathEnt.getKey(); + ResourcePath src2 = pathEnt.getValue(); + // get outside src resource state by pull data transfer. + if (cm.isOutside() || src2.getCommonPrefix(dst.getOutSideResource()) == null) { + Type srcResourceType = src2.getResourceStateType(); + List pathParams = new ArrayList<>(); + for (Expression pathExp: src2.getPathParams()) { + pathParams.add("\" + " + pathExp.toImplementation(sideEffects) + " + \""); + } + generatePullDataTransfer(getter, src2.getResourceName(), src2.getResourceHierarchy().toResourcePath(pathParams), srcResourceType); } } - // get src side resource state by pull data transfer. + } + // get src resource state by pull data transfer. + if (src.getNumberOfParameters() == 0 && src.getOutSideResource().getCommonPrefix(dst.getOutSideResource()) == null) { Type srcResourceType = src.getResourceStateType(); - generatePullDataTransfer(getter, srcResourceName, srcResourceType); + List pathParams = new ArrayList<>(); + generatePullDataTransfer(getter, src.getResourceName(), src.getResourceHierarchy().toResourcePath(pathParams), srcResourceType); } } } @@ -322,11 +381,11 @@ // for source nodes for (ResourceHierarchy resource: model.getResourceHierarchies()) { String resourceName = JerseyCodeGenerator.getComponentName(resource); - TypeDeclaration type = typeMap.get(resourceName); - if (type != null) { + TypeDeclaration component = componentMap.get(resourceName); + if (component != null) { // state getter method Type resourceType = JerseyCodeGenerator.getImplStateType(resource); - MethodDeclaration stateGetter = getGetterMethod(type, resourceType); + MethodDeclaration stateGetter = getMethod(component, "getValue"); if (stateGetter.getBody() == null || stateGetter.getBody().getStatements().size() == 0) { if (model.isPrimitiveType(resourceType)) { // primitive type @@ -379,7 +438,7 @@ if (resource.getChildren().size() > 0) { for (ResourceHierarchy child: resource.getChildren()) { String methodName = "get" + JerseyCodeGenerator.getComponentName(child); - MethodDeclaration childGetter = getMethod(type, methodName); + MethodDeclaration childGetter = getMethod(component, methodName); if (childGetter != null && (childGetter.getBody() == null || childGetter.getBody().getStatements().size() == 0)) { if (DataConstraintModel.typeList.isAncestorOf(resource.getResourceStateType())) { Term selector = new Term(DataConstraintModel.get); @@ -417,12 +476,12 @@ MethodDeclaration input = null; if (JavaCodeGenerator.generatesComponent(resource)) { // A component is generated for this resource. - input = getInputMethod(type, out); + input = getInputMethod(component, out); } else { // No component is generated for this resource. ResourceHierarchy parent = resource.getParent(); if (parent != null) { - TypeDeclaration parentType = typeMap.get(JavaCodeGenerator.getComponentName(parent)); + TypeDeclaration parentType = componentMap.get(JavaCodeGenerator.getComponentName(parent)); input = getInputMethod(parentType, out); } } @@ -472,9 +531,9 @@ 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()); + MethodDeclaration inputAccessor = getMethod(componentMap.get(JerseyCodeGenerator.getComponentName(resource.getRoot())), input.getName()); if (inputAccessor != null) { - Expression resExp = JerseyCodeGenerator.pullAccessor.getCurrentStateAccessorFor(out.getResource(), out.getResource().getRoot()); + Expression resExp = JerseyCodeGenerator.pullAccessor.getDirectStateAccessorFor(out.getResource(), out.getResource().getRoot()); String args = ""; String delimiter = ""; if (resExp instanceof Term) { @@ -507,7 +566,7 @@ return codes; } - private static void generatePullDataTransfer(MethodDeclaration methodBody, String fromResourceName, Type fromResourceType) { + private static void generatePullDataTransfer(MethodDeclaration methodBody, String fromResourceName, String fromResourcePath, Type fromResourceType) { String varName = new String(fromResourceName); String respTypeName = fromResourceType.getInterfaceTypeName(); String respImplTypeName = fromResourceType.getImplementationTypeName(); @@ -546,7 +605,7 @@ if (respConverter.length() > 0) { methodBody.addFirstStatement(respConverter); } - methodBody.addFirstStatement(respTypeName + " " + varName + " = " + getHttpMethodCallStatementWithResponse(baseURL, fromResourceName, "get", respImplTypeName)); + methodBody.addFirstStatement(respTypeName + " " + varName + " = " + getHttpMethodCallStatementWithResponse(baseURL, fromResourcePath, "get", respImplTypeName)); } private static String convertFromEntryToMapType(Type type) { @@ -689,25 +748,23 @@ return "client.target(\"" + baseURL + "\").path(\"/" + resourceName + "\").request()." + httpMethod + "(" + responseShortTypeName + ".class);"; } - private static MethodDeclaration getUpdateMethod(TypeDeclaration type, TypeDeclaration from) { - for (MethodDeclaration m: type.getMethods()) { + private static MethodDeclaration getUpdateMethod(TypeDeclaration component, TypeDeclaration from) { + for (MethodDeclaration m: component.getMethods()) { if (m.getName().equals("update" + from.getTypeName())) return m; } return null; } - private static MethodDeclaration getGetterMethod(TypeDeclaration type, Type returnType) { - for (MethodDeclaration m: type.getMethods()) { - if (m.getName().startsWith("get")) { - if (m.getReturnType().getInterfaceTypeName().equals(returnType.getInterfaceTypeName())) return m; - } + private static MethodDeclaration getGetterMethod(TypeDeclaration component, String resourceName) { + for (MethodDeclaration m: component.getMethods()) { + if (m.getName().startsWith("get" + resourceName)) return m; } return null; } - private static List getUpdateMethods(TypeDeclaration type) { + private static List getUpdateMethods(TypeDeclaration component) { List updates = new ArrayList<>(); - for (MethodDeclaration m: type.getMethods()) { + for (MethodDeclaration m: component.getMethods()) { if (m.getName().startsWith("update")) { updates.add(m); } @@ -736,14 +793,14 @@ return ioChannelsAndMembers; } - private static List getInputMethods(TypeDeclaration type, ResourceNode resource, DataTransferModel model) { + private static List getInputMethods(TypeDeclaration component, ResourceNode resource, DataTransferModel model) { List inputs = new ArrayList<>(); for (Channel c: model.getIOChannels()) { DataTransferChannel channel = (DataTransferChannel) c; // I/O channel for (ChannelMember out: channel.getOutputChannelMembers()) { if (resource.getInSideResources().contains(out.getResource())) { - MethodDeclaration input = getInputMethod(type, out); + MethodDeclaration input = getInputMethod(component, out); inputs.add(input); } } @@ -751,20 +808,20 @@ return inputs; } - private static MethodDeclaration getInputMethod(TypeDeclaration type, ChannelMember out) { + private static MethodDeclaration getInputMethod(TypeDeclaration component, ChannelMember out) { MethodDeclaration input = null; if (out.getStateTransition().getMessageExpression() instanceof Term) { Term message = (Term) out.getStateTransition().getMessageExpression(); - input = getMethod(type, message.getSymbol().getImplName()); + input = getMethod(component, message.getSymbol().getImplName()); } else if (out.getStateTransition().getMessageExpression() instanceof Variable) { Variable message = (Variable) out.getStateTransition().getMessageExpression(); - input = getMethod(type, message.getName()); + input = getMethod(component, message.getName()); } return input; } - private static MethodDeclaration getMethod(TypeDeclaration type, String methodName) { - for (MethodDeclaration m: type.getMethods()) { + private static MethodDeclaration getMethod(TypeDeclaration component, String methodName) { + for (MethodDeclaration m: component.getMethods()) { if (m.getName().equals(methodName)) return m; } return null; diff --git a/AlgebraicDataflowArchitectureModel/src/models/algebra/Term.java b/AlgebraicDataflowArchitectureModel/src/models/algebra/Term.java index a0f34eb..3c15d21 100644 --- a/AlgebraicDataflowArchitectureModel/src/models/algebra/Term.java +++ b/AlgebraicDataflowArchitectureModel/src/models/algebra/Term.java @@ -242,7 +242,7 @@ if (getArity() == 2 && symbol.isInfix()) { return "(" + children.get(0) + symbol.toString() + children.get(1) + ")"; } - if (getArity() >= 1 && symbol.isMethod()) { + if ((getArity() >= 1 || getArity() == -1) && symbol.isMethod()) { String exp = children.get(0).toString() + "." + symbol.toString() + "("; String delimiter = ""; for (int i = 1; i < children.size(); i++) { diff --git a/AlgebraicDataflowArchitectureModel/src/models/dataConstraintModel/Channel.java b/AlgebraicDataflowArchitectureModel/src/models/dataConstraintModel/Channel.java index c7b96ae..a778387 100644 --- a/AlgebraicDataflowArchitectureModel/src/models/dataConstraintModel/Channel.java +++ b/AlgebraicDataflowArchitectureModel/src/models/dataConstraintModel/Channel.java @@ -5,6 +5,7 @@ import java.util.List; import java.util.Set; +import models.algebra.Expression; import models.algebra.Variable; public class Channel { @@ -89,18 +90,19 @@ public void setChannelMembers(Set channelMembers) { this.channelMembers = channelMembers; -// for (ChannelMember channelMember: channelMembers) { -// for (Selector selector: channelMember.getSelectors()) { -// addSelector(selector); -// } -// } } public void addChannelMember(ChannelMember channelMember) { channelMembers.add(channelMember); -// for (Selector selector: channelMember.getSelectors()) { -// addSelector(selector); -// } + if (getAllSelectors().size() > 0) { + Set params = new HashSet<>(); + for (Selector s: getAllSelectors()) { + params.add(s.getExpression()); + } + if (!params.containsAll(channelMember.getResource().getPathParams())) { + channelMember.setOutside(true); + } + } } public void removeChannelMember(ResourcePath res) { diff --git a/AlgebraicDataflowArchitectureModel/src/models/dataConstraintModel/ChannelMember.java b/AlgebraicDataflowArchitectureModel/src/models/dataConstraintModel/ChannelMember.java index 6be0bb3..93a3cea 100644 --- a/AlgebraicDataflowArchitectureModel/src/models/dataConstraintModel/ChannelMember.java +++ b/AlgebraicDataflowArchitectureModel/src/models/dataConstraintModel/ChannelMember.java @@ -6,10 +6,12 @@ public class ChannelMember { private ResourcePath resourcePath = null; private StateTransition stateTransition = null; + private boolean isOutside = false; public ChannelMember(ResourcePath resourcePath) { this.resourcePath = resourcePath; stateTransition = new StateTransition(); + isOutside = false; } public ResourcePath getResource() { @@ -20,19 +22,6 @@ this.resourcePath = resourcePath; } -// public List getSelectors() { -// return selectors; -// } -// -// public void setSelectors(List selectors) { -// this.selectors = selectors; -// } -// -// public ChannelMember addSelector(Selector selector) { -// selectors.add(selector); -// return this; -// } - public StateTransition getStateTransition() { return stateTransition; } @@ -41,6 +30,14 @@ this.stateTransition = stateTransition; } + public boolean isOutside() { + return this.isOutside; + } + + public void setOutside(boolean isOutside) { + this.isOutside = isOutside; + } + @Override public String toString() { if (stateTransition.getNextStateExpression() == null) { diff --git a/AlgebraicDataflowArchitectureModel/src/models/dataConstraintModel/ResourceHierarchy.java b/AlgebraicDataflowArchitectureModel/src/models/dataConstraintModel/ResourceHierarchy.java index be87686..7412266 100644 --- a/AlgebraicDataflowArchitectureModel/src/models/dataConstraintModel/ResourceHierarchy.java +++ b/AlgebraicDataflowArchitectureModel/src/models/dataConstraintModel/ResourceHierarchy.java @@ -236,7 +236,7 @@ } else { String lastParam = pathParams.get(pathParams.size() - 1); pathParams = pathParams.subList(0, pathParams.size() - 1); - return parent.toResourcePath(pathParams) + "/{" + lastParam +"}"; + return parent.toResourcePath(pathParams) + "/" + lastParam; } } } \ No newline at end of file diff --git a/AlgebraicDataflowArchitectureModel/src/models/dataConstraintModel/ResourcePath.java b/AlgebraicDataflowArchitectureModel/src/models/dataConstraintModel/ResourcePath.java index d7c2195..f4d0e19 100644 --- a/AlgebraicDataflowArchitectureModel/src/models/dataConstraintModel/ResourcePath.java +++ b/AlgebraicDataflowArchitectureModel/src/models/dataConstraintModel/ResourcePath.java @@ -36,6 +36,13 @@ this.pathParams = new ArrayList<>(parent.getPathParams()); this.pathParams.add(exp); } + + public ResourcePath(ResourcePath another) { + super(another.name); + this.parent = another.parent; + this.resourceHierarchy = another.resourceHierarchy; + this.pathParams = new ArrayList<>(another.getPathParams()); + } public ResourceHierarchy getResourceHierarchy() { return resourceHierarchy; @@ -111,13 +118,4 @@ public String toString() { return resourceHierarchy.toString(pathParams); } -// -// public boolean equals(Object another) { -// if (!(another instanceof ResourcePath)) return false; -// return toString().equals(((ResourcePath) another).toString()); -// } -// -// public int hashCode() { -// return toString().hashCode(); -// } } diff --git a/AlgebraicDataflowArchitectureModel/src/models/dataFlowModel/DataTransferChannel.java b/AlgebraicDataflowArchitectureModel/src/models/dataFlowModel/DataTransferChannel.java index ad09c92..892a2f6 100644 --- a/AlgebraicDataflowArchitectureModel/src/models/dataFlowModel/DataTransferChannel.java +++ b/AlgebraicDataflowArchitectureModel/src/models/dataFlowModel/DataTransferChannel.java @@ -3,8 +3,11 @@ import java.util.HashMap; import java.util.HashSet; import java.util.List; +import java.util.Map; import java.util.Set; +import java.util.Map.Entry; +import models.algebra.Constant; import models.algebra.Expression; import models.algebra.InvalidMessage; import models.algebra.Parameter; @@ -50,7 +53,7 @@ this.inputChannelMembers = inputChannelMembers; } - public void addInputChannelMember(ChannelMember inputChannelMember) { + private void addInputChannelMember(ChannelMember inputChannelMember) { inputChannelMembers.add(inputChannelMember); } @@ -62,7 +65,7 @@ this.outputChannelMembers = outputChannelMembers; } - public void addOutputChannelMember(ChannelMember outputChannelMember) { + private void addOutputChannelMember(ChannelMember outputChannelMember) { outputChannelMembers.add(outputChannelMember); } @@ -74,7 +77,7 @@ this.referenceChannelMembers = referenceChannelMembers; } - public void addReferenceChannelMember(ChannelMember referenceChannelMember) { + private void addReferenceChannelMember(ChannelMember referenceChannelMember) { referenceChannelMembers.add(referenceChannelMember); } @@ -157,8 +160,8 @@ HashMap nextStateParams = new HashMap<>(); @Override - public Expression getCurrentStateAccessorFor(ResourcePath target, ResourcePath from) { - String resource = target.getResourceName(); + public Expression getCurrentStateAccessorFor(ChannelMember target, ChannelMember from) { + String resource = target.getResource().getResourceName(); Parameter curStateParam = curStateParams.get(resource); if (curStateParam == null) { curStateParam = new Parameter("cur" + resource); @@ -168,24 +171,35 @@ } @Override - public Expression getNextStateAccessorFor(ResourcePath target, ResourcePath from) { - String resource = target.getResourceName(); + public Expression getNextStateAccessorFor(ChannelMember target, ChannelMember from) { + String resource = target.getResource().getResourceName(); Parameter nextStateParam = nextStateParams.get(resource); if (nextStateParam == null) { - nextStateParam = new Parameter("next" + resource); + nextStateParam = new Parameter("next" + target); nextStateParams.put(resource, nextStateParam); } return nextStateParam; } + + @Override + public Expression getDirectStateAccessorFor(ResourcePath target, ResourcePath from) { + String resource = target.getResourceName(); + Parameter curStateParam = curStateParams.get(resource); + if (curStateParam == null) { + curStateParam = new Parameter("cur" + resource); + curStateParams.put(resource, curStateParam); + } + return curStateParam; + } }; return deriveUpdateExpressionOf(targetMember, defaultStateAccessor); } /** - * Derive the update expression of the state of the target channel member with a given resource state accessor. + * Derive the state update calculation of the target channel member with a given resource push/pull state accessor. * @param targetMember a channel member whose state is to be updated - * @param stateAccessor a resource state accessor - * @return the derived update expression + * @param stateAccessor a push/pull resource state accessor + * @return the derived update calculation * @throws ParameterizedIdentifierIsFutureWork * @throws ResolvingMultipleDefinitionIsFutureWork * @throws InvalidMessage @@ -196,23 +210,94 @@ throws ParameterizedIdentifierIsFutureWork, ResolvingMultipleDefinitionIsFutureWork, InvalidMessage, UnificationFailed, ValueUndefined { return deriveUpdateExpressionOf(targetMember, stateAccessor, null); } + + /** + * Derive the state update calculation of the target channel member and the filled outside resource paths with a given resource push/pull state accessor. + * @param targetMember a channel member whose state is to be updated + * @param stateAccessor a push/pull resource state accessor + * @param resourcePaths a container to be returned with filled outside resource paths + * @return the derived update calculation + * @throws ParameterizedIdentifierIsFutureWork + * @throws ResolvingMultipleDefinitionIsFutureWork + * @throws InvalidMessage + * @throws UnificationFailed + * @throws ValueUndefined + */ + public Expression deriveUpdateExpressionAndConcreteResourcePathsOf(ChannelMember targetMember, IResourceStateAccessor stateAccessor, Map resourcePaths) + throws ParameterizedIdentifierIsFutureWork, ResolvingMultipleDefinitionIsFutureWork, InvalidMessage, UnificationFailed, ValueUndefined { + return deriveUpdateExpressionAndConcreteResourcePathsOf(targetMember, stateAccessor, null, resourcePaths); + } - public Expression deriveUpdateExpressionOf(ChannelMember targetMember, IResourceStateAccessor stateAccessor, HashMap inputResourceToStateAccessor) + public Expression deriveUpdateExpressionOf(ChannelMember targetMember, IResourceStateAccessor stateAccessor, HashMap inputResourceToStateAccessor) throws ParameterizedIdentifierIsFutureWork, ResolvingMultipleDefinitionIsFutureWork, InvalidMessage, UnificationFailed, ValueUndefined { if (!getOutputChannelMembers().contains(targetMember)) return null; + + // Calculate unified message constraints + Term unifiedMessage = calcUnifiedMessage(targetMember, stateAccessor, inputResourceToStateAccessor); + + // Calculate the next state of target resource from the unified message and the current resource state + Expression curOutputStateAccessor = stateAccessor.getCurrentStateAccessorFor(targetMember, targetMember); + if (unifiedMessage == null) { + // for IOChannel + if (targetMember.getStateTransition().getMessageExpression() instanceof Term) { + unifiedMessage = (Term) targetMember.getStateTransition().getMessageExpression(); + } + } + return targetMember.getStateTransition().deriveNextStateExpressionFor(curOutputStateAccessor, unifiedMessage); + } + + public Expression deriveUpdateExpressionAndConcreteResourcePathsOf(ChannelMember targetMember, IResourceStateAccessor stateAccessor, HashMap inputResourceToStateAccessor, Map resourcePaths) + throws ParameterizedIdentifierIsFutureWork, ResolvingMultipleDefinitionIsFutureWork, InvalidMessage, UnificationFailed, ValueUndefined { + if (!getOutputChannelMembers().contains(targetMember)) return null; + + // Calculate unified message constraints from input and reference state transitions + Term unifiedMessage = calcUnifiedMessage(targetMember, stateAccessor, inputResourceToStateAccessor); + + // Fill outside resource paths + if (unifiedMessage != null) { + for (ChannelMember cm: getInputChannelMembers()) { + if (cm.isOutside()) { + resourcePaths.put(cm, fillOutsideResourcePath(cm.getResource(), unifiedMessage, targetMember.getStateTransition().getMessageExpression())); + } + } + for (ChannelMember cm: getReferenceChannelMembers()) { + if (cm.isOutside()) { + resourcePaths.put(cm, fillOutsideResourcePath(cm.getResource(), unifiedMessage, targetMember.getStateTransition().getMessageExpression())); + } + } + for (ChannelMember cm: getOutputChannelMembers()) { + if (cm.isOutside()) { + resourcePaths.put(cm, fillOutsideResourcePath(cm.getResource(), unifiedMessage, targetMember.getStateTransition().getMessageExpression())); + } + } + } + + // Calculate the next state of target resource from the unified message and the current resource state + Expression curOutputStateAccessor = stateAccessor.getCurrentStateAccessorFor(targetMember, targetMember); + if (unifiedMessage == null) { + // for IOChannel + if (targetMember.getStateTransition().getMessageExpression() instanceof Term) { + unifiedMessage = (Term) targetMember.getStateTransition().getMessageExpression(); + } + } + return targetMember.getStateTransition().deriveNextStateExpressionFor(curOutputStateAccessor, unifiedMessage); + } + + private Term calcUnifiedMessage(ChannelMember targetMember, IResourceStateAccessor stateAccessor, + HashMap inputResourceToStateAccessor) + throws InvalidMessage, ResolvingMultipleDefinitionIsFutureWork, UnificationFailed { HashSet messageConstraints = new HashSet<>(); // Calculate message constraints from input state transitions for (ChannelMember inputMember: getInputChannelMembers()) { - ResourcePath inputResource = inputMember.getResource(); Expression curInputStateAccessor = null; Expression nextInputStateAccessor = null; if (inputResourceToStateAccessor == null) { - curInputStateAccessor = stateAccessor.getCurrentStateAccessorFor(inputResource, targetMember.getResource()); - nextInputStateAccessor = stateAccessor.getNextStateAccessorFor(inputResource, targetMember.getResource()); + curInputStateAccessor = stateAccessor.getCurrentStateAccessorFor(inputMember, targetMember); + nextInputStateAccessor = stateAccessor.getNextStateAccessorFor(inputMember, targetMember); } else { - curInputStateAccessor = inputResourceToStateAccessor.get(inputResource).getCurrentStateAccessorFor(inputResource, targetMember.getResource()); - nextInputStateAccessor = inputResourceToStateAccessor.get(inputResource).getNextStateAccessorFor(inputResource, targetMember.getResource()); + curInputStateAccessor = inputResourceToStateAccessor.get(inputMember).getCurrentStateAccessorFor(inputMember, targetMember); + nextInputStateAccessor = inputResourceToStateAccessor.get(inputMember).getNextStateAccessorFor(inputMember, targetMember); } Expression messageConstraintByInput = inputMember.getStateTransition().deriveMessageConstraintFor(curInputStateAccessor, nextInputStateAccessor); messageConstraints.add((Term) messageConstraintByInput); @@ -220,12 +305,11 @@ // Calculate message constraints from reference state transitions for (ChannelMember referenceMember: getReferenceChannelMembers()) { - ResourcePath referenceResource = referenceMember.getResource(); Expression curInputStateAccessor = null; if (inputResourceToStateAccessor == null) { - curInputStateAccessor = stateAccessor.getCurrentStateAccessorFor(referenceResource, targetMember.getResource()); + curInputStateAccessor = stateAccessor.getCurrentStateAccessorFor(referenceMember, targetMember); } else { - curInputStateAccessor = inputResourceToStateAccessor.get(referenceResource).getCurrentStateAccessorFor(referenceResource, targetMember.getResource()); + curInputStateAccessor = inputResourceToStateAccessor.get(referenceMember).getCurrentStateAccessorFor(referenceMember, targetMember); } Expression messageConstraintByReference = referenceMember.getStateTransition().deriveMessageConstraintFor(curInputStateAccessor); messageConstraints.add((Term) messageConstraintByReference); @@ -243,17 +327,41 @@ } } } + return unifiedMessage; + } + + private ResourcePath fillOutsideResourcePath(ResourcePath resource, Term unifiedMessage, Expression messageTerm) + throws ResolvingMultipleDefinitionIsFutureWork { + ResourcePath filledResourcePath = new ResourcePath(resource); - // Calculate the next state of target resource from the unified message and the current resource state - ResourcePath targetResource = targetMember.getResource(); - Expression curOutputStateAccessor = stateAccessor.getCurrentStateAccessorFor(targetResource, targetResource); - if (unifiedMessage == null) { - // for IOChannel - if (targetMember.getStateTransition().getMessageExpression() instanceof Term) { - unifiedMessage = (Term) targetMember.getStateTransition().getMessageExpression(); + HashMap bindings = new HashMap<>(); + HashMap messageVars = messageTerm.getVariables(); + for (Entry messageVarEnt: messageVars.entrySet()) { + Variable var = messageVarEnt.getValue(); + Position varPos = messageVarEnt.getKey(); + Expression valueCalc = unifiedMessage.getSubTerm(varPos); + if (valueCalc != null) { + if (bindings.get(var) != null) throw new ResolvingMultipleDefinitionIsFutureWork(); + bindings.put(var, valueCalc); } } - return targetMember.getStateTransition().deriveNextStateExpressionFor(curOutputStateAccessor, unifiedMessage); + + List dstParams = filledResourcePath.getPathParams(); + for (int i = 0; i < filledResourcePath.getPathParams().size(); i++) { + Expression pathParam = dstParams.get(i); + if (pathParam instanceof Variable) { + dstParams.set(i, bindings.get((Variable) pathParam)); + } else { + for (Variable var: bindings.keySet()) { + pathParam = ((Term) pathParam).substitute(var, bindings.get(var)); + } + if (!(pathParam instanceof Constant)) { + pathParam = ((Term) pathParam).reduce(); + } + dstParams.set(i, pathParam); + } + } + return filledResourcePath; } @Override @@ -273,7 +381,8 @@ } public interface IResourceStateAccessor { - Expression getCurrentStateAccessorFor(ResourcePath target, ResourcePath from); - Expression getNextStateAccessorFor(ResourcePath target, ResourcePath from); + Expression getCurrentStateAccessorFor(ChannelMember target, ChannelMember from); + Expression getNextStateAccessorFor(ChannelMember target, ChannelMember from); + Expression getDirectStateAccessorFor(ResourcePath targetRes, ResourcePath fromRes); } } diff --git a/AlgebraicDataflowArchitectureModel/src/tests/UpdateCodeGenerationTest.java b/AlgebraicDataflowArchitectureModel/src/tests/UpdateCodeGenerationTest.java index bdb21e6..92c754d 100644 --- a/AlgebraicDataflowArchitectureModel/src/tests/UpdateCodeGenerationTest.java +++ b/AlgebraicDataflowArchitectureModel/src/tests/UpdateCodeGenerationTest.java @@ -46,21 +46,28 @@ final Parameter pTotal = new Parameter("total", DataConstraintModel.typeInt); IResourceStateAccessor pushAccessor = new IResourceStateAccessor() { @Override - public Expression getCurrentStateAccessorFor(ResourcePath target, ResourcePath from) { - if (target.equals(from)) { - if (target.equals(payment)) return fPayment; - if (target.equals(points)) return fPoints; - if (target.equals(history)) return fHistory; - if (target.equals(total)) return fTotal; + public Expression getCurrentStateAccessorFor(ChannelMember target, ChannelMember from) { + ResourcePath targetRes = target.getResource(); + ResourcePath fromRes = from.getResource(); + if (targetRes.equals(fromRes)) { + if (targetRes.equals(payment)) return fPayment; + if (targetRes.equals(points)) return fPoints; + if (targetRes.equals(history)) return fHistory; + if (targetRes.equals(total)) return fTotal; } return null; } @Override - public Expression getNextStateAccessorFor(ResourcePath target, ResourcePath from) { - if (target.equals(payment)) return pPayment; - if (target.equals(points)) return pPoints; - if (target.equals(history)) return pHistory; - if (target.equals(total)) return pTotal; + public Expression getNextStateAccessorFor(ChannelMember target, ChannelMember from) { + ResourcePath targetRes = target.getResource(); + if (targetRes.equals(payment)) return pPayment; + if (targetRes.equals(points)) return pPoints; + if (targetRes.equals(history)) return pHistory; + if (targetRes.equals(total)) return pTotal; + return null; + } + @Override + public Expression getDirectStateAccessorFor(ResourcePath targetRes, ResourcePath fromRes) { return null; } }; @@ -72,38 +79,45 @@ final Symbol totalGetter = new Symbol("getTotal", 1, Symbol.Type.METHOD); IResourceStateAccessor pullAccessor = new IResourceStateAccessor() { @Override - public Expression getCurrentStateAccessorFor(ResourcePath target, ResourcePath from) { - if (target.equals(from)) { - if (target.equals(payment)) return fPayment; - if (target.equals(points)) return fPoints; - if (target.equals(history)) return fHistory; - if (target.equals(total)) return fTotal; + public Expression getCurrentStateAccessorFor(ChannelMember target, ChannelMember from) { + ResourcePath targetRes = target.getResource(); + ResourcePath fromRes = from.getResource(); + if (targetRes.equals(fromRes)) { + if (targetRes.equals(payment)) return fPayment; + if (targetRes.equals(points)) return fPoints; + if (targetRes.equals(history)) return fHistory; + if (targetRes.equals(total)) return fTotal; } return null; } @Override - public Expression getNextStateAccessorFor(ResourcePath target, ResourcePath from) { - if (target.equals(payment)) { + public Expression getNextStateAccessorFor(ChannelMember target, ChannelMember from) { + ResourcePath targetRes = target.getResource(); + if (targetRes.equals(payment)) { Term getter = new Term(paymentGetter); getter.addChild(fPayment); return getter; } - if (target.equals(points)) { + if (targetRes.equals(points)) { Term getter = new Term(pointsGetter); getter.addChild(fPoints); return getter; } - if (target.equals(history)) { + if (targetRes.equals(history)) { Term getter = new Term(historyGetter); getter.addChild(fHistory); return getter; } - if (target.equals(total)) { + if (targetRes.equals(total)) { Term getter = new Term(totalGetter); getter.addChild(fTotal); return getter; } return null; + } + @Override + public Expression getDirectStateAccessorFor(ResourcePath targetRes, ResourcePath fromRes) { + return null; } };