diff --git a/AlgebraicDataflowArchitectureModel/src/generators/JerseyCodeGenerator.java b/AlgebraicDataflowArchitectureModel/src/generators/JerseyCodeGenerator.java index 88e747f..18c8b1b 100644 --- a/AlgebraicDataflowArchitectureModel/src/generators/JerseyCodeGenerator.java +++ b/AlgebraicDataflowArchitectureModel/src/generators/JerseyCodeGenerator.java @@ -295,7 +295,7 @@ dstRes = dstRes.getParent(); } String dstResName = getComponentName(dstRes.getResourceHierarchy()); - if (resourceNode.getOutSideResource().getCommonPrefix(dstRes) == null && differentTreesAsDifferentServices) { +// if (resourceNode.getOutSideResource().getCommonPrefix(dstRes) == null && differentTreesAsDifferentServices) { // Inter-service if (!bDeclareClientField) { // Declare a client field to connect to the destination resource of push transfer. @@ -303,14 +303,14 @@ fields.add(new AbstractMap.SimpleEntry<>(resourceNode.getParent().getResourceHierarchy(), clientField)); bDeclareClientField = true; } - } else { - // Inner-service - // Declare a field to directly refer to the destination resource of push transfer. - if (resourceNode.getParent().getResourceHierarchy() != dstRes.getResourceHierarchy()) { - FieldDeclaration refFieldForPush = new FieldDeclaration(new Type(dstResName, dstResName), toVariableName(dstResName)); - fields.add(new AbstractMap.SimpleEntry<>(resourceNode.getParent().getResourceHierarchy(), refFieldForPush)); - } - } +// } else { +// // Inner-service +// // Declare a field to directly refer to the destination resource of push transfer. +// if (resourceNode.getParent().getResourceHierarchy() != dstRes.getResourceHierarchy()) { +// FieldDeclaration refFieldForPush = new FieldDeclaration(new Type(dstResName, dstResName), toVariableName(dstResName)); +// fields.add(new AbstractMap.SimpleEntry<>(resourceNode.getParent().getResourceHierarchy(), refFieldForPush)); +// } +// } } } } @@ -333,7 +333,7 @@ srcRes = srcRes.getParent(); } String srcResName = getComponentName(srcRes.getResourceHierarchy()); - if (resourceNode.getOutSideResource().getCommonPrefix(srcRes) == null && differentTreesAsDifferentServices) { +// if (resourceNode.getOutSideResource().getCommonPrefix(srcRes) == null && differentTreesAsDifferentServices) { // Inter-service if (!bDeclareClientField) { // Declare a client field to connect to the source resource of pull transfer. @@ -341,14 +341,14 @@ fields.add(new AbstractMap.SimpleEntry<>(resourceNode.getParent().getResourceHierarchy(), clientField)); bDeclareClientField = true; } - } else { - // Inner-service - // Declare a field to directly refer to the source resource of pull transfer. - if (resourceNode.getParent().getResourceHierarchy() != srcRes.getResourceHierarchy()) { - FieldDeclaration refFieldForPull = new FieldDeclaration(new Type(srcResName, srcResName), toVariableName(srcResName)); - fields.add(new AbstractMap.SimpleEntry<>(resourceNode.getParent().getResourceHierarchy(), refFieldForPull)); - } - } +// } else { +// // Inner-service +// // Declare a field to directly refer to the source resource of pull transfer. +// if (resourceNode.getParent().getResourceHierarchy() != srcRes.getResourceHierarchy()) { +// FieldDeclaration refFieldForPull = new FieldDeclaration(new Type(srcResName, srcResName), toVariableName(srcResName)); +// fields.add(new AbstractMap.SimpleEntry<>(resourceNode.getParent().getResourceHierarchy(), refFieldForPull)); +// } +// } noPullTransfer = false; } } @@ -457,11 +457,12 @@ // Check if the output resource is outside of the channel scope. boolean outsideOutputResource = cm.isOutside(); if (!bDeclareClientField && ((((PushPullAttribute) re.getAttribute()).getOptions().get(0) == PushPullValue.PUSH && !outsideInputResource) || outsideOutputResource)) { + // For push transfer. if (!generatesComponent(dstRes.getResourceHierarchy())) { dstRes = dstRes.getParent(); } String dstResName = getComponentName(dstRes.getResourceHierarchy()); - if (resourceNode.getOutSideResource().getCommonPrefix(dstRes) == null && differentTreesAsDifferentServices) { + if (outsideOutputResource || (resourceNode.getOutSideResource().getCommonPrefix(dstRes) == null && differentTreesAsDifferentServices)) { // Inter-service if (!bDeclareClientField) { // Declare a client field to connect to the destination resource of push transfer. @@ -509,18 +510,24 @@ } // Check if the output resource is outside of the channel scope. boolean outsideOutputResource = false; + ChannelMember out = null; for (ChannelMember cm: ch.getOutputChannelMembers()) { - if (resourceNode.getInSideResources().contains(cm.getResource()) && cm.isOutside()) { - outsideOutputResource = true; // Regarded as push transfer. - break; + if (resourceNode.getInSideResources().contains(cm.getResource())) { + out = cm; + if (cm.isOutside()) { + outsideOutputResource = true; // Regarded as push transfer. + break; + } } } String srcResName = getComponentName(srcRes.getResourceHierarchy()); + Type srcType = srcRes.getResourceStateType(); if (!generatesComponent(srcRes.getResourceHierarchy())) { srcRes = srcRes.getParent(); } if ((((PushPullAttribute) re.getAttribute()).getOptions().get(0) != PushPullValue.PUSH && !outsideOutputResource) || outsideInputResource) { - if (resourceNode.getOutSideResource().getCommonPrefix(srcRes) == null && differentTreesAsDifferentServices) { + // For pull transfer. + if (outsideInputResource || (resourceNode.getOutSideResource().getCommonPrefix(srcRes) == null && differentTreesAsDifferentServices)) { // Inter-service if (!bDeclareClientField) { // Declare a client field to connect to the source resource of pull transfer. @@ -551,17 +558,27 @@ } } } else { + // For push transfer. + boolean hasRestAPI = false; + boolean isRestAPI = false; + if (outsideOutputResource || (resourceNode.getOutSideResource().getCommonPrefix(srcRes) == null && differentTreesAsDifferentServices)) { + // Inter-service + hasRestAPI = true; + if (resourceNode.getParent() == null) { + // A root resource + isRestAPI = true; + } + } // Declare an update method in the type of the destination resource. ArrayList vars = new ArrayList<>(); - String srcName = srcRes.getResourceName(); - Type srcType = srcRes.getResourceStateType(); + String srcName = toVariableName(srcResName); VariableDeclaration param = new VariableDeclaration(srcType, srcName); - param.addAnnotation(new Annotation("FormParam", "\"" + srcName + "\"")); + if (isRestAPI) param.addAnnotation(new Annotation("FormParam", "\"" + srcName + "\"")); vars.add(param); for (ResourcePath refRes: ((ChannelNode) re.getDestination()).getChannel().getReferenceResources()) { if (!refRes.equals(resourceNode.getOutSideResource())) { param = new VariableDeclaration(refRes.getResourceStateType(), refRes.getResourceName()); - param.addAnnotation(new Annotation("FormParam", "\"" + refRes.getResourceName() + "\"")); + if (isRestAPI) param.addAnnotation(new Annotation("FormParam", "\"" + refRes.getResourceName() + "\"")); vars.add(param); } } @@ -574,17 +591,37 @@ String resourceName = getComponentName(resourceNode.getResourceHierarchy()); update = new MethodDeclaration("update" + resourceName + "From" + srcResName, false, typeVoid, vars); } + // Determine whether the update method is put or post. + boolean isPut = false; for (ChannelMember cm: ((ChannelNode) re.getDestination()).getChannel().getOutputChannelMembers()) { if (resourceNode.getInSideResources().contains(cm.getResource())) { if (cm.getStateTransition().isRightUnary()) { - update.addAnnotation(new Annotation("PUT")); + isPut = true; } else { - update.addAnnotation(new Annotation("POST")); + isPut = false; } } } - if (re.getDestination().getIndegree() > 1 - || (re.getDestination().getIndegree() == 1 && ch.getInputChannelMembers().iterator().next().getStateTransition().isRightPartial())) { + if (isRestAPI) { + if (isPut) { + update.addAnnotation(new Annotation("PUT")); + } else { + update.addAnnotation(new Annotation("POST")); + } + } + // Calculate in-degree of the destination resource. + Set inResources = new HashSet<>(); + for (ResourceNode rn: graph.getResourceNodes(out.getResource().getResourceHierarchy())) { + // ResourceNodes that have the same ResourceHierarchy. + for (Edge chToRes2: rn.getInEdges()) { + for (Edge resToCh2: chToRes2.getSource().getInEdges()) { + inResources.add(((ResourceNode) resToCh2.getSource()).getResourceHierarchy()); + } + } + } + int inDegree = inResources.size(); + if (inDegree > 1 + || (inDegree == 1 && ch.getInputChannelMembers().iterator().next().getStateTransition().isRightPartial())) { // Declare a field to cache the state of the source resource in the type of the destination resource. ResourcePath cacheRes = ((ResourceNode) re.getSource()).getOutSideResource(); FieldDeclaration cacheField = new FieldDeclaration(cacheRes.getResourceStateType(), srcName, getInitializer(cacheRes)); @@ -595,9 +632,9 @@ // No component is created for this resource. fields.add(new AbstractMap.SimpleEntry<>(resourceNode.getParent().getResourceHierarchy(), cacheField)); } - if (re.getDestination().getIndegree() > 1) { + if (inDegree > 1) { // For each source resource, a child resource is defined in the destination resource so that its state can be updated separately. - update.addAnnotation(new Annotation("Path", "\"/" + srcName + "\"")); + if (isRestAPI) update.addAnnotation(new Annotation("Path", "\"/" + srcName + "\"")); } } if (component != null) { @@ -615,6 +652,41 @@ nameToMethod.put(updateMethodName, update); } } + if (hasRestAPI && !isRestAPI) { + // Declare an update accessor method in the type of root resource. + String updateMethodName = update.getName(); + vars = new ArrayList<>(); + String resourcePath = getUpdateAccessorResourcePathAndPathParams(out.getResource(), vars); + param = new VariableDeclaration(srcType, srcName); + param.addAnnotation(new Annotation("FormParam", "\"" + srcName + "\"")); + vars.add(param); + for (ResourcePath refRes: ((ChannelNode) re.getDestination()).getChannel().getReferenceResources()) { + if (!refRes.equals(resourceNode.getOutSideResource())) { + param = new VariableDeclaration(refRes.getResourceStateType(), refRes.getResourceName()); + param.addAnnotation(new Annotation("FormParam", "\"" + refRes.getResourceName() + "\"")); + vars.add(param); + } + } + MethodDeclaration updateAccessor = new MethodDeclaration(updateMethodName, false, typeVoid, vars); + if (isPut) { + updateAccessor.addAnnotation(new Annotation("PUT")); + } else { + updateAccessor.addAnnotation(new Annotation("POST")); + } + if (inDegree > 1) { + // For each source resource, a child resource is defined in the destination resource so that its state can be updated separately. + resourcePath += "/" + toVariableName(srcResName); + } + updateAccessor.addAnnotation(new Annotation("Path", "\"" + resourcePath + "\"")); + Map nameToMethod = updates.get(resourceNode.getResourceHierarchy().getRoot()); + if (nameToMethod == null) { + nameToMethod = new HashMap<>(); + updates.put(resourceNode.getResourceHierarchy().getRoot(), nameToMethod); + } + if (nameToMethod.get(updateMethodName) == null) { + nameToMethod.put(updateMethodName, updateAccessor); + } + } } } } @@ -951,6 +1023,30 @@ } return resPath.getResourceHierarchy().toResourcePath(params); } + + private static String getUpdateAccessorResourcePathAndPathParams(ResourcePath resPath, ArrayList rootParams) { + int v = 1; + List params = new ArrayList<>(); + for (Expression pathParam: resPath.getPathParams()) { + if (pathParam instanceof Variable) { + Variable var = (Variable) pathParam; + String paramName = var.getName(); + params.add("{" + paramName + "}"); + VariableDeclaration param = new VariableDeclaration(var.getType(), paramName); + param.addAnnotation(new Annotation("PathParam", "\"" + paramName + "\"")); + rootParams.add(param); + } else if (pathParam instanceof Term) { + Term var = (Term) pathParam; + String paramName = "v" + v; + params.add("{" + paramName + "}"); + VariableDeclaration param = new VariableDeclaration(var.getType(), paramName); + param.addAnnotation(new Annotation("PathParam", "\"" + paramName + "\"")); + rootParams.add(param); + } + v++; + } + return resPath.getResourceHierarchy().toResourcePath(params); + } private static String getInputMethodResourcePathAndPathParams(ResourcePath resPath, ArrayList resInputParams, ArrayList rootInputParams) { diff --git a/AlgebraicDataflowArchitectureModel/src/generators/JerseyMethodBodyGenerator.java b/AlgebraicDataflowArchitectureModel/src/generators/JerseyMethodBodyGenerator.java index 8f86fc5..352e5ba 100644 --- a/AlgebraicDataflowArchitectureModel/src/generators/JerseyMethodBodyGenerator.java +++ b/AlgebraicDataflowArchitectureModel/src/generators/JerseyMethodBodyGenerator.java @@ -184,77 +184,119 @@ } } } - if (resToCh.getDestination().getIndegree() > 1 - || (resToCh.getDestination().getIndegree() == 1 && ch.getInputChannelMembers().iterator().next().getStateTransition().isRightPartial())) { + // Calculate in-degree of the destination resource. + Set inResources = new HashSet<>(); + for (ResourceNode rn: graph.getResourceNodes(out.getResource().getResourceHierarchy())) { + // ResourceNodes that have the same ResourceHierarchy. + for (Edge chToRes2: rn.getInEdges()) { + for (Edge resToCh2: chToRes2.getSource().getInEdges()) { + inResources.add(((ResourceNode) resToCh2.getSource()).getResourceHierarchy()); + } + } + } + int inDegree = inResources.size(); + if (inDegree > 1 + || (inDegree == 1 && ch.getInputChannelMembers().iterator().next().getStateTransition().isRightPartial())) { // update a cache of src side resource (when incoming edges are multiple) String cacheStatement = "this." + JerseyCodeGenerator.toVariableName(srcResourceName) + " = " + JerseyCodeGenerator.toVariableName(srcResourceName) + ";"; if (update.getBody() == null || !update.getBody().getStatements().contains(cacheStatement)) { update.addStatement(cacheStatement); - } - } - // to convert a json param to a tuple, pair or map object. - for (VariableDeclaration param: update.getParameters()) { - Type paramType = param.getType(); - String paramName = param.getName(); - String paramConverter = ""; - if (DataConstraintModel.typeList.isAncestorOf(paramType) && paramType != DataConstraintModel.typeList) { - Type compType = TypeInference.getListComponentType(paramType); - if (DataConstraintModel.typeTuple.isAncestorOf(compType)) { - param.setType(DataConstraintModel.typeListStr); - param.setName(paramName + "_json"); - paramConverter += paramType.getInterfaceTypeName() + " " + paramName + " = new " + paramType.getImplementationTypeName() + "();\n"; - paramConverter += "for (String str: " + param.getName() + ") {\n"; - String mapTypeName = convertFromEntryToMapType(compType); - paramConverter += "\t" + mapTypeName + " i = new ObjectMapper().readValue(str, HashMap.class);\n"; - paramConverter += "\t" + paramName + ".add(" + getCodeForConversionFromMapToTuple(compType, "i") + ");\n"; - paramConverter += "}"; - update.addThrow("JsonProcessingException"); - } else if (DataConstraintModel.typePair.isAncestorOf(compType)) { - param.setType(DataConstraintModel.typeListStr); - param.setName(paramName + "_json"); - paramConverter += paramType.getInterfaceTypeName() + " " + paramName + " = new " + paramType.getImplementationTypeName() + "();\n"; - paramConverter += "for (String str: " + param.getName() + ") {\n"; - String mapTypeName = convertFromEntryToMapType(compType); - paramConverter += "\t" + mapTypeName + " i = new ObjectMapper().readValue(str, HashMap.class);\n"; - paramConverter += "\t" + paramName + ".add(" + getCodeForConversionFromMapToPair(compType, "i") + ");\n"; - paramConverter += "}"; - update.addThrow("JsonProcessingException"); - } else if (DataConstraintModel.typeMap.isAncestorOf(compType)) { - param.setType(DataConstraintModel.typeListStr); - // To do. - } - } else if (DataConstraintModel.typeTuple.isAncestorOf(paramType)) { - param.setType(DataConstraintModel.typeString); - param.setName(paramName + "_json"); - paramConverter += paramType.getInterfaceTypeName() + " " + paramName + ";\n"; - paramConverter += "{\n"; - String mapTypeName = convertFromEntryToMapType(paramType); - paramConverter += "\t" + mapTypeName + " i = new ObjectMapper().readValue(" + paramName + "_json" + ", HashMap.class);\n"; - paramConverter += "\t" + paramName + " = " + getCodeForConversionFromMapToTuple(paramType, "i") + ";\n"; - paramConverter += "}"; - update.addThrow("JsonProcessingException"); - } else if (DataConstraintModel.typePair.isAncestorOf(paramType)) { - param.setType(DataConstraintModel.typeString); - param.setName(paramName + "_json"); - paramConverter += paramType.getInterfaceTypeName() + " " + paramName + ";\n"; - paramConverter += "{\n"; - String mapTypeName = convertFromEntryToMapType(paramType); - paramConverter += "\t" + mapTypeName + " i = new ObjectMapper().readValue(" + paramName + "_json" + ", HashMap.class);\n"; - paramConverter += "\t" + paramName + " = " + getCodeForConversionFromMapToPair(paramType, "i") + ";\n"; - paramConverter += "}"; - update.addThrow("JsonProcessingException"); - } else if (DataConstraintModel.typeMap.isAncestorOf(paramType)) { - param.setType(DataConstraintModel.typeString); - param.setName(paramName + "_json"); - paramConverter += paramType.getInterfaceTypeName() + " " + paramName + " = " + "new " + paramType.getImplementationTypeName() + "();\n"; - paramConverter += "{\n"; - String mapTypeName = convertFromEntryToMapType(paramType); - paramConverter += "\t" + mapTypeName + " i = new ObjectMapper().readValue(" + paramName + "_json" + ", HashMap.class);\n"; - paramConverter += "\t" + getCodeForConversionFromMapToMap(paramType, "i", paramName) + "\n"; - paramConverter += "}"; - update.addThrow("JsonProcessingException"); } - if (paramConverter.length() > 0) update.addFirstStatement(paramConverter); + } + // For a post/put REST API. + if (outsideOutputResource + || (in.getResource().getCommonPrefix(out.getResource()) == null && JerseyCodeGenerator.differentTreesAsDifferentServices)) { + // Inter-services + if (dst.getResourceHierarchy().getParent() != null) { + // If not a root resource. + TypeDeclaration rootComponent = componentMap.get(JerseyCodeGenerator.getComponentName(dst.getResourceHierarchy().getRoot())); + MethodDeclaration update2 = update; + update = getMethod(rootComponent, update2.getName()); // get the accessor to the update method. + // To make the accessor call the update method. + Expression resExp = JerseyCodeGenerator.pullAccessor.getDirectStateAccessorFor(out.getResource(), out.getResource().getRoot()); + String args = ""; + String delimiter = ""; + if (resExp instanceof Term) { + // to access the parent + if (((Term) resExp).getChildren().size() > 1 && ((Term) resExp).getChild(1) instanceof Variable) { + args += delimiter + ((Variable)((Term) resExp).getChild(1)).getName(); + delimiter = ", "; + } + resExp = ((Term) resExp).getChild(0); + } + String resourceAccess = resExp.toImplementation(new String[] {null}); + for (VariableDeclaration var: update2.getParameters()) { + args += delimiter + var.getName(); + delimiter = ", "; + } + update.addStatement(resourceAccess + "." + update2.getName() + "(" + args + ");"); + } + // to convert a json param to a tuple, pair or map object. + for (VariableDeclaration param: update.getParameters()) { + Type paramType = param.getType(); + String paramName = param.getName(); + String paramConverter = ""; + if (DataConstraintModel.typeList.isAncestorOf(paramType) && paramType != DataConstraintModel.typeList) { + Type compType = TypeInference.getListComponentType(paramType); + if (DataConstraintModel.typeTuple.isAncestorOf(compType)) { + param.setType(DataConstraintModel.typeListStr); + param.setName(paramName + "_json"); + paramConverter += paramType.getInterfaceTypeName() + " " + paramName + " = new " + paramType.getImplementationTypeName() + "();\n"; + paramConverter += "for (String str: " + param.getName() + ") {\n"; + String mapTypeName = convertFromEntryToMapType(compType); + paramConverter += "\t" + mapTypeName + " i = new ObjectMapper().readValue(str, HashMap.class);\n"; + paramConverter += "\t" + paramName + ".add(" + getCodeForConversionFromMapToTuple(compType, "i") + ");\n"; + paramConverter += "}"; + update.addThrow("JsonProcessingException"); + } else if (DataConstraintModel.typePair.isAncestorOf(compType)) { + param.setType(DataConstraintModel.typeListStr); + param.setName(paramName + "_json"); + paramConverter += paramType.getInterfaceTypeName() + " " + paramName + " = new " + paramType.getImplementationTypeName() + "();\n"; + paramConverter += "for (String str: " + param.getName() + ") {\n"; + String mapTypeName = convertFromEntryToMapType(compType); + paramConverter += "\t" + mapTypeName + " i = new ObjectMapper().readValue(str, HashMap.class);\n"; + paramConverter += "\t" + paramName + ".add(" + getCodeForConversionFromMapToPair(compType, "i") + ");\n"; + paramConverter += "}"; + update.addThrow("JsonProcessingException"); + } else if (DataConstraintModel.typeMap.isAncestorOf(compType)) { + param.setType(DataConstraintModel.typeListStr); + // To do. + } + } else if (DataConstraintModel.typeTuple.isAncestorOf(paramType)) { + param.setType(DataConstraintModel.typeString); + param.setName(paramName + "_json"); + paramConverter += paramType.getInterfaceTypeName() + " " + paramName + ";\n"; + paramConverter += "{\n"; + String mapTypeName = convertFromEntryToMapType(paramType); + paramConverter += "\t" + mapTypeName + " i = new ObjectMapper().readValue(" + paramName + "_json" + ", HashMap.class);\n"; + paramConverter += "\t" + paramName + " = " + getCodeForConversionFromMapToTuple(paramType, "i") + ";\n"; + paramConverter += "}"; + update.addThrow("JsonProcessingException"); + } else if (DataConstraintModel.typePair.isAncestorOf(paramType)) { + param.setType(DataConstraintModel.typeString); + param.setName(paramName + "_json"); + paramConverter += paramType.getInterfaceTypeName() + " " + paramName + ";\n"; + paramConverter += "{\n"; + String mapTypeName = convertFromEntryToMapType(paramType); + paramConverter += "\t" + mapTypeName + " i = new ObjectMapper().readValue(" + paramName + "_json" + ", HashMap.class);\n"; + paramConverter += "\t" + paramName + " = " + getCodeForConversionFromMapToPair(paramType, "i") + ";\n"; + paramConverter += "}"; + update.addThrow("JsonProcessingException"); + } else if (DataConstraintModel.typeMap.isAncestorOf(paramType)) { + param.setType(DataConstraintModel.typeString); + param.setName(paramName + "_json"); + paramConverter += paramType.getInterfaceTypeName() + " " + paramName + " = " + "new " + paramType.getImplementationTypeName() + "();\n"; + paramConverter += "{\n"; + String mapTypeName = convertFromEntryToMapType(paramType); + paramConverter += "\t" + mapTypeName + " i = new ObjectMapper().readValue(" + paramName + "_json" + ", HashMap.class);\n"; + paramConverter += "\t" + getCodeForConversionFromMapToMap(paramType, "i", paramName) + "\n"; + paramConverter += "}"; + update.addThrow("JsonProcessingException"); + } + if (paramConverter.length() > 0 && !update.getBody().getStatements().contains(paramConverter)) { + update.addFirstStatement(paramConverter); + } + } } if (((StoreAttribute) dst.getAttribute()).isStored()) { // returns the state stored in a field. @@ -350,18 +392,23 @@ } params.add(0, new AbstractMap.SimpleEntry<>(src.getResourceStateType(), new AbstractMap.SimpleEntry<>(JerseyCodeGenerator.toVariableName(srcResourceName), srcFieldName))); - if (outsideOutputResource) { + if (outsideOutputResource || (in.getResource().getCommonPrefix(dstRes) == null && JerseyCodeGenerator.differentTreesAsDifferentServices)) { + // Inter-servces String[] sideEffects = new String[] {""}; List pathParams = new ArrayList<>(); for (Expression pathExp: dstRes.getPathParams()) { pathParams.add("\" + " + pathExp.toImplementation(sideEffects) + " + \""); } + String srcResName = JerseyCodeGenerator.toVariableName(srcResourceName); + if (inDegree <= 1) { + srcResName = null; + } if (!chainedCalls.contains(srcUpdate)) { // The first call to an update method in this method srcUpdate.addStatement(getHttpMethodParamsStatement(srcComponent.getTypeName(), params, true)); srcUpdate.addStatement("String result = " + getHttpMethodCallStatement(baseURL, dstRes.getResourceHierarchy().toResourcePath(pathParams), - JerseyCodeGenerator.toVariableName(srcResourceName), + srcResName, httpMethod)); chainedCalls.add(srcUpdate); } else { @@ -369,11 +416,12 @@ srcUpdate.addStatement(getHttpMethodParamsStatement(srcComponent.getTypeName(), params, false)); srcUpdate.addStatement("result = " + getHttpMethodCallStatement(baseURL, dstRes.getResourceHierarchy().toResourcePath(pathParams), - JerseyCodeGenerator.toVariableName(srcResourceName), + srcResName, httpMethod)); } srcUpdate.addThrow("JsonProcessingException"); } else { + // Inner-service String updateMethodName = null; if (JerseyCodeGenerator.generatesComponent(dst.getResourceHierarchy())) { updateMethodName = "updateFrom" + srcResourceName; @@ -442,18 +490,23 @@ } params.add(0, new AbstractMap.SimpleEntry<>(src.getResourceStateType(), new AbstractMap.SimpleEntry<>(JerseyCodeGenerator.toVariableName(srcResourceName), srcFieldName))); - if (outsideOutputResource) { + if (outsideOutputResource || (in.getResource().getCommonPrefix(dstRes) == null && JerseyCodeGenerator.differentTreesAsDifferentServices)) { + // Inter-services String[] sideEffects = new String[] {""}; List pathParams = new ArrayList<>(); for (Expression pathExp: dstRes.getPathParams()) { pathParams.add("\" + " + pathExp.toImplementation(sideEffects) + " + \""); } + String srcResName = JerseyCodeGenerator.toVariableName(srcResourceName); + if (inDegree <= 1) { + srcResName = null; + } if (!chainedCalls.contains(srcInput)) { // First call to an update method in this method srcInput.addStatement(getHttpMethodParamsStatement(srcComponent.getTypeName(), params, true)); srcInput.addStatement("String result = " + getHttpMethodCallStatement(baseURL, dstRes.getResourceHierarchy().toResourcePath(pathParams), - JerseyCodeGenerator.toVariableName(srcResourceName), + srcResName, httpMethod)); chainedCalls.add(srcInput); } else { @@ -461,11 +514,12 @@ srcInput.addStatement(getHttpMethodParamsStatement(srcComponent.getTypeName(), params, false)); srcInput.addStatement("result = " + getHttpMethodCallStatement(baseURL, dstRes.getResourceHierarchy().toResourcePath(pathParams), - JerseyCodeGenerator.toVariableName(srcResourceName), + srcResName, httpMethod)); } srcInput.addThrow("JsonProcessingException"); } else { + // Inner-service String updateMethodName = null; if (JerseyCodeGenerator.generatesComponent(dst.getResourceHierarchy())) { updateMethodName = "updateFrom" + srcResourceName; diff --git a/AlgebraicDataflowArchitectureModel/src/models/dataFlowModel/DataFlowGraph.java b/AlgebraicDataflowArchitectureModel/src/models/dataFlowModel/DataFlowGraph.java index 6be124c..53ea105 100644 --- a/AlgebraicDataflowArchitectureModel/src/models/dataFlowModel/DataFlowGraph.java +++ b/AlgebraicDataflowArchitectureModel/src/models/dataFlowModel/DataFlowGraph.java @@ -1,5 +1,6 @@ package models.dataFlowModel; +import java.util.ArrayList; import java.util.Collection; import java.util.HashMap; import java.util.HashSet; @@ -7,6 +8,7 @@ import java.util.Set; import models.DirectedGraph; +import models.dataConstraintModel.ResourceHierarchy; import models.dataConstraintModel.ResourcePath; public class DataFlowGraph extends DirectedGraph { @@ -81,6 +83,17 @@ return resourceNodeMap.values(); } + public Collection getResourceNodes(ResourceHierarchy resourceHierarchy) { + Collection resourceNodes = new ArrayList<>(); + for (ResourceNode rn: resourceNodeMap.values()) { + if (rn.getResourceHierarchy() == resourceHierarchy) { + resourceNodes.add(rn); + } + } + return resourceNodes; + } + + public Collection getChannelNodes() { return channelNodeMap.values(); }