diff --git a/AlgebraicDataflowArchitectureModel/src/generators/CodeGeneratorFromDataFlowGraph.java b/AlgebraicDataflowArchitectureModel/src/generators/CodeGeneratorFromDataFlowGraph.java index 5c7a65b..3f8105c 100644 --- a/AlgebraicDataflowArchitectureModel/src/generators/CodeGeneratorFromDataFlowGraph.java +++ b/AlgebraicDataflowArchitectureModel/src/generators/CodeGeneratorFromDataFlowGraph.java @@ -973,28 +973,39 @@ DataTransferChannel ch2 = ((ChannelNode) resToCh2.getDestination()).getChannel(); // Check if the input resource is outside of the channel scope. boolean outsideInputResource2 = false; + ChannelMember in = null; Set outsideInputMembers2 = new HashSet<>(); for (ChannelMember cm: ch2.getInputChannelMembers()) { - if (cm.isOutside()) { - outsideInputMembers2.add(cm); - if (cm.getResource().equals(resourceNode.getOutSideResource())) { + if (cm.getResource().equals(resourceNode.getOutSideResource())) { + if (cm.isOutside()) { outsideInputResource2 = true; // Regarded as pull transfer. } + in = cm; + } + if (cm.isOutside()) { + outsideInputMembers2.add(cm); } } - 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; - } + for (Edge chToRes2: resToCh2.getDestination().getOutEdges()) { + ResourceNode dstNode = ((ResourceNode) chToRes2.getDestination()); + // Check if the output resource is outside of the channel scope. + boolean outsideOutputResource2 = false; + for (ChannelMember cm: ch2.getOutputChannelMembers()) { + if (dstNode.getInSideResources().contains(cm.getResource()) && cm.isOutside()) { + outsideOutputResource2 = true; } + } + if ((((PushPullAttribute) dOut.getAttribute()).getOptions().get(0) == PushPullValue.PUSH && !outsideInputResource2) || outsideOutputResource2) { + // PUSH transfer Map> referredResources = new HashMap<>(); List params = new ArrayList<>(); - params.add(langSpec.getFieldAccessor(fieldOfResourceState)); + ResourceHierarchy srcRes2 = resourceNode.getResourceHierarchy(); + if (generatesComponent(srcRes2)) { + params.add(langSpec.getFieldAccessor(fieldOfResourceState)); + } else { + params.add(langSpec.getFieldAccessor(langSpec.toVariableName(srcRes2.getResourceName()))); + srcRes2 = srcRes2.getParent(); + } Set referredSet = referredResources.get(update); for (ChannelMember rc: ch2.getReferenceChannelMembers()) { // to get the value of reference member. @@ -1016,12 +1027,8 @@ params.add(refVarName); } } - ResourceHierarchy srcRes2 = resourceNode.getResourceHierarchy(); - if (!generatesComponent(srcRes2)) { - srcRes2 = srcRes2.getParent(); - } String updateMethodName = null; - ResourceHierarchy dstRes = ((ResourceNode) chToRes2.getDestination()).getResourceHierarchy(); + ResourceHierarchy dstRes = dstNode.getResourceHierarchy(); if (!generatesComponent(dstRes)) { updateMethodName = updateMethodPrefix + getComponentName(dstRes, langSpec) + from + resComponentName; dstRes = dstRes.getParent(); @@ -1029,12 +1036,19 @@ updateMethodName = updateMethodPrefix + from + resComponentName; } String dstCompName = langSpec.toVariableName(getComponentName(dstRes, langSpec)); - if (srcRes2 != dstRes) { + if (!outsideOutputResource2) { + // The destination resource is not outside. + if (srcRes2 != dstRes) { + update.addStatement(langSpec.getMethodInvocation(langSpec.getFieldAccessor(dstCompName), updateMethodName, params) + + langSpec.getStatementDelimiter()); // this.dst.updateDstFromSrc(value, refParams); + } else { + update.addStatement(langSpec.getMethodInvocation(updateMethodName, params) + + langSpec.getStatementDelimiter()); // this.updateDstFromSrc(value, refParams); + } + } else { + // Use the reference field to refer to outside destination resource. update.addStatement(langSpec.getMethodInvocation(langSpec.getFieldAccessor(dstCompName), updateMethodName, params) + langSpec.getStatementDelimiter()); // this.dst.updateDstFromSrc(value, refParams); - } else { - update.addStatement(langSpec.getMethodInvocation(updateMethodName, params) - + langSpec.getStatementDelimiter()); // this.updateDstFromSrc(value, refParams); } } } @@ -1419,29 +1433,41 @@ for (Edge resToCh: resourceNode.getOutEdges()) { DataFlowEdge dOut = (DataFlowEdge) resToCh; DataTransferChannel ch2 = ((ChannelNode) resToCh.getDestination()).getChannel(); + // Check if the input resource is outside of the channel scope. boolean outsideInputResource2 = false; + ChannelMember in = null; Set outsideInputMembers2 = new HashSet<>(); for (ChannelMember cm: ch2.getInputChannelMembers()) { - if (cm.isOutside()) { - outsideInputMembers2.add(cm); - if (cm.getResource().equals(resourceNode.getOutSideResource())) { + if (cm.getResource().equals(resourceNode.getOutSideResource())) { + if (cm.isOutside()) { outsideInputResource2 = true; // Regarded as pull transfer. } + in = cm; + } + if (cm.isOutside()) { + outsideInputMembers2.add(cm); } } - 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; - } + for (Edge chToRes: resToCh.getDestination().getOutEdges()) { + ResourceNode dstNode = ((ResourceNode) chToRes.getDestination()); + // Check if the output resource is outside of the channel scope. + boolean outsideOutputResource2 = false; + for (ChannelMember cm: ch2.getOutputChannelMembers()) { + if (dstNode.getInSideResources().contains(cm.getResource()) && cm.isOutside()) { + outsideOutputResource2 = true; } + } + if ((((PushPullAttribute) dOut.getAttribute()).getOptions().get(0) == PushPullValue.PUSH && !outsideInputResource2) || outsideOutputResource2) { + // PUSH transfer Map> referredResources = new HashMap<>(); List params = new ArrayList<>(); - params.add(langSpec.getFieldAccessor(fieldOfResourceState)); + ResourceHierarchy srcRes = resourceNode.getResourceHierarchy(); + if (generatesComponent(srcRes)) { + params.add(langSpec.getFieldAccessor(fieldOfResourceState)); + } else { + params.add(langSpec.getFieldAccessor(langSpec.toVariableName(srcRes.getResourceName()))); + srcRes = srcRes.getParent(); + } Set referredSet = referredResources.get(input); for (ChannelMember rc: ch2.getReferenceChannelMembers()) { // to get the value of reference member. @@ -1463,12 +1489,8 @@ params.add(refVarName); } } - ResourceHierarchy srcRes = resourceNode.getResourceHierarchy(); - if (!generatesComponent(srcRes)) { - srcRes = srcRes.getParent(); - } String updateMethodName = null; - ResourceHierarchy dstRes = ((ResourceNode) chToRes.getDestination()).getResourceHierarchy(); + ResourceHierarchy dstRes = dstNode.getResourceHierarchy(); if (!generatesComponent(dstRes)) { updateMethodName = updateMethodPrefix + getComponentName(dstRes, langSpec) + from + resComponentName; dstRes = dstRes.getParent(); @@ -1476,12 +1498,19 @@ updateMethodName = updateMethodPrefix + from + resComponentName; } String dstCompName = langSpec.toVariableName(getComponentName(dstRes, langSpec)); - if (srcRes != dstRes) { + if (!outsideOutputResource2) { + // The destination resource is not outside. + if (srcRes != dstRes) { + input.addStatement(langSpec.getMethodInvocation(langSpec.getFieldAccessor(dstCompName), updateMethodName, params) + + langSpec.getStatementDelimiter()); // this.dst.updateDstFromSrc(value, refParams); + } else { + input.addStatement(langSpec.getMethodInvocation(updateMethodName, params) + + langSpec.getStatementDelimiter()); // this.updateDstFromSrc(value, refParams); + } + } else { + // Use the reference field to refer to outside destination resource. input.addStatement(langSpec.getMethodInvocation(langSpec.getFieldAccessor(dstCompName), updateMethodName, params) + langSpec.getStatementDelimiter()); // this.dst.updateDstFromSrc(value, refParams); - } else { - input.addStatement(langSpec.getMethodInvocation(updateMethodName, params) - + langSpec.getStatementDelimiter()); // this.updateDstFromSrc(value, refParams); } } } diff --git a/AlgebraicDataflowArchitectureModel/src/generators/JavaMethodBodyGenerator.java b/AlgebraicDataflowArchitectureModel/src/generators/JavaMethodBodyGenerator.java index 8e8466e..9cb1c6c 100644 --- a/AlgebraicDataflowArchitectureModel/src/generators/JavaMethodBodyGenerator.java +++ b/AlgebraicDataflowArchitectureModel/src/generators/JavaMethodBodyGenerator.java @@ -74,20 +74,14 @@ // 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()) { + if (cm.getResource().equals(src.getOutSideResource()) && cm.isOutside()) { outsideInputResource = true; // Regarded as pull transfer. break; } } // Check if the output resource is outside of the channel scope. - boolean outsideOutputResource = false; - for (ChannelMember cm: ch.getOutputChannelMembers()) { - if (cm.getResource().getResourceHierarchy().equals(dst.getResourceHierarchy()) && cm.isOutside()) { - outsideOutputResource = true; // Regarded as push transfer. - break; - } - } - if (pushPull.getOptions().get(0) == PushPullValue.PUSH && !outsideInputResource) { + boolean outsideOutputResource = out.isOutside(); + if ((pushPull.getOptions().get(0) == PushPullValue.PUSH && !outsideInputResource) || outsideOutputResource) { // for push data transfer MethodDeclaration update = null; if (dstComponent == null) { @@ -267,10 +261,20 @@ } else { updateMethodName = "update" + dstResourceName + "From" + srcResourceName; } - if (srcComponent != dstComponent) { - srcUpdate.addStatement("this." + JavaCodeGenerator.toVariableName(dstComponent.getTypeName()) + "." + updateMethodName + "(value" + refParams + ");"); + String srcFieldName = "value"; + if (!JavaCodeGenerator.generatesComponent(src.getResourceHierarchy())) { + srcFieldName = JavaCodeGenerator.toVariableName(srcResourceName); + } + if (!outsideOutputResource) { + // The destination resource is not outside. + if (srcComponent != dstComponent) { + srcUpdate.addStatement("this." + JavaCodeGenerator.toVariableName(dstComponent.getTypeName()) + "." + updateMethodName + "(" + srcFieldName + refParams + ");"); + } else { + srcUpdate.addStatement("this." + updateMethodName + "(" + srcFieldName + refParams + ");"); + } } else { - srcUpdate.addStatement("this." + updateMethodName + "(value" + refParams + ");"); + // Use the reference field to refer to outside destination resource. + srcUpdate.addStatement("this." + JavaCodeGenerator.toVariableName(dstComponent.getTypeName()) + "." + updateMethodName + "(" + srcFieldName + refParams + ");"); } } for (MethodDeclaration srcInput: getInputMethods(srcComponent, src, model)) { @@ -302,10 +306,20 @@ } else { updateMethodName = "update" + dstResourceName + "From" + srcResourceName; } - if (srcComponent != dstComponent) { - srcInput.addStatement("this." + JavaCodeGenerator.toVariableName(dstComponent.getTypeName()) + "." + updateMethodName + "(value" + refParams + ");"); + String srcFieldName = "value"; + if (!JavaCodeGenerator.generatesComponent(src.getResourceHierarchy())) { + srcFieldName = JavaCodeGenerator.toVariableName(srcResourceName); + } + if (!outsideOutputResource) { + // The destination resource is not outside. + if (srcComponent != dstComponent) { + srcInput.addStatement("this." + JavaCodeGenerator.toVariableName(dstComponent.getTypeName()) + "." + updateMethodName + "(" + srcFieldName + refParams + ");"); + } else { + srcInput.addStatement("this." + updateMethodName + "(" + srcFieldName + refParams + ");"); + } } else { - srcInput.addStatement("this." + updateMethodName + "(value" + refParams + ");"); + // Use the reference field to refer to outside destination resource. + srcInput.addStatement("this." + JavaCodeGenerator.toVariableName(dstComponent.getTypeName()) + "." + updateMethodName + "(" + srcFieldName + refParams + ");"); } } } else if ((pushPull.getOptions().get(0) != PushPullValue.PUSH && !outsideOutputResource) || outsideInputResource) { diff --git a/AlgebraicDataflowArchitectureModel/src/generators/JerseyMethodBodyGenerator.java b/AlgebraicDataflowArchitectureModel/src/generators/JerseyMethodBodyGenerator.java index 4254cab..8f86fc5 100644 --- a/AlgebraicDataflowArchitectureModel/src/generators/JerseyMethodBodyGenerator.java +++ b/AlgebraicDataflowArchitectureModel/src/generators/JerseyMethodBodyGenerator.java @@ -79,21 +79,19 @@ if (dst.getInSideResources().contains(out.getResource())) { // Check if the input resource is outside of the channel scope. boolean outsideInputResource = false; + ChannelMember in = null; for (ChannelMember cm: ch.getInputChannelMembers()) { - if (cm.getResource().getResourceHierarchy().equals(src.getResourceHierarchy()) && cm.isOutside()) { - outsideInputResource = true; // Regarded as pull transfer. - break; + if (cm.getResource().equals(src.getOutSideResource())) { + in = cm; + if (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) { + boolean outsideOutputResource = out.isOutside(); + if ((pushPull.getOptions().get(0) == PushPullValue.PUSH && !outsideInputResource) || outsideOutputResource) { // for push data transfer MethodDeclaration update = null; if (dstComponent == null) { @@ -115,14 +113,14 @@ DataTransferChannel ch2 = ((ChannelNode) chToRes2.getSource()).getChannel(); for (Edge resToCh2: chToRes2.getSource().getInEdges()) { DataFlowEdge dIn = (DataFlowEdge) resToCh2; - ChannelMember in = null; + ChannelMember in2 = null; for (ChannelMember cm: ch2.getInputChannelMembers()) { if (cm.getResource().equals(((ResourceNode) dIn.getSource()).getOutSideResource())) { - in = cm; + in2 = cm; break; } } - inputResourceToStateAccessor.put(in, JerseyCodeGenerator.pushAccessor); + inputResourceToStateAccessor.put(in2, JerseyCodeGenerator.pushAccessor); } } for (ChannelMember c: ch.getReferenceChannelMembers()) { @@ -321,36 +319,82 @@ Type refResourceType = ref.getResourceStateType(); if (!referredSet.contains(ref)) { referredSet.add(ref); - generatePullDataTransfer(srcUpdate, refResourceName, refResourceName, refResourceType); + String[] sideEffects = new String[] {""}; + if (rc.isOutside()) { + List pathParams = new ArrayList<>(); + for (Expression pathExp: ref.getPathParams()) { + pathParams.add("\" + " + pathExp.toImplementation(sideEffects) + " + \""); + } + generatePullDataTransfer(srcUpdate, refResourceName, ref.getResourceHierarchy().toResourcePath(pathParams), refResourceType); + } else { + ResourcePath srcRes = in.getResource(); + if (!JerseyCodeGenerator.generatesComponent(srcRes.getResourceHierarchy())) { + srcRes = srcRes.getParent(); + } + Expression refGetter = JerseyCodeGenerator.pullAccessor.getDirectStateAccessorFor(ref, srcRes); + String refExp = refGetter.toImplementation(sideEffects); + String refTypeName = ref.getResourceStateType().getInterfaceTypeName(); + srcUpdate.addFirstStatement(sideEffects[0] + refTypeName + " " + refResourceName + " = " + refExp + ";"); + } } // Value of a reference side resource. params.add(new AbstractMap.SimpleEntry<>(refResourceType, new AbstractMap.SimpleEntry<>(refResourceName, refResourceName))); } } } - if (!chainedCalls.contains(srcUpdate)) { - // 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<>(JerseyCodeGenerator.toVariableName(srcResourceName), "this.value"))); - srcUpdate.addStatement(getHttpMethodParamsStatement(srcComponent.getTypeName(), params, true)); - srcUpdate.addStatement("String result = " + getHttpMethodCallStatement(baseURL, - JerseyCodeGenerator.toVariableName(dstResourceName), - JerseyCodeGenerator.toVariableName(srcResourceName), - 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<>(JerseyCodeGenerator.toVariableName(srcResourceName), "this.value"))); - srcUpdate.addStatement(getHttpMethodParamsStatement(srcComponent.getTypeName(), params, false)); - srcUpdate.addStatement("result = " + getHttpMethodCallStatement(baseURL, - JerseyCodeGenerator.toVariableName(dstResourceName), - JerseyCodeGenerator.toVariableName(srcResourceName), - httpMethod)); + ResourcePath dstRes = out.getResource(); + // Value of the source side (input side) resource. + String srcFieldName = "this.value"; + if (!JerseyCodeGenerator.generatesComponent(src.getResourceHierarchy())) { + srcFieldName = JerseyCodeGenerator.toVariableName(srcResourceName); } - srcUpdate.addThrow("JsonProcessingException"); + params.add(0, new AbstractMap.SimpleEntry<>(src.getResourceStateType(), + new AbstractMap.SimpleEntry<>(JerseyCodeGenerator.toVariableName(srcResourceName), srcFieldName))); + if (outsideOutputResource) { + String[] sideEffects = new String[] {""}; + List pathParams = new ArrayList<>(); + for (Expression pathExp: dstRes.getPathParams()) { + pathParams.add("\" + " + pathExp.toImplementation(sideEffects) + " + \""); + } + 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), + httpMethod)); + chainedCalls.add(srcUpdate); + } else { + // After the second time of call to update methods in this method + srcUpdate.addStatement(getHttpMethodParamsStatement(srcComponent.getTypeName(), params, false)); + srcUpdate.addStatement("result = " + getHttpMethodCallStatement(baseURL, + dstRes.getResourceHierarchy().toResourcePath(pathParams), + JerseyCodeGenerator.toVariableName(srcResourceName), + httpMethod)); + } + srcUpdate.addThrow("JsonProcessingException"); + } else { + String updateMethodName = null; + if (JerseyCodeGenerator.generatesComponent(dst.getResourceHierarchy())) { + updateMethodName = "updateFrom" + srcResourceName; + } else { + updateMethodName = "update" + dstResourceName + "From" + srcResourceName; + } + String callParams = ""; + String delimiter = ""; + for (Map.Entry> paramEnt: params) { + callParams += delimiter + paramEnt.getValue().getValue(); + delimiter = ", "; + } + if (!chainedCalls.contains(srcUpdate)) { + // The first call to an update method in this method + srcUpdate.addStatement("String result = this." + JerseyCodeGenerator.toVariableName(dstResourceName) + "." + updateMethodName + "(" + callParams + ");"); + chainedCalls.add(srcUpdate); + } else { + // After the second time of call to update methods in this method + srcUpdate.addStatement("result = this." + JerseyCodeGenerator.toVariableName(dstResourceName) + "." + updateMethodName + "(" + callParams + ");"); + } + } } } for (MethodDeclaration srcInput: getInputMethods(srcComponent, src, model)) { @@ -368,35 +412,81 @@ Type refResourceType = ref.getResourceStateType(); if (!referredSet.contains(ref)) { referredSet.add(ref); - generatePullDataTransfer(srcInput, refResourceName, refResourceName, refResourceType); + String[] sideEffects = new String[] {""}; + if (rc.isOutside()) { + List pathParams = new ArrayList<>(); + for (Expression pathExp: ref.getPathParams()) { + pathParams.add("\" + " + pathExp.toImplementation(sideEffects) + " + \""); + } + generatePullDataTransfer(srcInput, refResourceName, ref.getResourceHierarchy().toResourcePath(pathParams), refResourceType); + } else { + ResourcePath srcRes = in.getResource(); + if (!JerseyCodeGenerator.generatesComponent(srcRes.getResourceHierarchy())) { + srcRes = srcRes.getParent(); + } + Expression refGetter = JerseyCodeGenerator.pullAccessor.getDirectStateAccessorFor(ref, srcRes); + String refExp = refGetter.toImplementation(sideEffects); + String refTypeName = ref.getResourceStateType().getInterfaceTypeName(); + srcInput.addFirstStatement(sideEffects[0] + refTypeName + " " + ref.getResourceName() + " = " + refExp + ";"); + } } // Value of a reference side resource. params.add(new AbstractMap.SimpleEntry<>(refResourceType, new AbstractMap.SimpleEntry<>(refResourceName, refResourceName))); } } - if (!chainedCalls.contains(srcInput)) { - // 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<>(JerseyCodeGenerator.toVariableName(srcResourceName), "this.value"))); - srcInput.addStatement(getHttpMethodParamsStatement(srcComponent.getTypeName(), params, true)); - srcInput.addStatement("String result = " + getHttpMethodCallStatement(baseURL, - JerseyCodeGenerator.toVariableName(dstResourceName), - JerseyCodeGenerator.toVariableName(srcResourceName), - 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<>(JerseyCodeGenerator.toVariableName(srcResourceName), "this.value"))); - srcInput.addStatement(getHttpMethodParamsStatement(srcComponent.getTypeName(), params, false)); - srcInput.addStatement("result = " + getHttpMethodCallStatement(baseURL, - JerseyCodeGenerator.toVariableName(dstResourceName), - JerseyCodeGenerator.toVariableName(srcResourceName), - httpMethod)); + ResourcePath dstRes = out.getResource(); + // Value of the source side (input side) resource. + String srcFieldName = "this.value"; + if (!JerseyCodeGenerator.generatesComponent(src.getResourceHierarchy())) { + srcFieldName = JerseyCodeGenerator.toVariableName(srcResourceName); } - srcInput.addThrow("JsonProcessingException"); + params.add(0, new AbstractMap.SimpleEntry<>(src.getResourceStateType(), + new AbstractMap.SimpleEntry<>(JerseyCodeGenerator.toVariableName(srcResourceName), srcFieldName))); + if (outsideOutputResource) { + String[] sideEffects = new String[] {""}; + List pathParams = new ArrayList<>(); + for (Expression pathExp: dstRes.getPathParams()) { + pathParams.add("\" + " + pathExp.toImplementation(sideEffects) + " + \""); + } + 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), + httpMethod)); + chainedCalls.add(srcInput); + } else { + // After the second time of call to update methods in this method + srcInput.addStatement(getHttpMethodParamsStatement(srcComponent.getTypeName(), params, false)); + srcInput.addStatement("result = " + getHttpMethodCallStatement(baseURL, + dstRes.getResourceHierarchy().toResourcePath(pathParams), + JerseyCodeGenerator.toVariableName(srcResourceName), + httpMethod)); + } + srcInput.addThrow("JsonProcessingException"); + } else { + String updateMethodName = null; + if (JerseyCodeGenerator.generatesComponent(dst.getResourceHierarchy())) { + updateMethodName = "updateFrom" + srcResourceName; + } else { + updateMethodName = "update" + dstResourceName + "From" + srcResourceName; + } + String callParams = ""; + String delimiter = ""; + for (Map.Entry> paramEnt: params) { + callParams += delimiter + paramEnt.getValue().getValue(); + delimiter = ", "; + } + if (!chainedCalls.contains(srcInput)) { + // The first call to an update method in this method + srcInput.addStatement("String result = this." + JerseyCodeGenerator.toVariableName(dstResourceName) + "." + updateMethodName + "(" + callParams + ");"); + chainedCalls.add(srcInput); + } else { + // After the second time of call to update methods in this method + srcInput.addStatement("result = this." + JerseyCodeGenerator.toVariableName(dstResourceName) + "." + updateMethodName + "(" + callParams + ");"); + } + } } } else if ((pushPull.getOptions().get(0) != PushPullValue.PUSH && !outsideOutputResource) || outsideInputResource) { // for pull (or push/pull) data transfer @@ -418,10 +508,26 @@ 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 (ChannelMember rc: ch.getReferenceChannelMembers()) { + ResourcePath refRes = rc.getResource(); + String refResourceName = refRes.getResourceName(); + Type refResourceType = refRes.getResourceStateType(); + if (rc.isOutside()) { + List pathParams = new ArrayList<>(); + for (Expression pathExp: refRes.getPathParams()) { + pathParams.add("\" + " + pathExp.toImplementation(sideEffects) + " + \""); + } + generatePullDataTransfer(getter, refResourceName, refRes.getResourceHierarchy().toResourcePath(pathParams), refResourceType); + } else { + ResourcePath dstRes = out.getResource(); + if (!JerseyCodeGenerator.generatesComponent(dstRes.getResourceHierarchy())) { + dstRes = dstRes.getParent(); + } + Expression refGetter = JerseyCodeGenerator.pullAccessor.getDirectStateAccessorFor(refRes, dstRes); + String refExp = refGetter.toImplementation(sideEffects); + String refTypeName = refResourceType.getInterfaceTypeName(); + getter.addFirstStatement(sideEffects[0] + refTypeName + " " + refResourceName + " = " + refExp + ";"); + } } for (Entry>> pathEnt: resourcePaths.entrySet()) { ChannelMember cm = pathEnt.getKey(); @@ -575,7 +681,23 @@ Type refResourceType = ref.getResourceStateType(); if (!referredSet.contains(ref)) { referredSet.add(ref); - generatePullDataTransfer(input, refResourceName, refResourceName, refResourceType); + String[] sideEffects = new String[] {""}; + if (rc.isOutside()) { + List pathParams = new ArrayList<>(); + for (Expression pathExp: ref.getPathParams()) { + pathParams.add("\" + " + pathExp.toImplementation(sideEffects) + " + \""); + } + generatePullDataTransfer(input, refResourceName, ref.getResourceHierarchy().toResourcePath(pathParams), refResourceType); + } else { + ResourcePath dstRes = out.getResource(); + if (!JerseyCodeGenerator.generatesComponent(dstRes.getResourceHierarchy())) { + dstRes = dstRes.getParent(); + } + Expression refGetter = JerseyCodeGenerator.pullAccessor.getDirectStateAccessorFor(ref, dstRes); + String refExp = refGetter.toImplementation(sideEffects); + String refTypeName = refResourceType.getInterfaceTypeName(); + input.addFirstStatement(sideEffects[0] + refTypeName + " " + refResourceName + " = " + refExp + ";"); + } } } }