diff --git a/AlgebraicDataflowArchitectureModel/src/generators/CodeGenerator.java b/AlgebraicDataflowArchitectureModel/src/generators/CodeGenerator.java index f4a867b..3ce6bb8 100644 --- a/AlgebraicDataflowArchitectureModel/src/generators/CodeGenerator.java +++ b/AlgebraicDataflowArchitectureModel/src/generators/CodeGenerator.java @@ -506,6 +506,26 @@ } return input; } + + + protected MethodDeclaration getMethod(TypeDeclaration component, String methodName, List params) { + for (MethodDeclaration m: component.getMethods()) { + if (m.getName().equals(methodName)) { + if (m.getParameters() == null && (params == null || params.size() == 0)) return m; + if (m.getParameters() != null && params != null && m.getParameters().size() == params.size()) { + boolean matchParams = true; + for (int i = 0; i < m.getParameters().size(); i++) { + if (!m.getParameters().get(i).getType().equals(params.get(i).getType())) { + matchParams = false; + break; + } + } + if (matchParams) return m; + } + } + } + return null; + } protected MethodDeclaration getMethod(TypeDeclaration component, String methodName) { for (MethodDeclaration m: component.getMethods()) { diff --git a/AlgebraicDataflowArchitectureModel/src/generators/CodeGeneratorFromDataFlowGraph.java b/AlgebraicDataflowArchitectureModel/src/generators/CodeGeneratorFromDataFlowGraph.java index 0052cb2..3c6160c 100644 --- a/AlgebraicDataflowArchitectureModel/src/generators/CodeGeneratorFromDataFlowGraph.java +++ b/AlgebraicDataflowArchitectureModel/src/generators/CodeGeneratorFromDataFlowGraph.java @@ -11,13 +11,11 @@ import java.util.Map.Entry; import java.util.Set; import java.util.Stack; -import java.util.AbstractMap.SimpleEntry; import code.ast.Annotation; import code.ast.Block; import code.ast.CompilationUnit; import code.ast.FieldDeclaration; -import code.ast.ImportDeclaration; import code.ast.MethodDeclaration; import code.ast.TypeDeclaration; import code.ast.VariableDeclaration; @@ -30,6 +28,7 @@ import models.algebra.Parameter; import models.algebra.ParameterizedIdentifierIsFutureWork; import models.algebra.Position; +import models.algebra.Symbol; import models.algebra.Term; import models.algebra.Type; import models.algebra.UnificationFailed; @@ -65,7 +64,6 @@ List> constructorStatements = new ArrayList<>(); Map>> updateStatements = new HashMap<>(); Map> descendantGetters = new HashMap<>(); - Map getterAccessors = new HashMap<>(); TypeDeclaration mainComponent = null; MethodDeclaration mainConstructor = null; @@ -148,21 +146,25 @@ } // For each components (2nd pass). + Map priorMemberForInputChannel = new HashMap<>(); for (Node componentNode: components) { // Declare this resource. ResourceNode resourceNode = (ResourceNode) componentNode; Type resStateType = getImplStateType(resourceNode.getResourceHierarchy(), langSpec); TypeDeclaration component = null; TypeDeclaration parentComponent = null; + TypeDeclaration rootComponent = null; if (generatesComponent(resourceNode.getResourceHierarchy())) { component = resourceComponents.get(resourceNode.getResourceHierarchy()); } if (resourceNode.getResourceHierarchy().getParent() != null) { parentComponent = resourceComponents.get(resourceNode.getResourceHierarchy().getParent()); } + rootComponent = resourceComponents.get(resourceNode.getResourceHierarchy().getRoot()); - // Declare cache fields and update methods in this resource. - Map.Entry, Map>>> initStatementsAndUpdateUpdates = declareCacheFieldsAndUpdateMethods(resourceNode, component, parentComponent, platformSpec, langSpec); + // Declare cache fields and update methods in this resource, and an update accessor method in the type of root resource. + Map.Entry, Map>>> initStatementsAndUpdateUpdates + = declareCacheFieldsAndUpdateMethods(resourceNode, component, parentComponent, rootComponent, platformSpec, langSpec); if (component == null) { // Constructor statements were not added to any component because no component had been generated. for (String statement: initStatementsAndUpdateUpdates.getKey()) { @@ -188,11 +190,12 @@ if (!platformSpec.isMonolithic()) { // Declare the getter accessor in the root resource. - declareGetterAccessorInTheRootResource(resourceNode, getterAccessors, platformSpec, langSpec); + declareGetterAccessorInTheRootResource(resourceNode, rootComponent, platformSpec, langSpec); } // Declare input methods in this component and the main component. - Map.Entry, Map>>> initStatementsAndInputUpdates = declareInputMethodsInThisAndMainComponents(resourceNode, component, parentComponent, mainComponent, model, platformSpec, langSpec); + Map.Entry, Map>>> initStatementsAndInputUpdates + = declareInputMethodsInThisAndMainComponents(resourceNode, component, parentComponent, mainComponent, rootComponent, model, priorMemberForInputChannel, platformSpec, langSpec); if (component == null) { // Constructor statements were not added to any component because no component had been generated. for (String statement: initStatementsAndInputUpdates.getKey()) { @@ -549,7 +552,7 @@ if (!platformSpec.isMonolithic() && (outsideOutputResource || (resourceNode.getOutSideResource(ch).getCommonPrefix(dstResPath) == null && platformSpec.isDifferentTreesAsDifferentServices()))) { // Inter-service (for REST API) - if (!bDeclareClientField) { + if (!bDeclareClientField && parentComponent != null) { // Declare a client field to connect to the destination resource of push transfer. platformSpec.addClientFieldDeclaration(parentComponent); bDeclareClientField = true; @@ -573,7 +576,7 @@ } } else { // No component is created for this resource. - if (resourceNode.getParent().getResourceHierarchy() != dstRes) { + if (resourceNode.getParent().getResourceHierarchy() != dstRes && parentComponent != null) { parentComponent.addField(refFieldForPush); if (!outsideOutputResource) { Map nameToParam = constructorParams.get(resourceNode.getParent().getResourceHierarchy()); @@ -699,7 +702,7 @@ if (!platformSpec.isMonolithic() && (outsideInputResource || (resourceNode.getInSideResource(ch).getCommonPrefix(srcRes) == null && platformSpec.isDifferentTreesAsDifferentServices()))) { // Inter-service (for REST API) - if (!bDeclareClientField) { + if (!bDeclareClientField && parentComponent != null) { // Declare a client field to connect to the destination resource of push transfer. platformSpec.addClientFieldDeclaration(parentComponent); bDeclareClientField = true; @@ -724,7 +727,7 @@ } } else { // No component is created for this resource. - if (resourceNode.getParent().getResourceHierarchy() != srcRes.getResourceHierarchy()) { + if (resourceNode.getParent().getResourceHierarchy() != srcRes.getResourceHierarchy() && parentComponent != null) { parentComponent.addField(refFieldForPull); if (!outsideInputResource) { Map nameToParam = constructorParams.get(resourceNode.getParent().getResourceHierarchy()); @@ -1156,8 +1159,8 @@ } } - private Map.Entry, Map>>> declareCacheFieldsAndUpdateMethods(ResourceNode resourceNode, TypeDeclaration component, TypeDeclaration parentComponent, - IPlatformSpecific platformSpec, ILanguageSpecific langSpec) { + private Map.Entry, Map>>> declareCacheFieldsAndUpdateMethods(ResourceNode resourceNode, + TypeDeclaration component, TypeDeclaration parentComponent, TypeDeclaration rootComponent, IPlatformSpecific platformSpec, ILanguageSpecific langSpec) { // Declare cash fields and update methods in the component. String resComponentName = getComponentName(resourceNode.getResourceHierarchy(), langSpec); List constructorStatements = new ArrayList<>(); @@ -1194,9 +1197,11 @@ } // Check if the output resource is outside of the channel scope. boolean outsideOutputResource = false; + ChannelMember out = null; ResourcePath dstResPath = null; for (ChannelMember cm: ch.getOutputChannelMembers()) { if (resourceNode.getInSideResources().contains(cm.getResource())) { + out = cm; dstResPath = cm.getResource(); if (cm.isOutside()) { outsideOutputResource = true; // Regarded as push transfer. @@ -1214,31 +1219,38 @@ if ((((PushPullAttribute) re.getAttribute()).getSelectedOption() == PushPullValue.PUSH && !outsideInputResource) || outsideOutputResource) { // For push data transfer + boolean hasRestAPI = false; + boolean isRestAPI = false; + if (!platformSpec.isMonolithic() + && (outsideOutputResource || (resourceNode.getInSideResource(ch).getCommonPrefix(srcResPath) == null && platformSpec.isDifferentTreesAsDifferentServices()))) { + // 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 parameters = new ArrayList<>(); - int v = 1; - for (Expression exp: dstResPath.getPathParams()) { - if (exp instanceof Variable) { - Variable pathVar = (Variable) exp; - String varName = "self" + (v > 1 ? v : ""); -// String varName = pathVar.getName(); - VariableDeclaration pathParam = langSpec.newVariableDeclaration(pathVar.getType(), varName); - parameters.add(pathParam); // A path parameter to identify the self resource. - } - v++; - } + getUpdateResourcePathAndPathParams(dstResPath, parameters, isRestAPI, platformSpec, langSpec); // Path parameters to identify the self resource. for (Selector selector: ch.getAllSelectors()) { if (selector.getExpression() instanceof Variable) { Variable selVar = (Variable) selector.getExpression(); VariableDeclaration chParam = langSpec.newVariableDeclaration(selVar.getType(), selVar.getName()); + if (isRestAPI) platformSpec.addFormParamAnnotation(chParam, selVar.getName()); parameters.add(chParam); // A channel parameter to specify the context of the collaboration. } } - parameters.add(langSpec.newVariableDeclaration(srcResPath.getResourceStateType(), srcResPath.getLeafResourceName())); // The state of the source resource to carry the data-flow. + VariableDeclaration param = langSpec.newVariableDeclaration(srcResPath.getResourceStateType(), srcResName); + if (isRestAPI) platformSpec.addFormParamAnnotation(param, srcResName); + parameters.add(param); // The state of the source resource to carry the data-flow. // For the refs. for (ResourcePath ref: ch.getReferenceResources()) { if (!resourceNode.getInSideResources().contains(ref)) { - parameters.add(langSpec.newVariableDeclaration(ref.getResourceStateType(), ref.getLeafResourceName())); + String refName = langSpec.toVariableName(getComponentName(ref.getResourceHierarchy(), langSpec)); + param = langSpec.newVariableDeclaration(ref.getResourceStateType(), refName); + if (isRestAPI) platformSpec.addFormParamAnnotation(param, refName); + parameters.add(param); } } MethodDeclaration update = null; @@ -1251,7 +1263,6 @@ } if (update == null) { update = langSpec.newMethodDeclaration(updateMethodPrefix + from + srcResComponentName, false, null, parameters); - component.addMethod(update); } } else if (parentComponent != null) { for (MethodDeclaration method: parentComponent.getMethods()) { @@ -1262,133 +1273,162 @@ } if (update == null) { update = langSpec.newMethodDeclaration(updateMethodPrefix + resComponentName + from + srcResComponentName, false, null, parameters); + } + } + int inDegree = 0; + if (isRestAPI) { + // Determine whether the update method is put or post or delete. + if (isPut(out)) { + platformSpec.addPutAnnotations(update); + } else { + if (!isDelete(out)) { + platformSpec.addPostAnnotations(update); + } else { + platformSpec.addDeleteAnnotations(update); + } + } + inDegree = indirectSrcChNode.getIndegree() + ch.getInputChannelMembers().size(); + if (inDegree > 1) { + // If incoming edges are multiple, then a child resource for each source resource is defined in the destination resource so that its state can be updated separately. + if (isRestAPI) platformSpec.addPathAnnotation(update, "/" + srcResName); + } + } + if (update != null) { + if (component != null) { + // A component is created for this resource. + component.addMethod(update); + } else if (parentComponent != null) { + // No component is created for this resource. parentComponent.addMethod(update); } } + if (hasRestAPI && !isRestAPI) { + // Declare an update accessor method in the type of root resource. + declareUpdateAccessorInTheRootResource(resourceNode, update.getName(), ch, out, srcResPath, dstResPath, + rootComponent, inDegree, platformSpec, langSpec); + } // Add a statement to update the state field if (((StoreAttribute) resourceNode.getAttribute()).isStored()) { try { - for (ChannelMember out: ch.getOutputChannelMembers()) { - if (resourceNode.getInSideResources().contains(out.getResource())) { - Expression updateExp = null; - if (ch.getReferenceChannelMembers().size() == 0) { - updateExp = ch.deriveUpdateExpressionOf(out, getPushAccessor(platformSpec)).getKey(); - } else { - // if there exists one or more reference channel member. - HashMap inputResourceToStateAccessor = new HashMap<>(); - for (ChannelMember in: ch.getInputChannelMembers()) { - inputResourceToStateAccessor.put(in, getPushAccessor(platformSpec)); - } - for (ChannelMember c: ch.getReferenceChannelMembers()) { - inputResourceToStateAccessor.put(c, getRefAccessor(platformSpec)); - } - updateExp = ch.deriveUpdateExpressionOf(out, getPushAccessor(platformSpec), inputResourceToStateAccessor).getKey(); + if (resourceNode.getInSideResources().contains(out.getResource())) { + Expression updateExp = null; + if (ch.getReferenceChannelMembers().size() == 0) { + updateExp = ch.deriveUpdateExpressionOf(out, getPushAccessor(platformSpec)).getKey(); + } else { + // if there exists one or more reference channel member. + HashMap inputResourceToStateAccessor = new HashMap<>(); + for (ChannelMember in: ch.getInputChannelMembers()) { + inputResourceToStateAccessor.put(in, getPushAccessor(platformSpec)); } - // Replace Json constructor with a constructor of the child resource. - ResourceHierarchy outRes = out.getResource().getResourceHierarchy(); - if (outRes.getChildren().size() == 1 && outRes.getChildren().iterator().next().getNumParameters() > 0) { - ResourceHierarchy descendantRes = outRes; - Set children = descendantRes.getChildren(); - do { - descendantRes = children.iterator().next(); - if (generatesComponent(descendantRes)) { - updateStatements.put(update, new AbstractMap.SimpleEntry<>(updateExp, new AbstractMap.SimpleEntry<>(outRes, descendantRes))); - updateExp = null; - break; - } - children = descendantRes.getChildren(); - } while (children != null && children.size() == 1); + for (ChannelMember c: ch.getReferenceChannelMembers()) { + inputResourceToStateAccessor.put(c, getRefAccessor(platformSpec)); } - // Add statements to the update method. - String[] sideEffects = new String[] {""}; - String newState = updateExp.toImplementation(sideEffects); - int numOfOutResourcesWithTheSameHierarchy = 0; - for (ResourcePath outResPath: ch.getOutputResources()) { - if (outResPath.getResourceHierarchy().equals(outRes)) { - numOfOutResourcesWithTheSameHierarchy++; + updateExp = ch.deriveUpdateExpressionOf(out, getPushAccessor(platformSpec), inputResourceToStateAccessor).getKey(); + } + // Replace Json constructor with a constructor of the child resource. + ResourceHierarchy outRes = out.getResource().getResourceHierarchy(); + if (outRes.getChildren().size() == 1 && outRes.getChildren().iterator().next().getNumParameters() > 0) { + ResourceHierarchy descendantRes = outRes; + Set children = descendantRes.getChildren(); + do { + descendantRes = children.iterator().next(); + if (generatesComponent(descendantRes)) { + updateStatements.put(update, new AbstractMap.SimpleEntry<>(updateExp, new AbstractMap.SimpleEntry<>(outRes, descendantRes))); + updateExp = null; + break; } + children = descendantRes.getChildren(); + } while (children != null && children.size() == 1); + } + // Add statements to the update method. + String[] sideEffects = new String[] {""}; + String newState = updateExp.toImplementation(sideEffects); + int numOfOutResourcesWithTheSameHierarchy = 0; + for (ResourcePath outResPath: ch.getOutputResources()) { + if (outResPath.getResourceHierarchy().equals(outRes)) { + numOfOutResourcesWithTheSameHierarchy++; } - String updateStatement = ""; - if (generatesComponent(outRes)) { - if (updateExp instanceof Term && ((Term) updateExp).getSymbol().isImplWithSideEffect()) { - updateStatement = sideEffects[0]; - if (updateStatement.endsWith("\n")) { - updateStatement = updateStatement.substring(0, updateStatement.length() - 1); - } - } else { - updateStatement = sideEffects[0] + langSpec.getFieldAccessor(fieldOfResourceState) + langSpec.getAssignment() + newState + langSpec.getStatementDelimiter(); // this.value = ... + } + String updateStatement = ""; + if (generatesComponent(outRes)) { + if (updateExp instanceof Term && ((Term) updateExp).getSymbol().isImplWithSideEffect()) { + updateStatement = sideEffects[0]; + if (updateStatement.endsWith("\n")) { + updateStatement = updateStatement.substring(0, updateStatement.length() - 1); } } else { - if (sideEffects[0] != null) { - updateStatement = sideEffects[0]; - String resourceName = langSpec.toVariableName(getComponentName(outRes, langSpec)); - updateStatement = updateStatement.replace(langSpec.getFieldAccessor(fieldOfResourceState), langSpec.getFieldAccessor(resourceName)); - if (updateStatement.endsWith("\n")) { - updateStatement = updateStatement.substring(0, updateStatement.length() - 1); - } - } - if (DataConstraintModel.typeList.isAncestorOf(resourceNode.getParent().getResourceStateType())) { - Term selector = new Term(DataConstraintModel.set); - selector.addChild(new Constant(langSpec.getFieldAccessor(fieldOfResourceState))); - selector.addChild(new Variable(update.getParameters().get(update.getParameters().size() - 2).getName())); - selector.addChild(new Constant(newState)); - String[] sideEffects2 = new String[] {""}; - String newList = selector.toImplementation(sideEffects2); - updateStatement += sideEffects2[0]; - } else if (DataConstraintModel.typeMap.isAncestorOf(resourceNode.getParent().getResourceStateType())) { - Term selector = new Term(DataConstraintModel.insert); - selector.addChild(new Constant(langSpec.getFieldAccessor(fieldOfResourceState))); - selector.addChild(new Variable(update.getParameters().get(update.getParameters().size() - 2).getName())); - selector.addChild(new Constant(newState)); - String[] sideEffects2 = new String[] {""}; - String newMap = selector.toImplementation(sideEffects2); - updateStatement += sideEffects2[0]; - } else if (!(updateExp instanceof Term && ((Term) updateExp).getSymbol().isImplWithSideEffect())) { - String resourceName = langSpec.toVariableName(getComponentName(outRes, langSpec)); - updateStatement += langSpec.getFieldAccessor(resourceName) + langSpec.getAssignment() + newState + langSpec.getStatementDelimiter(); + updateStatement = sideEffects[0] + langSpec.getFieldAccessor(fieldOfResourceState) + langSpec.getAssignment() + newState + langSpec.getStatementDelimiter(); // this.value = ... + } + } else { + if (sideEffects[0] != null) { + updateStatement = sideEffects[0]; + String resourceName = langSpec.toVariableName(getComponentName(outRes, langSpec)); + updateStatement = updateStatement.replace(langSpec.getFieldAccessor(fieldOfResourceState), langSpec.getFieldAccessor(resourceName)); + if (updateStatement.endsWith("\n")) { + updateStatement = updateStatement.substring(0, updateStatement.length() - 1); } } - if (numOfOutResourcesWithTheSameHierarchy == 1) { - update.addFirstStatement(updateStatement); - } else { - Term conditions = null; - int i = 1; - Map>> resourcePaths = ch.fillOutsideResourcePaths(out, JerseyCodeGenerator.pushAccessor); - for (Expression pathParam: out.getResource().getPathParams()) { - if (pathParam instanceof Variable) { - String selfParamName = ((Variable) pathParam).getName(); - Expression arg = null; - for (Selector selector: ch.getAllSelectors()) { - if (selector.getExpression() instanceof Variable) { - Variable selVar = (Variable) selector.getExpression(); - if (selVar.getName().equals(selfParamName)) { - arg = selVar; - break; - } + if (DataConstraintModel.typeList.isAncestorOf(resourceNode.getParent().getResourceStateType())) { + Term selector = new Term(DataConstraintModel.set); + selector.addChild(new Constant(langSpec.getFieldAccessor(fieldOfResourceState))); + selector.addChild(new Variable(update.getParameters().get(update.getParameters().size() - 2).getName())); + selector.addChild(new Constant(newState)); + String[] sideEffects2 = new String[] {""}; + String newList = selector.toImplementation(sideEffects2); + updateStatement += sideEffects2[0]; + } else if (DataConstraintModel.typeMap.isAncestorOf(resourceNode.getParent().getResourceStateType())) { + Term selector = new Term(DataConstraintModel.insert); + selector.addChild(new Constant(langSpec.getFieldAccessor(fieldOfResourceState))); + selector.addChild(new Variable(update.getParameters().get(update.getParameters().size() - 2).getName())); + selector.addChild(new Constant(newState)); + String[] sideEffects2 = new String[] {""}; + String newMap = selector.toImplementation(sideEffects2); + updateStatement += sideEffects2[0]; + } else if (!(updateExp instanceof Term && ((Term) updateExp).getSymbol().isImplWithSideEffect())) { + String resourceName = langSpec.toVariableName(getComponentName(outRes, langSpec)); + updateStatement += langSpec.getFieldAccessor(resourceName) + langSpec.getAssignment() + newState + langSpec.getStatementDelimiter(); + } + } + if (numOfOutResourcesWithTheSameHierarchy == 1) { + update.addFirstStatement(updateStatement); + } else { + Term conditions = null; + int i = 1; + Map>> resourcePaths = ch.fillOutsideResourcePaths(out, JerseyCodeGenerator.pushAccessor); + for (Expression pathParam: out.getResource().getPathParams()) { + if (pathParam instanceof Variable) { + String selfParamName = ((Variable) pathParam).getName(); + Expression arg = null; + for (Selector selector: ch.getAllSelectors()) { + if (selector.getExpression() instanceof Variable) { + Variable selVar = (Variable) selector.getExpression(); + if (selVar.getName().equals(selfParamName)) { + arg = selVar; + break; } } - if (arg == null) { - ResourcePath filledPath = resourcePaths.get(out).getKey(); - arg = filledPath.getPathParams().get(i - 1); - } - Term condition = new Term(DataConstraintModel.eq, new Expression[] { - new Parameter("self" + (i > 1 ? i : ""), DataConstraintModel.typeString), - arg}); - if (conditions == null) { - conditions = condition; - } else { - conditions = new Term(DataConstraintModel.and, new Expression[] { - conditions, - condition}); - } } - i++; + if (arg == null) { + ResourcePath filledPath = resourcePaths.get(out).getKey(); + arg = filledPath.getPathParams().get(i - 1); + } + Term condition = new Term(DataConstraintModel.eq, new Expression[] { + new Parameter("self" + (i > 1 ? i : ""), DataConstraintModel.typeString), + arg}); + if (conditions == null) { + conditions = condition; + } else { + conditions = new Term(DataConstraintModel.and, new Expression[] { + conditions, + condition}); + } } - update.addFirstStatement(langSpec.getIfStatement(conditions, updateStatement)); + i++; } - break; + update.addFirstStatement(langSpec.getIfStatement(conditions, updateStatement)); } + break; } } catch (ParameterizedIdentifierIsFutureWork | ResolvingMultipleDefinitionIsFutureWork | InvalidMessage | UnificationFailed | ValueUndefined e1) { @@ -1397,14 +1437,16 @@ } // Declare the field to cache the state of the source resource in the type of the destination resource. - if (resToCh.getDestination().getIndegree() + ch.getInputChannelMembers().size() > 1 + inDegree = indirectSrcChNode.getIndegree() + ch.getInputChannelMembers().size(); + if (inDegree > 1 || (ch.getInputChannelMembers().size() == 1 && ch.getInputChannelMembers().iterator().next().getStateTransition().isRightPartial())) { // If incoming edges are multiple, or the current state of an input member is needed. if (langSpec.declareField()) { // Declare the cache field. + String cacheFieldName = langSpec.toVariableName(getComponentName(srcResPath.getResourceHierarchy(), langSpec)); FieldDeclaration cacheField = langSpec.newFieldDeclaration( srcResPath.getResourceStateType(), - srcResPath.getLeafResourceName(), + cacheFieldName, langSpec.getFieldInitializer(srcResPath.getResourceStateType(), srcResPath.getResourceHierarchy().getInitialValue())); if (component != null) { component.addField(cacheField); @@ -1428,10 +1470,10 @@ } if (outsideInputMembers.size() > 0) { Map>> resourcePaths = null; - for (ChannelMember out: ch.getOutputChannelMembers()) { - if (resourceNode.getInSideResources().contains(out.getResource())) { + for (ChannelMember out1: ch.getOutputChannelMembers()) { + if (resourceNode.getInSideResources().contains(out1.getResource())) { try { - resourcePaths = ch.fillOutsideResourcePaths(out, getPullAccessor(platformSpec)); + resourcePaths = ch.fillOutsideResourcePaths(out1, getPullAccessor(platformSpec)); } catch (ParameterizedIdentifierIsFutureWork | ResolvingMultipleDefinitionIsFutureWork | InvalidMessage | UnificationFailed | ValueUndefined e) { e.printStackTrace(); @@ -1513,10 +1555,10 @@ DataTransferChannel ch2 = chNode2.getChannel(); // Check if the output resource is outside of the channel scope. boolean outsideOutputResource2 = false; - ChannelMember out = null; + ChannelMember out1 = null; for (ChannelMember cm: ch2.getOutputChannelMembers()) { if (dstNode.getInSideResources().contains(cm.getResource())) { - out = cm; + out1 = cm; if (cm.isOutside()) { outsideOutputResource2 = true; break; @@ -1616,7 +1658,7 @@ } // Update fields to refer to outside resources. try { - Map>> resourcePaths = ch2.fillOutsideResourcePaths(out, getPullAccessor(platformSpec)); + Map>> resourcePaths = ch2.fillOutsideResourcePaths(out1, getPullAccessor(platformSpec)); if (resourcePaths != null && resourcePaths.size() > 0) { for (ChannelMember outsideMember: resourcePaths.keySet()) { ResourcePath outsidePath = resourcePaths.get(outsideMember).getKey(); @@ -1648,7 +1690,7 @@ e.printStackTrace(); } // Values of path parameters to call the update method. - for (Expression pathParam: out.getResource().getPathParams()) { + for (Expression pathParam: out1.getResource().getPathParams()) { if (pathParam instanceof Variable) { Variable pathVar = (Variable) pathParam; params.add(pathVar.getName()); @@ -1706,14 +1748,14 @@ for (Edge chToRes2: outEdges) { ChannelNode chNode2 = (ChannelNode) chToRes2.getSource(); DataTransferChannel ch2 = chNode2.getChannel(); - for (ChannelMember out: ch2.getOutputChannelMembers()) { - if (!generatesComponent(out.getResource().getResourceHierarchy())) { + for (ChannelMember out2: ch2.getOutputChannelMembers()) { + if (!generatesComponent(out2.getResource().getResourceHierarchy())) { // Also dstRes2 does not have a component. - ResourcePath dstRes2 = out.getResource(); + ResourcePath dstRes2 = out2.getResource(); if (srcRes2.getParent().equals(dstRes2.getParent())) { Map>> resourcePaths = null; try { - resourcePaths = ch2.fillOutsideResourcePaths(out, getPullAccessor(platformSpec)); + resourcePaths = ch2.fillOutsideResourcePaths(out2, getPullAccessor(platformSpec)); if (resourcePaths != null && resourcePaths.size() > 0) { for (ChannelMember outsideMember: outsideInputMembers2) { for (ChannelMember dependedMember: resourcePaths.get(outsideMember).getValue()) { @@ -1761,22 +1803,40 @@ } private Map.Entry, Map>>> declareInputMethodsInThisAndMainComponents(ResourceNode resourceNode, TypeDeclaration component, - TypeDeclaration parentComponent, TypeDeclaration mainComponent, DataTransferModel model, IPlatformSpecific platformSpec, ILanguageSpecific langSpec) { + TypeDeclaration parentComponent, TypeDeclaration mainComponent, TypeDeclaration rootComponent, DataTransferModel model, Map priorMemberForInputChannel, IPlatformSpecific platformSpec, ILanguageSpecific langSpec) { // Declare input methods. String resName = resourceNode.getResourceName(); String resComponentName = langSpec.toComponentName(resName); List constructorStatements = new ArrayList<>(); Map>> inputStatements = new HashMap<>(); for (Channel ch: model.getInputChannels()) { + for (ChannelMember cm : ((DataTransferChannel) ch).getOutputChannelMembers()) { + if (!cm.isOutside()) { + if (priorMemberForInputChannel.get(ch) == null) { + priorMemberForInputChannel.put(ch, cm); // The receiver of the input event when multiple output resources are defined for the channel. + } + } + } for (ChannelMember out: ((DataTransferChannel) ch).getOutputChannelMembers()) { if (resourceNode.getInSideResources().contains(out.getResource())) { Expression message = out.getStateTransition().getMessageExpression(); MethodDeclaration input = null; MethodDeclaration inputAccessor = null; + MethodDeclaration rootInputAccessor = null; if (message instanceof Term) { // Declare an input method in this component. ArrayList resInputParams = new ArrayList<>(); ArrayList mainInputParams = new ArrayList<>(); + ArrayList rootInputParams = new ArrayList<>(); + String resourcePath = null; + if (!platformSpec.isMonolithic()) { + resourcePath = getInputMethodResourcePathAndPathParams(out.getResource(), rootInputParams, platformSpec, langSpec); // Path parameters for the input REST API. + if (resourcePath.indexOf('/') > 0) { + resourcePath = resourcePath.substring(resourcePath.indexOf('/')); + } else { + resourcePath = ""; + } + } // The path parameters are not to be passed to the input method of each resource (resInputParams) // because they are always equal to either channel selectors or message parameters. @@ -1835,39 +1895,47 @@ if (!bExists) { mainInputParams.add(langSpec.newVariableDeclaration(var.getType(), var.getName())); } - } - } - String inputMethodName = ((Term) message).getSymbol().getImplName(); - if (((DataTransferChannel) ch).getOutputChannelMembers().size() > 1) { - inputMethodName += _for + getComponentName(out.getResource().getResourceHierarchy(), langSpec); - } - if (component != null) { - // A component is created for this resource. - for (MethodDeclaration method: component.getMethods()) { - if (method.getName().equals(inputMethodName)) { - input = method; - break; + if (!platformSpec.isMonolithic() && !resourcePath.contains("{" + var.getName()+ "}")) { + VariableDeclaration param = langSpec.newVariableDeclaration(var.getType(), var.getName()); + platformSpec.addFormParamAnnotation(param, var.getName()); + rootInputParams.add(param); } } - if (input == null) { - input = langSpec.newMethodDeclaration(inputMethodName, false, null, resInputParams); - component.addMethod(input); + } + if (platformSpec.isMonolithic() + || (resourceNode.getResourceHierarchy().getParent() != null && resourceNode.getResourceHierarchy().getParent().getParent() != null)) { + String inputMethodName = ((Term) message).getSymbol().getImplName(); + if (((DataTransferChannel) ch).getOutputChannelMembers().size() > 1) { + inputMethodName += _for + getComponentName(out.getResource().getResourceHierarchy(), langSpec); } - } else if (parentComponent != null) { - // No component is created for this resource. - for (MethodDeclaration method: parentComponent.getMethods()) { - if (method.getName().equals(inputMethodName)) { - input = method; - break; + if (component != null) { + // A component is created for this resource. + for (MethodDeclaration method: component.getMethods()) { + if (method.getName().equals(inputMethodName)) { + input = method; + break; + } } - } - if (input == null) { - input = langSpec.newMethodDeclaration(inputMethodName, false, null, resInputParams); - parentComponent.addMethod(input); + if (input == null) { + input = langSpec.newMethodDeclaration(inputMethodName, false, null, resInputParams); + component.addMethod(input); + } + } else if (parentComponent != null) { + // No component is created for this resource. + for (MethodDeclaration method: parentComponent.getMethods()) { + if (method.getName().equals(inputMethodName)) { + input = method; + break; + } + } + if (input == null) { + input = langSpec.newMethodDeclaration(inputMethodName, false, null, resInputParams); + parentComponent.addMethod(input); + } } } - // Declare the accessor in the main component to call the input method. + // Declare the accessor in the main component to call the input method. (for monolithic application) if (platformSpec.hasMain()) { String messageSymbol = ((Term) message).getSymbol().getImplName(); inputAccessor = getMethod(mainComponent, messageSymbol); @@ -1889,6 +1957,17 @@ } } } + + // For the root resource. (for REST API) + if (!platformSpec.isMonolithic()) { + if (priorMemberForInputChannel.get(ch) == null || out == priorMemberForInputChannel.get(ch)) { + // If out is the receiver of the input event. + priorMemberForInputChannel.put(ch, out); + String messageSymbol = ((Term) message).getSymbol().getImplName(); + declareInputAccessorInTheRootResource(messageSymbol, rootInputParams, out, resourcePath, + rootComponent, platformSpec, langSpec); + } + } } else if (message instanceof Variable) { // Declare an input method in this component. ArrayList resInputParams = new ArrayList<>(); @@ -1919,48 +1998,51 @@ v++; } } - String inputMethodName = ((Variable) message).getName(); - if (((DataTransferChannel) ch).getOutputChannelMembers().size() > 1) { - inputMethodName += _for + getComponentName(out.getResource().getResourceHierarchy(), langSpec); - } - if (component != null) { - // A component is created for this resource. - for (MethodDeclaration method: component.getMethods()) { - if (method.getName().equals(inputMethodName)) { - input = method; - break; - } + if (platformSpec.isMonolithic() + || (resourceNode.getResourceHierarchy().getParent() != null && resourceNode.getResourceHierarchy().getParent().getParent() != null)) { + String inputMethodName = ((Variable) message).getName(); + if (((DataTransferChannel) ch).getOutputChannelMembers().size() > 1) { + inputMethodName += _for + getComponentName(out.getResource().getResourceHierarchy(), langSpec); } - if (input == null) { - if (resInputParams.size() == 0) { - input = langSpec.newMethodDeclaration(inputMethodName, null); - } else { - input = langSpec.newMethodDeclaration(inputMethodName, false, null, resInputParams); + if (component != null) { + // A component is created for this resource. + for (MethodDeclaration method: component.getMethods()) { + if (method.getName().equals(inputMethodName)) { + input = method; + break; + } } - component.addMethod(input); - } - } else if (parentComponent != null) { - // No component is created for this resource. - for (MethodDeclaration method: parentComponent.getMethods()) { - if (method.getName().equals(inputMethodName)) { - input = method; - break; + if (input == null) { + if (resInputParams.size() == 0) { + input = langSpec.newMethodDeclaration(inputMethodName, null); + } else { + input = langSpec.newMethodDeclaration(inputMethodName, false, null, resInputParams); + } + component.addMethod(input); } - } - if (input == null) { - if (resInputParams.size() == 0) { - input = langSpec.newMethodDeclaration(inputMethodName, null); - } else { - input = langSpec.newMethodDeclaration(inputMethodName, false, null, resInputParams); + } else if (parentComponent != null) { + // No component is created for this resource. + for (MethodDeclaration method: parentComponent.getMethods()) { + if (method.getName().equals(inputMethodName)) { + input = method; + break; + } } - parentComponent.addMethod(input); + if (input == null) { + if (resInputParams.size() == 0) { + input = langSpec.newMethodDeclaration(inputMethodName, null); + } else { + input = langSpec.newMethodDeclaration(inputMethodName, false, null, resInputParams); + } + parentComponent.addMethod(input); + } } } - // Declare the accessor in the main component to call the input method. + // Declare the accessor in the main component to call the input method. (for monolithic application) if (platformSpec.hasMain()) { String messageSymbol = ((Variable) message).getName(); - inputAccessor = getMethod(mainComponent, messageSymbol); + inputAccessor = getMethod(mainComponent, messageSymbol, mainInputParams); if (inputAccessor == null) { if (mainInputParams.size() == 0) { inputAccessor = langSpec.newMethodDeclaration(messageSymbol, null); @@ -1970,6 +2052,24 @@ mainComponent.addMethod(inputAccessor); } } + + // For the root resource. (for REST API) + if (!platformSpec.isMonolithic()) { + if (priorMemberForInputChannel.get(ch) == null || out == priorMemberForInputChannel.get(ch)) { + // If out is the receiver of the input event. + priorMemberForInputChannel.put(ch, out); + ArrayList rootInputParams = new ArrayList<>(); + String resourcePath = getGetterResourcePathAndPathParams(out.getResource(), rootInputParams, platformSpec, langSpec); + if (resourcePath.indexOf('/') > 0) { + resourcePath = resourcePath.substring(resourcePath.indexOf('/')); + } else { + resourcePath = ""; + } + String messageSymbol = ((Variable) message).getName(); + declareInputAccessorInTheRootResource(messageSymbol, rootInputParams, out, resourcePath, + rootComponent, platformSpec, langSpec); + } + } } // Add an invocation to the accessor method. @@ -2383,8 +2483,39 @@ return new AbstractMap.SimpleEntry<>(constructorStatements, inputStatements); } - private void declareGetterAccessorInTheRootResource(ResourceNode resourceNode, - Map getterAccessors, IPlatformSpecific platformSpec, ILanguageSpecific langSpec) { + protected boolean isPut(ChannelMember cm) { + return cm.getStateTransition().isRightUnary(); + } + + protected boolean isDelete(ChannelMember cm) { + boolean isDelete = false; + Expression nextExp = cm.getStateTransition().getNextStateExpression(); + if (nextExp instanceof Term) { + Symbol rootSymbol = ((Term) nextExp).getSymbol(); + if (rootSymbol.equals(DataConstraintModel.delete) || rootSymbol.equals(DataConstraintModel.remove)) { + isDelete = true; + } else if (rootSymbol.equals(DataConstraintModel.cond)) { + Expression childExp = ((Term) nextExp).getChild(1); + if (childExp instanceof Term) { + rootSymbol = ((Term) childExp).getSymbol(); + if (rootSymbol.equals(DataConstraintModel.delete) || rootSymbol.equals(DataConstraintModel.remove)) { + isDelete = true; + } + } + childExp = ((Term) nextExp).getChild(2); + if (childExp instanceof Term) { + rootSymbol = ((Term) childExp).getSymbol(); + if (rootSymbol.equals(DataConstraintModel.delete) || rootSymbol.equals(DataConstraintModel.remove)) { + isDelete = true; + } + } + } + } + return isDelete; + } + + protected void declareGetterAccessorInTheRootResource(ResourceNode resourceNode, TypeDeclaration rootComponent, + IPlatformSpecific platformSpec, ILanguageSpecific langSpec) { if (resourceNode.getResourceHierarchy().getParent() != null) { // For a non-root resource MethodDeclaration getterAccessor = null; @@ -2412,11 +2543,78 @@ if (resourcePath.length() > 0) { platformSpec.addPathAnnotation(getterAccessor, resourcePath); } - getterAccessors.put(resourceNode.getResourceHierarchy(), getterAccessor); + rootComponent.addMethod(getterAccessor); } } - private String getGetterResourcePathAndPathParams(ResourcePath resPath, List pathParams, IPlatformSpecific platformSpec, ILanguageSpecific langSpec) { + protected void declareUpdateAccessorInTheRootResource(ResourceNode resourceNode, String updateMethodName, + DataTransferChannel ch, ChannelMember cm, ResourcePath srcResPath, ResourcePath dstResPath, TypeDeclaration rootComponent, + int inDegree, IPlatformSpecific platformSpec, ILanguageSpecific langSpec) { + ArrayList parameters; + VariableDeclaration param; + parameters = new ArrayList<>(); + String resourcePath = getUpdateResourcePathAndPathParams(dstResPath, parameters, true, platformSpec, langSpec); // Path parameters to identify the self resource. + for (Selector selector: ch.getAllSelectors()) { + if (selector.getExpression() instanceof Variable) { + Variable selVar = (Variable) selector.getExpression(); + VariableDeclaration chParam = langSpec.newVariableDeclaration(selVar.getType(), selVar.getName()); + platformSpec.addFormParamAnnotation(chParam, selVar.getName()); + parameters.add(chParam); // A channel parameter to specify the context of the collaboration. + } + } + Type srcType = srcResPath.getResourceStateType(); + String srcResName = langSpec.toVariableName(getComponentName(srcResPath.getResourceHierarchy(), langSpec)); + param = langSpec.newVariableDeclaration(srcType, srcResName); + platformSpec.addFormParamAnnotation(param, srcResName); + parameters.add(param); // The state of the source resource to carry the data-flow. + for (ResourcePath refRes: ch.getReferenceResources()) { + if (!refRes.equals(resourceNode.getInSideResource(ch))) { + String refName = langSpec.toVariableName(getComponentName(refRes.getResourceHierarchy(), langSpec)); + param = langSpec.newVariableDeclaration(refRes.getResourceStateType(), refName); + platformSpec.addFormParamAnnotation(param, refName); + parameters.add(param); + } + } + MethodDeclaration updateAccessor = langSpec.newMethodDeclaration(updateMethodName, false, null, parameters); + if (isPut(cm)) { + platformSpec.addPutAnnotations(updateAccessor); + } else { + if (!isDelete(cm)) { + platformSpec.addPostAnnotations(updateAccessor); + } else { + platformSpec.addDeleteAnnotations(updateAccessor); + } + } + 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 += "/" + langSpec.toVariableName(srcResName); + } + platformSpec.addPathAnnotation(updateAccessor, resourcePath); + rootComponent.addMethod(updateAccessor); + } + + protected void declareInputAccessorInTheRootResource(String inputMethodName, + ArrayList rootInputParams, ChannelMember cm, String resourcePath, + TypeDeclaration rootComponent, IPlatformSpecific platformSpec, ILanguageSpecific langSpec) { + MethodDeclaration rootInputAccessor; + rootInputAccessor = langSpec.newMethodDeclaration(inputMethodName, false, null, rootInputParams); + if (isPut(cm)) { + platformSpec.addPutAnnotations(rootInputAccessor); + } else { + if (!isDelete(cm)) { + platformSpec.addPostAnnotations(rootInputAccessor); + } else { + platformSpec.addDeleteAnnotations(rootInputAccessor); + } + } + if (resourcePath.length() > 0) { + platformSpec.addPathAnnotation(rootInputAccessor, resourcePath); + } + rootComponent.addMethod(rootInputAccessor); + } + + protected String getGetterResourcePathAndPathParams(ResourcePath resPath, List pathParams, + IPlatformSpecific platformSpec, ILanguageSpecific langSpec) { int v = 1; List params = new ArrayList<>(); for (Expression pathParam: resPath.getPathParams()) { @@ -2425,14 +2623,48 @@ String paramName = var.getName(); params.add("{" + paramName + "}"); VariableDeclaration param = langSpec.newVariableDeclaration(var.getType(), paramName); - platformSpec.addParamAnnotation(param, paramName); + if (!platformSpec.isMonolithic()) platformSpec.addPathParamAnnotation(param, paramName); pathParams.add(param); } else if (pathParam instanceof Term) { Term var = (Term) pathParam; String paramName = "v" + v; params.add("{" + paramName + "}"); VariableDeclaration param = langSpec.newVariableDeclaration(var.getType(), paramName); - platformSpec.addParamAnnotation(param, paramName); + if (!platformSpec.isMonolithic()) platformSpec.addPathParamAnnotation(param, paramName); + pathParams.add(param); + } + } + return resPath.getResourceHierarchy().toResourcePath(params); + } + + protected String getUpdateResourcePathAndPathParams(ResourcePath resPath, ArrayList pathParams, boolean isRestAPI, + IPlatformSpecific platformSpec, ILanguageSpecific langSpec) { + int v = 1; + List params = new ArrayList<>(); + for (Expression pathParam: resPath.getPathParams()) { + if (pathParam instanceof Variable) { + Variable var = (Variable) pathParam; + String paramName = null; + if (isRestAPI) { + paramName = var.getName(); + } else { + paramName = "self" + (v > 1 ? v : ""); + } + params.add("{" + paramName + "}"); + VariableDeclaration param = langSpec.newVariableDeclaration(var.getType(), paramName); + if (isRestAPI) platformSpec.addPathParamAnnotation(param, paramName); + pathParams.add(param); + } else if (pathParam instanceof Term) { + Term var = (Term) pathParam; + String paramName = null; + if (isRestAPI) { + paramName = "v" + v; + } else { + paramName = "self" + (v > 1 ? v : ""); + } + params.add("{" + paramName + "}"); + VariableDeclaration param = langSpec.newVariableDeclaration(var.getType(), paramName); + if (isRestAPI) platformSpec.addPathParamAnnotation(param, paramName); pathParams.add(param); } v++; @@ -2440,4 +2672,49 @@ return resPath.getResourceHierarchy().toResourcePath(params); } + protected String getInputMethodResourcePathAndPathParams(ResourcePath resPath, ArrayList rootInputParams, + IPlatformSpecific platformSpec, ILanguageSpecific langSpec) { + int v = 1; + List params = new ArrayList<>(); + if (resPath.getLastParam() != null) { + Expression pathParam = resPath.getLastParam(); + if (pathParam instanceof Variable) { + Variable var = (Variable) pathParam; + String paramName = var.getName(); + params.add("{" + paramName + "}"); + VariableDeclaration param = langSpec.newVariableDeclaration(var.getType(), paramName); + if (!platformSpec.isMonolithic()) platformSpec.addPathParamAnnotation(param, paramName); + rootInputParams.add(param); + } else if (pathParam instanceof Term) { + Term var = (Term) pathParam; + String paramName = "v" + v; + params.add("{" + paramName + "}"); + VariableDeclaration param = langSpec.newVariableDeclaration(var.getType(), paramName); + if (!platformSpec.isMonolithic()) platformSpec.addPathParamAnnotation(param, paramName); + rootInputParams.add(param); + } + v++; + } + if (resPath.getParent() != null) { + for (Expression pathParam: resPath.getParent().getPathParams()) { + if (pathParam instanceof Variable) { + Variable var = (Variable) pathParam; + String paramName = var.getName(); + params.add("{" + paramName + "}"); + VariableDeclaration param = langSpec.newVariableDeclaration(var.getType(), paramName); + if (!platformSpec.isMonolithic()) platformSpec.addPathParamAnnotation(param, paramName); + rootInputParams.add(param); + } else if (pathParam instanceof Term) { + Term var = (Term) pathParam; + String paramName = "v" + v; + params.add("{" + paramName + "}"); + VariableDeclaration param = langSpec.newVariableDeclaration(var.getType(), paramName); + if (!platformSpec.isMonolithic()) platformSpec.addPathParamAnnotation(param, paramName); + rootInputParams.add(param); + } + v++; + } + } + return resPath.getResourceHierarchy().toResourcePath(params); + } } diff --git a/AlgebraicDataflowArchitectureModel/src/generators/IPlatformSpecific.java b/AlgebraicDataflowArchitectureModel/src/generators/IPlatformSpecific.java index a3f35c1..4e38370 100644 --- a/AlgebraicDataflowArchitectureModel/src/generators/IPlatformSpecific.java +++ b/AlgebraicDataflowArchitectureModel/src/generators/IPlatformSpecific.java @@ -17,8 +17,12 @@ boolean hasComponentAnnotation(); void addComponentAnnotations(TypeDeclaration component, String resourceName); void addGetAnnotations(MethodDeclaration getMethod); + void addPutAnnotations(MethodDeclaration getMethod); + void addPostAnnotations(MethodDeclaration getMethod); + void addDeleteAnnotations(MethodDeclaration getMethod); void addPathAnnotation(MethodDeclaration method, String resourcePath); - void addParamAnnotation(VariableDeclaration var, String paramName); + void addPathParamAnnotation(VariableDeclaration var, String paramName); + void addFormParamAnnotation(VariableDeclaration var, String paramName); void addClientFieldDeclaration(TypeDeclaration component); boolean hasPlatformSpecificImports(); void addPlatformSpecificImports(CompilationUnit cu); diff --git a/AlgebraicDataflowArchitectureModel/src/generators/JavaCodeGenerator.java b/AlgebraicDataflowArchitectureModel/src/generators/JavaCodeGenerator.java index 904f1ca..2a8d5f4 100644 --- a/AlgebraicDataflowArchitectureModel/src/generators/JavaCodeGenerator.java +++ b/AlgebraicDataflowArchitectureModel/src/generators/JavaCodeGenerator.java @@ -610,7 +610,11 @@ if (exp instanceof Variable) { Variable pathVar = (Variable) exp; String varName = "self" + (v > 1 ? v : ""); -// String varName = pathVar.getName(); + VariableDeclaration pathParam = new VariableDeclaration(pathVar.getType(), varName); + params.add(pathParam); // A path parameter to identify the self resource. + } else if (exp instanceof Term) { + Term pathVar = (Term) exp; + String varName = "self" + (v > 1 ? v : ""); VariableDeclaration pathParam = new VariableDeclaration(pathVar.getType(), varName); params.add(pathParam); // A path parameter to identify the self resource. } @@ -623,10 +627,10 @@ params.add(chParam); // A channel parameter to specify the context of the collaboration. } } - params.add(new VariableDeclaration(srcResPath.getResourceStateType(), srcResPath.getLeafResourceName())); // The state of the source resource to carry the data-flow. + params.add(new VariableDeclaration(srcResPath.getResourceStateType(), toVariableName(getComponentName(srcResPath.getResourceHierarchy())))); // The state of the source resource to carry the data-flow. for (ResourcePath ref: ch.getReferenceResources()) { if (!ref.equals(resourceNode.getInSideResource(ch))) { - params.add(new VariableDeclaration(ref.getResourceStateType(), ref.getLeafResourceName())); + params.add(new VariableDeclaration(ref.getResourceStateType(), toVariableName(getComponentName(ref.getResourceHierarchy())))); } } MethodDeclaration update = null; diff --git a/AlgebraicDataflowArchitectureModel/src/generators/JerseyCodeGenerator.java b/AlgebraicDataflowArchitectureModel/src/generators/JerseyCodeGenerator.java index ae93b32..8f25f75 100644 --- a/AlgebraicDataflowArchitectureModel/src/generators/JerseyCodeGenerator.java +++ b/AlgebraicDataflowArchitectureModel/src/generators/JerseyCodeGenerator.java @@ -673,9 +673,10 @@ params.add(param); // The state of the source resource to carry the data-flow. for (ResourcePath refRes: ch.getReferenceResources()) { if (!refRes.equals(resourceNode.getInSideResource(ch))) { - param = new VariableDeclaration(refRes.getResourceStateType(), refRes.getLeafResourceName()); - if (isRestAPI) param.addAnnotation(new Annotation("FormParam", "\"" + refRes.getLeafResourceName() + "\"")); - params.add(param); + String refName = toVariableName(getComponentName(refRes.getResourceHierarchy())); + param = new VariableDeclaration(refRes.getResourceStateType(), refName); + if (isRestAPI) param.addAnnotation(new Annotation("FormParam", "\"" + refName + "\"")); + params.add(param); } } MethodDeclaration update = null; @@ -801,8 +802,9 @@ params.add(param); // The state of the source resource to carry the data-flow. for (ResourcePath refRes: ch.getReferenceResources()) { if (!refRes.equals(resourceNode.getInSideResource(ch))) { - param = new VariableDeclaration(refRes.getResourceStateType(), refRes.getLeafResourceName()); - param.addAnnotation(new Annotation("FormParam", "\"" + refRes.getLeafResourceName() + "\"")); + String refName = toVariableName(getComponentName(refRes.getResourceHierarchy())); + param = new VariableDeclaration(refRes.getResourceStateType(), refName); + param.addAnnotation(new Annotation("FormParam", "\"" + refName + "\"")); params.add(param); } } @@ -850,7 +852,7 @@ // In each resource. ArrayList resInputParams = new ArrayList<>(); ArrayList rootInputParams = new ArrayList<>(); - String resourcePath = getInputMethodResourcePathAndPathParams(cm.getResource(), resInputParams, rootInputParams); // Path parameters for the input REST API. + String resourcePath = getInputMethodResourcePathAndPathParams(cm.getResource(), rootInputParams); // Path parameters for the input REST API. if (resourcePath.indexOf('/') > 0) { resourcePath = resourcePath.substring(resourcePath.indexOf('/')); } else { @@ -1295,7 +1297,7 @@ return resPath.getResourceHierarchy().toResourcePath(params); } - private static String getInputMethodResourcePathAndPathParams(ResourcePath resPath, ArrayList resInputParams, ArrayList rootInputParams) { + private static String getInputMethodResourcePathAndPathParams(ResourcePath resPath, ArrayList rootInputParams) { int v = 1; List params = new ArrayList<>(); if (resPath.getLastParam() != null) { diff --git a/AlgebraicDataflowArchitectureModel/src/generators/RestApiSpecific.java b/AlgebraicDataflowArchitectureModel/src/generators/RestApiSpecific.java index 379b7d1..b5af7f5 100644 --- a/AlgebraicDataflowArchitectureModel/src/generators/RestApiSpecific.java +++ b/AlgebraicDataflowArchitectureModel/src/generators/RestApiSpecific.java @@ -48,14 +48,34 @@ } @Override + public void addPutAnnotations(MethodDeclaration putMethod) { + putMethod.addAnnotation(new Annotation("PUT")); + } + + @Override + public void addPostAnnotations(MethodDeclaration postMethod) { + postMethod.addAnnotation(new Annotation("POST")); + } + + @Override + public void addDeleteAnnotations(MethodDeclaration deleteMethod) { + deleteMethod.addAnnotation(new Annotation("DELETE")); + } + + @Override public void addPathAnnotation(MethodDeclaration method, String resourcePath) { method.addAnnotation(new Annotation("Path", "\"" + resourcePath + "\"")); } @Override - public void addParamAnnotation(VariableDeclaration var, String paramName) { + public void addPathParamAnnotation(VariableDeclaration var, String paramName) { var.addAnnotation(new Annotation("PathParam", "\"" + paramName + "\"")); } + + @Override + public void addFormParamAnnotation(VariableDeclaration var, String paramName) { + var.addAnnotation(new Annotation("FormParam", "\"" + paramName + "\"")); + } @Override public void addClientFieldDeclaration(TypeDeclaration component) { diff --git a/AlgebraicDataflowArchitectureModel/src/generators/StandaloneSpecific.java b/AlgebraicDataflowArchitectureModel/src/generators/StandaloneSpecific.java index 8ecbdc4..a1fc80e 100644 --- a/AlgebraicDataflowArchitectureModel/src/generators/StandaloneSpecific.java +++ b/AlgebraicDataflowArchitectureModel/src/generators/StandaloneSpecific.java @@ -40,11 +40,27 @@ } @Override + public void addPutAnnotations(MethodDeclaration getMethod) { + } + + @Override + public void addPostAnnotations(MethodDeclaration getMethod) { + } + + @Override + public void addDeleteAnnotations(MethodDeclaration getMethod) { + } + + @Override public void addPathAnnotation(MethodDeclaration method, String resourcePath) { } @Override - public void addParamAnnotation(VariableDeclaration var, String paramName) { + public void addPathParamAnnotation(VariableDeclaration var, String paramName) { + } + + @Override + public void addFormParamAnnotation(VariableDeclaration var, String paramName) { } @Override