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); }