diff --git a/AlgebraicDataflowArchitectureModel/src/generators/CodeGeneratorFromDataFlowGraph.java b/AlgebraicDataflowArchitectureModel/src/generators/CodeGeneratorFromDataFlowGraph.java index 0ac7327..fbb3ef2 100644 --- a/AlgebraicDataflowArchitectureModel/src/generators/CodeGeneratorFromDataFlowGraph.java +++ b/AlgebraicDataflowArchitectureModel/src/generators/CodeGeneratorFromDataFlowGraph.java @@ -948,6 +948,23 @@ // PULL transfer inputResourceToStateAccessor.put(in, getPullAccessor(platformSpec)); ch = ((ChannelNode) resToCh.getDestination()).getChannel(); // pull containing input side channel is at most one. + if (!platformSpec.isMonolithic() + && !in.isOutside() + && in.getResource().getCommonPrefix(resourceNode.getInSideResource(ch2)) == null + && platformSpec.isDifferentTreesAsDifferentServices()) { + // for REST API + ResourcePath srcResPath = in.getResource(); + String srcResourceName = langSpec.toVariableName(getComponentName(srcResPath.getResourceHierarchy(), langSpec)); + Type srcResourceType = srcResPath.getResourceStateType(); + List pathParams = new ArrayList<>(); + for (Expression pathExp: srcResPath.getPathParams()) { + String[] sideEffects = new String[] {""}; + pathParams.add("\" + " + pathExp.toImplementation(sideEffects) + " + \""); + } + generatePullDataTransfer(stateGetter, srcResourceName, + srcResPath.getResourceHierarchy().toResourcePath(pathParams), srcResourceType, + true, platformSpec, langSpec); + } } } } @@ -963,21 +980,62 @@ } // for reference channel members. - for (ChannelMember c: ch.getReferenceChannelMembers()) { - inputResourceToStateAccessor.put(c, getPullAccessor(platformSpec)); // by pull data transfer + ResourcePath dstResPath = resourceNode.getInSideResource(ch); + for (ChannelMember rc: ch.getReferenceChannelMembers()) { + inputResourceToStateAccessor.put(rc, getPullAccessor(platformSpec)); // by pull data transfer + ResourcePath refResPath = rc.getResource(); + if (!platformSpec.isMonolithic() + && (rc.isOutside() + || (refResPath.getCommonPrefix(dstResPath) == null && platformSpec.isDifferentTreesAsDifferentServices()))) { + // for REST API + String refResourceName = langSpec.toVariableName(getComponentName(refResPath.getResourceHierarchy(), langSpec)); + Type refResourceType = refResPath.getResourceStateType(); + List pathParams = new ArrayList<>(); + for (Expression pathExp: refResPath.getPathParams()) { + String[] sideEffects = new String[] {""}; + pathParams.add("\" + " + pathExp.toImplementation(sideEffects) + " + \""); + } + generatePullDataTransfer(stateGetter, refResourceName, + refResPath.getResourceHierarchy().toResourcePath(pathParams), refResourceType, + true, platformSpec, langSpec); + } } // Construct the base message. Map.Entry>>, Term> resourcePathsAndMessage; if (!isContainedPush) { // All incoming edges are in PULL-style. - resourcePathsAndMessage = ch.fillOutsideResourcePaths(out, JavaCodeGenerator.pullAccessor, null); + resourcePathsAndMessage = ch.fillOutsideResourcePaths(out, getPullAccessor(platformSpec), null); } else { // At least one incoming edge is in PUSH-style. - resourcePathsAndMessage = ch.fillOutsideResourcePaths(out, JavaCodeGenerator.pullAccessor, inputResourceToStateAccessor); + resourcePathsAndMessage = ch.fillOutsideResourcePaths(out, getPullAccessor(platformSpec), inputResourceToStateAccessor); } Map>> resourcePaths = resourcePathsAndMessage.getKey(); - Term messageTerm = resourcePathsAndMessage.getValue(); + Term messageTerm = resourcePathsAndMessage.getValue(); + + // Data transfer from path depending resource. + for (Entry>> pathEnt: resourcePaths.entrySet()) { + ChannelMember cm = pathEnt.getKey(); + ResourcePath srcResPath = pathEnt.getValue().getKey(); + // get outside srcResPath resource state by pull data transfer. + if (!platformSpec.isMonolithic() + && (cm.isOutside() + || (srcResPath.getCommonPrefix(dstResPath)) == null && platformSpec.isDifferentTreesAsDifferentServices())) { + // for REST API + // Data transfer from an outside input resource is regarded as PULL transfer. + List pathParams = new ArrayList<>(); + for (Expression pathExp: srcResPath.getPathParams()) { + String[] sideEffects = new String[] {""}; + pathParams.add("\" + " + pathExp.toImplementation(sideEffects) + " + \""); + } + // generate a pull data transfer from a depending in/ref resource. + Type srcResourceType = srcResPath.getResourceStateType(); + String srcResName2 = langSpec.toVariableName(getComponentName(srcResPath.getResourceHierarchy(), langSpec)); + String srcPath2 = srcResPath.toString().replaceAll("\\{", "\"+").replaceAll("\\}", "+\""); + generatePullDataTransfer(stateGetter, srcResName2, srcPath2, srcResourceType, false, platformSpec, langSpec); + } + } + // Data transfer from the descendant channel hierarchies. Stack> channelItrStack = new Stack<>(); DataTransferChannel curChannel = ch; @@ -997,9 +1055,15 @@ // not a depending channel member. ResourcePath src2 = cm2.getResource(); Type srcResType2 = src2.getResourceStateType(); - String srcResName2 = JerseyCodeGenerator.toVariableName(JerseyCodeGenerator.getComponentName(src2.getResourceHierarchy())); - String srcGetter = JavaCodeGenerator.pullAccessor.getDirectStateAccessorFor(src2, resourceNode.getInSideResource(curChannel)).toImplementation(new String[] {}); - stateGetter.addStatement(srcResType2.getInterfaceTypeName() + " " + srcResName2 + " = " + srcGetter + ";"); + String srcResName2 = langSpec.toVariableName(getComponentName(src2.getResourceHierarchy(), langSpec)); + if (platformSpec.isMonolithic()) { + String srcGetter = getPullAccessor(platformSpec).getDirectStateAccessorFor(src2, resourceNode.getInSideResource(curChannel)).toImplementation(new String[] {}); + stateGetter.addStatement(langSpec.getVariableDeclaration(srcResType2.getInterfaceTypeName(), srcResName2) + + langSpec.getAssignment() + srcGetter + langSpec.getStatementDelimiter()); + } else { + String srcPath2 = src2.toString().replaceAll(":.*\\}","\\}").replaceAll("\\{", "\"+").replaceAll("\\}", "+\""); + generatePullDataTransfer(stateGetter, srcResName2, srcPath2, srcResType2, false, platformSpec, langSpec); + } } else { // a depending channel member. ResourcePath src2 = resourcePaths.get(cm2).getKey(); @@ -1007,16 +1071,22 @@ if (cm2.isOutside() || src2.getCommonPrefix(resourceNode.getInSideResource(curChannel)) == null) { // generate a pull data transfer from a depending in/ref resource. Type srcResType2 = src2.getResourceStateType(); - String srcResName2 = JerseyCodeGenerator.toVariableName(JerseyCodeGenerator.getComponentName(src2.getResourceHierarchy())); - String dependingGetter = JavaCodeGenerator.pullAccessor.getDirectStateAccessorFor(src2, resourceNode.getInSideResource(curChannel)).toImplementation(new String[] {}); - stateGetter.addStatement(srcResType2.getInterfaceTypeName() + " " + srcResName2 + " = " + dependingGetter + ";"); + String srcResName2 = langSpec.toVariableName(getComponentName(src2.getResourceHierarchy(), langSpec)); + if (platformSpec.isMonolithic()) { + String dependingGetter = getPullAccessor(platformSpec).getDirectStateAccessorFor(src2, resourceNode.getInSideResource(curChannel)).toImplementation(new String[] {}); + stateGetter.addStatement(langSpec.getVariableDeclaration(srcResType2.getInterfaceTypeName(), srcResName2) + + langSpec.getAssignment() + dependingGetter + langSpec.getStatementDelimiter()); + } else { + String srcPath2 = src2.toString().replaceAll(":.*\\}","\\}").replaceAll("\\{", "\"+").replaceAll("\\}", "+\""); + generatePullDataTransfer(stateGetter, srcResName2, srcPath2, srcResType2, false, platformSpec, langSpec); + } } } } // collect the message constraints by a descendant channel. List varsForSideEffects = new ArrayList<>(); int v = 0; - resourcePathsAndMessage = curChannel.fillOutsideResourcePaths(out, JavaCodeGenerator.pullAccessor, null); + resourcePathsAndMessage = curChannel.fillOutsideResourcePaths(out, getPullAccessor(platformSpec), null); if (resourcePathsAndMessage != null) { resourcePaths = resourcePathsAndMessage.getKey(); Term messageTermSub = resourcePathsAndMessage.getValue(); @@ -1053,13 +1123,13 @@ throw new UnificationFailed(); } } - // enclosed by a for loop + // enclosed by a for loop (for data collecting pull transfer) Expression selExp = curChannel.getSelectors().get(0).getExpression(); Type selType = null; - String varName = null; + String forVarName = null; if (selExp instanceof Variable) { selType = ((Variable) selExp).getType(); - varName = ((Variable) selExp).getName(); + forVarName = ((Variable) selExp).getName(); ChannelMember insideChMem = null; for (ChannelMember cm2 :curChannel.getInputChannelMembers()) { if (!cm2.isOutside()) { @@ -1080,20 +1150,45 @@ insideResPath = insideResPath.getParent(); } insideResPath = insideResPath.getParent(); - String parent = JavaCodeGenerator.pullAccessor.getDirectStateAccessorFor(insideResPath, resourceNode.getInSideResource(curChannel)).toImplementation(new String[] {}); if (insideResPath != null) { + String parent = null; + if (platformSpec.isMonolithic() + || insideResPath.getCommonPrefix(dstResPath) != null + || !platformSpec.isDifferentTreesAsDifferentServices()) { + if (!platformSpec.isMonolithic() && generatesComponent(insideResPath.getResourceHierarchy())) { + Expression parentGetter = getPullAccessor(platformSpec).getDirectStateAccessorFor(insideResPath, dstResPath); + Term valueGetter = new Term(new Symbol(getterOfResourceState, 1, Symbol.Type.METHOD)); + valueGetter.addChild(parentGetter); + parent = valueGetter.toImplementation(new String[] {}); + } else { + parent = getPullAccessor(platformSpec).getDirectStateAccessorFor(insideResPath, dstResPath).toImplementation(new String[] {}); + } + } else { + // for REST API + parent = JerseyCodeGenerator.toVariableName(JerseyCodeGenerator.getComponentName(insideResPath.getResourceHierarchy())); + } if (selType.equals(DataConstraintModel.typeInt)) { // make a for loop (for a list) for data collecting. - stateGetter.addFirstStatement("for (int " + varName + " = 0; " + varName +" < " + parent + ".size(); " + varName + "++) {"); + stateGetter.addFirstStatement(langSpec.getForStatementForList(forVarName, parent)); } else if (selType.equals(DataConstraintModel.typeString)) { // make a for loop (for a map) for data collecting. - stateGetter.addFirstStatement("for (String " + varName + ": " + parent + ".keySet()) {"); + stateGetter.addFirstStatement(langSpec.getForStatementForMap(forVarName, DataConstraintModel.typeString.getInterfaceTypeName(), parent)); + } + if (!platformSpec.isMonolithic() + && insideResPath.getCommonPrefix(dstResPath) == null + && platformSpec.isDifferentTreesAsDifferentServices()) { + // for REST API + Type parentResType = insideResPath.getResourceStateType(); + String parentResName = JerseyCodeGenerator.toVariableName(JerseyCodeGenerator.getComponentName(insideResPath.getResourceHierarchy())); + String parentResPath = insideResPath.toString().replaceAll(":.*\\}","\\}").replaceAll("\\{", "\"+").replaceAll("\\}", "+\""); + generatePullDataTransfer(stateGetter, parentResName, parentResPath, parentResType, true, platformSpec, langSpec); } } } // initialize the variables to hold side effects within the loop for (Variable var: varsForSideEffects) { - stateGetter.addFirstStatement(var.getType().getInterfaceTypeName() + " " + var.getName() + " = new " + var.getType().getImplementationTypeName() + "();"); + stateGetter.addFirstStatement(langSpec.getVariableDeclaration(var.getType().getInterfaceTypeName(), var.getName()) + + langSpec.getAssignment() + langSpec.getConstructorInvocation(var.getType().getImplementationTypeName(), null) + langSpec.getStatementDelimiter()); } // end of the loop stateGetter.addStatement("}"); @@ -1490,7 +1585,7 @@ } else { Term conditions = null; int i = 1; - Map>> resourcePaths = ch.fillOutsideResourcePaths(out, JerseyCodeGenerator.pushAccessor); + Map>> resourcePaths = ch.fillOutsideResourcePaths(out, getPushAccessor(platformSpec)); for (Expression pathParam: out.getResource().getPathParams()) { if (pathParam instanceof Variable) { String selfParamName = ((Variable) pathParam).getName(); @@ -1707,16 +1802,23 @@ insideResPath = insideResPath.getParent(); } insideResPath = insideResPath.getParent(); - String parent = null; - if (!platformSpec.isMonolithic() && generatesComponent(insideResPath.getResourceHierarchy())) { - Expression getter = getPullAccessor(platformSpec).getDirectStateAccessorFor(insideResPath, resourceNode.getPrimaryResourcePath()); - Term valueGetter = new Term(new Symbol(getterOfResourceState, 1, Symbol.Type.METHOD)); - valueGetter.addChild(getter); - parent = valueGetter.toImplementation(new String[] {}); - } else { - parent = getPullAccessor(platformSpec).getDirectStateAccessorFor(insideResPath, resourceNode.getPrimaryResourcePath()).toImplementation(new String[] {}); - } if (insideResPath != null) { + String parent = null; + if (platformSpec.isMonolithic() + || insideResPath.getCommonPrefix(resourceNode.getOutSideResource(directDstCh)) != null + || !platformSpec.isDifferentTreesAsDifferentServices()) { + if (!platformSpec.isMonolithic() && generatesComponent(insideResPath.getResourceHierarchy())) { + Expression getter = getPullAccessor(platformSpec).getDirectStateAccessorFor(insideResPath, resourceNode.getOutSideResource(directDstCh)); + Term valueGetter = new Term(new Symbol(getterOfResourceState, 1, Symbol.Type.METHOD)); + valueGetter.addChild(getter); + parent = valueGetter.toImplementation(new String[] {}); + } else { + parent = getPullAccessor(platformSpec).getDirectStateAccessorFor(insideResPath, resourceNode.getOutSideResource(directDstCh)).toImplementation(new String[] {}); + } + } else { + // for REST API + parent = JerseyCodeGenerator.toVariableName(JerseyCodeGenerator.getComponentName(insideResPath.getResourceHierarchy())); + } if (selType.equals(DataConstraintModel.typeInt)) { // make a for loop (for a list) for broadcasting. update.addStatement(langSpec.getForStatementForList(forVarName, parent)); @@ -1726,6 +1828,15 @@ update.addStatement(langSpec.getForStatementForMap(forVarName, DataConstraintModel.typeString.getInterfaceTypeName(), parent)); addForStatement = true; } + if (!platformSpec.isMonolithic() + && insideResPath.getCommonPrefix(resourceNode.getOutSideResource(directDstCh)) == null + && platformSpec.isDifferentTreesAsDifferentServices()) { + // for REST API + Type parentResType = insideResPath.getResourceStateType(); + String parentResName = JerseyCodeGenerator.toVariableName(JerseyCodeGenerator.getComponentName(insideResPath.getResourceHierarchy())); + String parentResPath = insideResPath.toString().replaceAll(":.*\\}","\\}").replaceAll("\\{", "\"+").replaceAll("\\}", "+\""); + generatePullDataTransfer(update, parentResName, parentResPath, parentResType, true, platformSpec, langSpec); + } } } else if (selExp instanceof Term) { // not supported. @@ -2507,8 +2618,23 @@ insideResPath = insideResPath.getParent(); } insideResPath = insideResPath.getParent(); - String parent = getPullAccessor(platformSpec).getDirectStateAccessorFor(insideResPath, resourceNode.getPrimaryResourcePath()).toImplementation(new String[] {}); if (insideResPath != null) { + String parent = null; + if (platformSpec.isMonolithic() + || insideResPath.getCommonPrefix(resourceNode.getOutSideResource(directDstCh)) != null + || !platformSpec.isDifferentTreesAsDifferentServices()) { + if (!platformSpec.isMonolithic() && generatesComponent(insideResPath.getResourceHierarchy())) { + Expression getter = getPullAccessor(platformSpec).getDirectStateAccessorFor(insideResPath, resourceNode.getOutSideResource(directDstCh)); + Term valueGetter = new Term(new Symbol(getterOfResourceState, 1, Symbol.Type.METHOD)); + valueGetter.addChild(getter); + parent = valueGetter.toImplementation(new String[] {}); + } else { + parent = getPullAccessor(platformSpec).getDirectStateAccessorFor(insideResPath, resourceNode.getOutSideResource(directDstCh)).toImplementation(new String[] {}); + } + } else { + // for REST API + parent = JerseyCodeGenerator.toVariableName(JerseyCodeGenerator.getComponentName(insideResPath.getResourceHierarchy())); + } if (selType.equals(DataConstraintModel.typeInt)) { // make a for loop (for a list) for broadcasting. input.addStatement(langSpec.getForStatementForList(forVarName, parent)); @@ -2518,6 +2644,15 @@ input.addStatement(langSpec.getForStatementForMap(forVarName, DataConstraintModel.typeString.getInterfaceTypeName(), parent)); addForStatement = true; } + if (!platformSpec.isMonolithic() + && insideResPath.getCommonPrefix(resourceNode.getOutSideResource(directDstCh)) == null + && platformSpec.isDifferentTreesAsDifferentServices()) { + // for REST API + Type parentResType = insideResPath.getResourceStateType(); + String parentResName = JerseyCodeGenerator.toVariableName(JerseyCodeGenerator.getComponentName(insideResPath.getResourceHierarchy())); + String parentResPath = insideResPath.toString().replaceAll(":.*\\}","\\}").replaceAll("\\{", "\"+").replaceAll("\\}", "+\""); + generatePullDataTransfer(input, parentResName, parentResPath, parentResType, true, platformSpec, langSpec); + } } } else if (selExp instanceof Term) { // not supported. @@ -3055,9 +3190,9 @@ varName += "_json"; String mapTypeName = convertFromEntryToMapType(compType, langSpec); respTypeName = "List<" + mapTypeName + ">"; - respConverter += fromResourceType.getInterfaceTypeName() + " " + fromResourceName + langSpec.getAssignment() + langSpec.getConstructorInvocation(fromResourceType.getImplementationTypeName(), null) + langSpec.getStringDelimiter() + "\n"; + respConverter += langSpec.getVariableDeclaration(fromResourceType.getInterfaceTypeName(), fromResourceName) + langSpec.getAssignment() + langSpec.getConstructorInvocation(fromResourceType.getImplementationTypeName(), null) + langSpec.getStatementDelimiter() + "\n"; respConverter += "for (" + mapTypeName + " i: " + varName + ") {\n"; - respConverter += "\t" + fromResourceName + ".add(" + getCodeForConversionFromMapToTuple(compType, "i", langSpec) + ")" + langSpec.getStringDelimiter() + "\n"; + respConverter += "\t" + fromResourceName + ".add(" + getCodeForConversionFromMapToTuple(compType, "i", langSpec) + ")" + langSpec.getStatementDelimiter() + "\n"; respConverter += "}"; restApiSpec.addJsonException(methodBody); } else if (DataConstraintModel.typeMap.isAncestorOf(compType)) { @@ -3066,17 +3201,17 @@ } else if (DataConstraintModel.typeTuple.isAncestorOf(fromResourceType)) { varName += "_json"; respTypeName = convertFromEntryToMapType(fromResourceType, langSpec); - respConverter += fromResourceType.getInterfaceTypeName() + " " + fromResourceName + langSpec.getAssignment() + getCodeForConversionFromMapToTuple(fromResourceType, varName, langSpec) + langSpec.getStringDelimiter(); + respConverter += langSpec.getVariableDeclaration(fromResourceType.getInterfaceTypeName(), fromResourceName) + langSpec.getAssignment() + getCodeForConversionFromMapToTuple(fromResourceType, varName, langSpec) + langSpec.getStatementDelimiter(); respImplTypeName = "HashMap"; } else if (DataConstraintModel.typePair.isAncestorOf(fromResourceType)) { varName += "_json"; respTypeName = convertFromEntryToMapType(fromResourceType, langSpec); - respConverter += fromResourceType.getInterfaceTypeName() + " " + fromResourceName + langSpec.getAssignment() + getCodeForConversionFromMapToPair(fromResourceType, varName, langSpec) + langSpec.getStringDelimiter(); + respConverter += langSpec.getVariableDeclaration(fromResourceType.getInterfaceTypeName(), fromResourceName) + langSpec.getAssignment() + getCodeForConversionFromMapToPair(fromResourceType, varName, langSpec) + langSpec.getStatementDelimiter(); respImplTypeName = "HashMap"; } else if (DataConstraintModel.typeMap.isAncestorOf(fromResourceType)) { varName += "_json"; respTypeName = convertFromEntryToMapType(fromResourceType, langSpec); - respConverter += fromResourceType.getInterfaceTypeName() + " " + fromResourceName + langSpec.getAssignment() + langSpec.getConstructorInvocation(fromResourceType.getImplementationTypeName(), null) + langSpec.getStringDelimiter() + "\n"; + respConverter += langSpec.getVariableDeclaration(fromResourceType.getInterfaceTypeName(), fromResourceName) + langSpec.getAssignment() + langSpec.getConstructorInvocation(fromResourceType.getImplementationTypeName(), null) + langSpec.getStatementDelimiter() + "\n"; respConverter += getCodeForConversionFromMapToMap(fromResourceType, varName, fromResourceName, langSpec); respImplTypeName = "HashMap"; } @@ -3084,9 +3219,9 @@ if (respConverter.length() > 0) { methodBody.addFirstStatement(respConverter); } - methodBody.addFirstStatement(respTypeName + " " + varName + " = " + restApiSpec.getHttpMethodCallWithResponseStatement(restApiSpec.getBaseURL(), fromResourcePath, getterPrefix, respImplTypeName)); + methodBody.addFirstStatement(langSpec.getVariableDeclaration(respTypeName, varName) + langSpec.getAssignment() + restApiSpec.getHttpMethodCallWithResponseStatement(restApiSpec.getBaseURL(), fromResourcePath, getterPrefix, respImplTypeName)); } else { - methodBody.addStatement(respTypeName + " " + varName + " = " + restApiSpec.getHttpMethodCallWithResponseStatement(restApiSpec.getBaseURL(), fromResourcePath, getterPrefix, respImplTypeName)); + methodBody.addStatement(langSpec.getVariableDeclaration(respTypeName, varName) + langSpec.getAssignment() + restApiSpec.getHttpMethodCallWithResponseStatement(restApiSpec.getBaseURL(), fromResourcePath, getterPrefix, respImplTypeName)); if (respConverter.length() > 0) { methodBody.addStatement(respConverter); } diff --git a/AlgebraicDataflowArchitectureModel/src/generators/JavaCodeGenerator.java b/AlgebraicDataflowArchitectureModel/src/generators/JavaCodeGenerator.java index 2a8d5f4..61bb142 100644 --- a/AlgebraicDataflowArchitectureModel/src/generators/JavaCodeGenerator.java +++ b/AlgebraicDataflowArchitectureModel/src/generators/JavaCodeGenerator.java @@ -1279,6 +1279,7 @@ if (!target.isOutside()) { return getDirectStateAccessorFor(targetRes, fromRes); } + // Get the next state by invoking a getter method. Term getter = null; String targetComponentName = getComponentName(targetRes.getResourceHierarchy()); if (generatesComponent(targetRes.getResourceHierarchy())) { diff --git a/AlgebraicDataflowArchitectureModel/src/generators/JavaMethodBodyGenerator.java b/AlgebraicDataflowArchitectureModel/src/generators/JavaMethodBodyGenerator.java index 2cba6d3..d626b70 100644 --- a/AlgebraicDataflowArchitectureModel/src/generators/JavaMethodBodyGenerator.java +++ b/AlgebraicDataflowArchitectureModel/src/generators/JavaMethodBodyGenerator.java @@ -469,8 +469,8 @@ insideResPath = insideResPath.getParent(); } insideResPath = insideResPath.getParent(); - String parent = JavaCodeGenerator.pullAccessor.getDirectStateAccessorFor(insideResPath, src.getPrimaryResourcePath()).toImplementation(new String[] {}); if (insideResPath != null) { + String parent = JavaCodeGenerator.pullAccessor.getDirectStateAccessorFor(insideResPath, src.getOutSideResource(directDstCh)).toImplementation(new String[] {}); if (selType.equals(DataConstraintModel.typeInt)) { // make a for loop (for a list) for broadcasting. srcUpdate.addFirstStatement("for (int " + forVarName + " = 0; " + forVarName +" < " + parent + ".size(); " + forVarName + "++) {"); @@ -620,8 +620,8 @@ insideResPath = insideResPath.getParent(); } insideResPath = insideResPath.getParent(); - String parent = JavaCodeGenerator.pullAccessor.getDirectStateAccessorFor(insideResPath, src.getPrimaryResourcePath()).toImplementation(new String[] {}); if (insideResPath != null) { + String parent = JavaCodeGenerator.pullAccessor.getDirectStateAccessorFor(insideResPath, src.getOutSideResource(directDstCh)).toImplementation(new String[] {}); if (selType.equals(DataConstraintModel.typeInt)) { // make a for loop (for a list) for broadcasting. srcInput.addFirstStatement("for (int " + varName + " = 0; " + varName +" < " + parent + ".size(); " + varName + "++) {"); @@ -793,8 +793,8 @@ insideResPath = insideResPath.getParent(); } insideResPath = insideResPath.getParent(); - String parent = JavaCodeGenerator.pullAccessor.getDirectStateAccessorFor(insideResPath, src.getPrimaryResourcePath()).toImplementation(new String[] {}); if (insideResPath != null) { + String parent = JavaCodeGenerator.pullAccessor.getDirectStateAccessorFor(insideResPath, dst.getInSideResource(ch)).toImplementation(new String[] {}); if (selType.equals(DataConstraintModel.typeInt)) { // make a for loop (for a list) for data collecting. getter.addFirstStatement("for (int " + varName + " = 0; " + varName +" < " + parent + ".size(); " + varName + "++) {"); diff --git a/AlgebraicDataflowArchitectureModel/src/generators/JerseyCodeGenerator.java b/AlgebraicDataflowArchitectureModel/src/generators/JerseyCodeGenerator.java index 8f25f75..bd709ef 100644 --- a/AlgebraicDataflowArchitectureModel/src/generators/JerseyCodeGenerator.java +++ b/AlgebraicDataflowArchitectureModel/src/generators/JerseyCodeGenerator.java @@ -1457,6 +1457,7 @@ return getDirectStateAccessorFor(targetRes, fromRes); } } + // Get the next state through a local variable which is to be initialized by a response of a GET API. return new Parameter(toVariableName(getComponentName(targetRes.getResourceHierarchy())), targetRes.getResourceStateType() != null ? targetRes.getResourceStateType() : DataConstraintModel.typeInt); diff --git a/AlgebraicDataflowArchitectureModel/src/generators/JerseyMethodBodyGenerator.java b/AlgebraicDataflowArchitectureModel/src/generators/JerseyMethodBodyGenerator.java index 62140b9..da1c8fe 100644 --- a/AlgebraicDataflowArchitectureModel/src/generators/JerseyMethodBodyGenerator.java +++ b/AlgebraicDataflowArchitectureModel/src/generators/JerseyMethodBodyGenerator.java @@ -821,6 +821,8 @@ } if (getter.getBody() == null || getter.getBody().getStatements().size() == 0) { // The first time to fill the getter method's body. + + // Data transfer on the same channel hierarchy. String[] sideEffects = new String[] {""}; // For each reference channel member, get the current state of the reference side resource by pull data transfer. for (ChannelMember rc: ch.getReferenceChannelMembers()) { @@ -846,14 +848,19 @@ getter.addFirstStatement(sideEffects[0] + refTypeName + " " + refResourceName + " = " + refExp + ";"); } } + + // Construct the base message. Map.Entry>>, Term> resourcePathsAndMessage = ch.fillOutsideResourcePaths(out, JerseyCodeGenerator.pullAccessor, null); Map>> resourcePaths = resourcePathsAndMessage.getKey(); Term messageTerm = resourcePathsAndMessage.getValue(); + + // Data transfer from path depending resource. for (Entry>> pathEnt: resourcePaths.entrySet()) { ChannelMember cm = pathEnt.getKey(); ResourcePath src2 = pathEnt.getValue().getKey(); - // get outside src resource state by pull data transfer. + // get outside src2 resource state by pull data transfer. if (cm.isOutside() || src2.getCommonPrefix(dst.getInSideResource(ch)) == null) { + // Data transfer from an outside input resource is regarded as PULL transfer. List pathParams = new ArrayList<>(); for (Expression pathExp: src2.getPathParams()) { sideEffects = new String[] {""}; @@ -866,17 +873,19 @@ generatePullDataTransfer(getter, srcResName2, srcPath2, srcResourceType); } } - // Should take into account the channel hierarchy. + + // Data transfer from the descendant channel hierarchies. Stack> channelItrStack = new Stack<>(); DataTransferChannel curChannel = ch; if (curChannel.getChildren() != null && curChannel.getChildren().size() > 0) { - // retrieve descendant channels recursively. + // retrieve descendant channels recursively. + // (For each descendant channel, data transfer from every input resource is regarded as PULL transfer.) Iterator chItr = curChannel.getChildren().iterator(); do { if (!chItr.hasNext()) { chItr = channelItrStack.pop(); } else { - curChannel = (DataTransferChannel) chItr.next(); + curChannel = (DataTransferChannel) chItr.next(); // generate pull data transfers. Set chMems = new HashSet<>(curChannel.getInputChannelMembers()); chMems.addAll(curChannel.getReferenceChannelMembers()); diff --git a/AlgebraicDataflowArchitectureModel/src/generators/JerseySpecific.java b/AlgebraicDataflowArchitectureModel/src/generators/JerseySpecific.java index 5db510d..e4ee223 100644 --- a/AlgebraicDataflowArchitectureModel/src/generators/JerseySpecific.java +++ b/AlgebraicDataflowArchitectureModel/src/generators/JerseySpecific.java @@ -140,7 +140,7 @@ if (responseTypeName.contains("<")) { responseShortTypeName = responseTypeName.substring(0, responseTypeName.indexOf("<")); } - return "client.target(\"" + baseURL + "\").path(\"/" + resourceName + "\").request()." + httpMethod + "(" + responseShortTypeName + ".class)" + langSpec.getStatementDelimiter() + "\n"; + return "client.target(\"" + baseURL + "\").path(\"/" + resourceName + "\").request()." + httpMethod + "(" + responseShortTypeName + ".class)" + langSpec.getStatementDelimiter(); } @Override