diff --git a/AlgebraicDataflowArchitectureModel/src/generators/JavaCodeGenerator.java b/AlgebraicDataflowArchitectureModel/src/generators/JavaCodeGenerator.java deleted file mode 100644 index b362030..0000000 --- a/AlgebraicDataflowArchitectureModel/src/generators/JavaCodeGenerator.java +++ /dev/null @@ -1,1470 +0,0 @@ -package generators; - -import java.util.AbstractMap; -import java.util.ArrayList; -import java.util.Arrays; -import java.util.HashMap; -import java.util.HashSet; -import java.util.List; -import java.util.Map; -import java.util.Map.Entry; -import java.util.Set; -import java.util.Stack; - -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; -import models.Edge; -import models.Node; -import models.algebra.Expression; -import models.algebra.Field; -import models.algebra.Parameter; -import models.algebra.Position; -import models.algebra.Symbol; -import models.algebra.Term; -import models.algebra.Type; -import models.algebra.Variable; -import models.dataConstraintModel.Channel; -import models.dataConstraintModel.ChannelMember; -import models.dataConstraintModel.DataConstraintModel; -import models.dataConstraintModel.ResourceHierarchy; -import models.dataConstraintModel.ResourcePath; -import models.dataConstraintModel.Selector; -import models.dataFlowModel.DataTransferModel; -import models.dataFlowModel.DataTransferChannel; -import models.dataFlowModel.DataTransferChannel.IResourceStateAccessor; -import models.dataFlowModel.PushPullAttribute; -import models.dataFlowModel.PushPullValue; -import models.dataFlowModel.ChannelNode; -import models.dataFlowModel.DataFlowEdge; -import models.dataFlowModel.DataFlowGraph; -import models.dataFlowModel.ResourceNode; -import models.dataFlowModel.StoreAttribute; - -/** - * Generator for plain Java prototypes - * - * @author Nitta - * - */ -public class JavaCodeGenerator { - public static final Type typeVoid = new Type("Void", "void"); - private static String defaultMainTypeName = "Main"; - static String mainTypeName = defaultMainTypeName; - - public static String getMainTypeName() { - return mainTypeName; - } - - public static void setMainTypeName(String mainTypeName) { - JavaCodeGenerator.mainTypeName = mainTypeName; - } - - public static void resetMainTypeName() { - JavaCodeGenerator.mainTypeName = defaultMainTypeName; - } - - public static String getComponentName(ResourceHierarchy res) { - String name = res.getResourceName(); - if (res.getNumParameters() > 0) { - if (name.length() > 3 && name.endsWith("ies")) { - name = name.substring(0, name.length() - 3) + "y"; - } else if (name.length() > 1 && name.endsWith("s")) { - name = name.substring(0, name.length() - 1); - } else { - name += "Element"; - } - } - return name.substring(0, 1).toUpperCase() + name.substring(1); - } - - public static String toVariableName(String name) { - return name.substring(0, 1).toLowerCase() + name.substring(1); - } - - public static Type getImplStateType(ResourceHierarchy res) { - Set children = res.getChildren(); - if (children == null || children.size() == 0) { - // leaf resource. - return res.getResourceStateType(); - } else { - ResourceHierarchy child = children.iterator().next(); - if (children.size() == 1 && child.getNumParameters() > 0) { - // map or list. - if (DataConstraintModel.typeList.isAncestorOf(res.getResourceStateType())) { - // list. - if (generatesComponent(child)) { - return new Type("List", "ArrayList<>", "List<" + getComponentName(child) + ">", DataConstraintModel.typeList); - } else { - return new Type("List", "ArrayList<>", "List<" + getImplStateType(child).getInterfaceTypeName() + ">", DataConstraintModel.typeList); - } - } else if (DataConstraintModel.typeMap.isAncestorOf(res.getResourceStateType())) { - // map. - if (generatesComponent(child)) { - return new Type("Map", "HashMap<>", "Map", DataConstraintModel.typeMap); - } else { - return new Type("Map", "HashMap<>", "Map", DataConstraintModel.typeMap); - } - } - return null; - } else { - // class - return res.getResourceStateType(); - } - } - } - - public static boolean generatesComponent(ResourceHierarchy res) { - if (res.getParent() == null) return true; - if (res.getChildren() == null || res.getChildren().size() == 0) return false; - if (res.getNumParameters() > 0 && res.getChildren().size() == 1 && res.getChildren().iterator().next().getNumParameters() > 0) return false; - if (res.getChildren().size() == 1 && res.getChildren().iterator().next().getNumParameters() > 0 - && (res.getChildren().iterator().next().getChildren() == null || res.getChildren().iterator().next().getChildren().size() == 0)) return false; - return true; -// return res.getParent() == null || !(res.getChildren() == null || res.getChildren().size() == 0); - } - - static public ArrayList doGenerate(DataFlowGraph graph, DataTransferModel model) { - ArrayList codes = new ArrayList<>(); - Map resourceComponents = new HashMap<>(); - Map resourceConstructors = new HashMap<>(); - List> getters = new ArrayList<>(); - Map> updates = new HashMap<>(); - Map> inputs = new HashMap<>(); - List> fields = new ArrayList<>(); - Map> descendantGetters = new HashMap<>(); - List> constructorParams = new ArrayList<>(); - - Map> dependedRootComponentGraph = getDependedRootComponentGraph(model); - ArrayList resources = determineResourceOrder(graph, dependedRootComponentGraph); - TypeDeclaration mainComponent = new TypeDeclaration(mainTypeName); - CompilationUnit mainCU = new CompilationUnit(mainComponent); - mainCU.addImport(new ImportDeclaration("java.util.*")); - codes.add(mainCU); - - // Declare the constructor of the main type. - MethodDeclaration mainConstructor = new MethodDeclaration(mainTypeName, true); - mainComponent.addMethod(mainConstructor); - - // For each resource node. - for (ResourceNode resourceNode: resources) { - TypeDeclaration component = null; - Set depends = new HashSet<>(); - Set refs = new HashSet<>(); - if (generatesComponent(resourceNode.getResourceHierarchy())) { - boolean f = false; - String resourceName = getComponentName(resourceNode.getResourceHierarchy()); - - component = resourceComponents.get(resourceNode.getResourceHierarchy()); - if (component == null) { - // Add compilation unit for each resource. - component = new TypeDeclaration(resourceName); - resourceComponents.put(resourceNode.getResourceHierarchy(), component); - CompilationUnit cu = new CompilationUnit(component); - cu.addImport(new ImportDeclaration("java.util.*")); - codes.add(cu); - - // Declare the field to refer to each resource in the main type. - if (resourceNode.getResourceHierarchy().getParent() == null) { - // For a root resource - String fieldInitializer = "new " + resourceName + "("; - for (Edge resToCh: resourceNode.getOutEdges()) { - DataFlowEdge re = (DataFlowEdge) resToCh; - if (((PushPullAttribute) re.getAttribute()).getSelectedOption() == PushPullValue.PUSH) { - for (Edge chToRes: re.getDestination().getOutEdges()) { - ResourceHierarchy dstRes = ((ResourceNode) chToRes.getDestination()).getResourceHierarchy(); - String resName = getComponentName(dstRes); - depends.add(dstRes); - fieldInitializer += toVariableName(resName) + ","; - f = true; - } - } - } - for (Edge chToRes : resourceNode.getInEdges()) { - for (Edge resToCh: chToRes.getSource().getInEdges()) { - DataFlowEdge re = (DataFlowEdge) resToCh; - ResourceHierarchy srcRes = ((ResourceNode) re.getSource()).getResourceHierarchy(); - String resName = getComponentName(srcRes); - if (((PushPullAttribute) re.getAttribute()).getSelectedOption() != PushPullValue.PUSH) { - depends.add(srcRes); - fieldInitializer += toVariableName(resName) + ","; - f = true; - } else { - ChannelNode cn = (ChannelNode) re.getDestination(); - if (cn.getIndegree() > 1 - || (cn.getIndegree() == 1 && cn.getChannel().getInputChannelMembers().iterator().next().getStateTransition().isRightPartial())) { - // Declare a field to cache the state of the source resource in the type of the destination resource. - ResourceHierarchy cacheRes = ((ResourceNode) re.getSource()).getResourceHierarchy(); - component.addField(new FieldDeclaration( - cacheRes.getResourceStateType(), cacheRes.getResourceName(), getInitializer(cacheRes))); - } - } - } - } - for (ResourceHierarchy dependedRes: dependedRootComponentGraph.keySet()) { - for (ResourceHierarchy dependingRes: dependedRootComponentGraph.get(dependedRes)) { - if (resourceNode.getResourceHierarchy().equals(dependingRes)) { - // Declare a field to refer to outside resources. - depends.add(dependedRes); - String resName = getComponentName(dependedRes); - fieldInitializer += toVariableName(resName) + ","; - f = true; - } - } - } - for (Channel ch : model.getChannels()) { - DataTransferChannel c = (DataTransferChannel) ch; - if (resourceNode.getOutSideResource(c) != null) { - for (ResourcePath res: c.getReferenceResources()) { - if (!refs.contains(res) && !depends.contains(res.getResourceHierarchy())) { - refs.add(res); - String refResName = res.getLeafResourceName(); - fieldInitializer += toVariableName(refResName) + ","; - f = true; - } - } - } - } - if (f) fieldInitializer = fieldInitializer.substring(0, fieldInitializer.length() - 1); - fieldInitializer += ")"; - FieldDeclaration field = new FieldDeclaration(new Type(resourceName, resourceName), resourceNode.getResourceName()); - mainComponent.addField(field); - Block mainConstructorBody = mainConstructor.getBody(); - if (mainConstructorBody == null) { - mainConstructorBody = new Block(); - mainConstructor.setBody(mainConstructorBody); - } - mainConstructorBody.addStatement(resourceNode.getResourceName() + " = " + fieldInitializer + ";"); - } - - // Declare the field to store the state in the type of each resource. - if (((StoreAttribute) resourceNode.getAttribute()).isStored()) { - ResourceHierarchy res = resourceNode.getResourceHierarchy(); - Set children = res.getChildren(); - if (children == null || children.size() == 0) { - // leaf resource. - Type fieldType = getImplStateType(res); - component.addField(new FieldDeclaration(fieldType, "value", getInitializer(res))); - } else { - ResourceHierarchy child = children.iterator().next(); - if (children.size() == 1 && child.getNumParameters() > 0) { - // map or list. - component.addField(new FieldDeclaration(getImplStateType(res), "value", getInitializer(res))); - } else { - // class - for (ResourceHierarchy c: children) { - String childTypeName = getComponentName(c); - Type childType = null; - if (generatesComponent(c)) { - // The child has a component. - childType = new Type(childTypeName, childTypeName); - String fieldName = toVariableName(childTypeName); - component.addField(new FieldDeclaration(childType, fieldName, "new " + childTypeName + "()")); - } - } - } - } - } - - // Declare the getter method to obtain the resource state in this component. - MethodDeclaration stateGetter = new MethodDeclaration("getValue", getImplStateType(resourceNode.getResourceHierarchy())); - component.addMethod(stateGetter); - - // Declare the accessor method in the main type to call the getter method. - declareAccessorMethodInMainComponent(resourceNode, mainComponent); - } - if (component != null) { - // (#1) Declare the getter methods in this resource to obtain descendant resources. (complementary to #2) - Set descendants = descendantGetters.get(resourceNode.getResourceHierarchy()); - if (descendants == null) { - descendants = new HashSet<>(); - descendantGetters.put(resourceNode.getResourceHierarchy(), descendants); - } - for (ResourceNode child: resourceNode.getChildren()) { - // A descendant of the child may generate a component. - List params = new ArrayList<>(); - int v = 1; - ResourceNode descendant = child; - Set childNodes; - do { - Expression param = descendant.getPrimaryResourcePath().getLastParam(); - if (param != null) { - if (param instanceof Variable) { - Variable var = (Variable) param; - params.add(new VariableDeclaration(var.getType(), var.getName())); - } else if (param instanceof Term) { - Term var = (Term) param; - params.add(new VariableDeclaration(var.getType(), "v" + v)); - } - v++; - } - if (generatesComponent(descendant.getResourceHierarchy())) { - // If the descendant generates a component. - if (!descendants.contains(descendant.getResourceHierarchy())) { - descendants.add(descendant.getResourceHierarchy()); - String descendantCompName = getComponentName(descendant.getResourceHierarchy()); - Type descendantType = new Type(descendantCompName, descendantCompName); - MethodDeclaration descendantGetter = null; - if (params.size() == 0) { - descendantGetter = new MethodDeclaration("get" + descendantCompName, descendantType); - } else { - descendantGetter = new MethodDeclaration("get" + descendantCompName, false, descendantType, params); - } - component.addMethod(descendantGetter); - } - break; - } - childNodes = descendant.getChildren(); - } while (childNodes != null && childNodes.size() == 1 && (descendant = childNodes.iterator().next()) != null); - } - } - } - - // Declare the state field and reference fields in the parent component. - if (component == null) { - // Declare reference fields for push/pull data transfer. - boolean noPullTransfer = true; - for (Edge chToRes : resourceNode.getInEdges()) { - for (Edge resToCh: chToRes.getSource().getInEdges()) { - DataFlowEdge re = (DataFlowEdge) resToCh; - DataTransferChannel ch = ((ChannelNode) re.getDestination()).getChannel(); - ResourcePath srcRes = ((ResourceNode) re.getSource()).getOutSideResource(ch); - // Check if the input resource is outside of the channel scope. - boolean outsideInputResource = false; - for (ChannelMember cm: ch.getInputChannelMembers()) { - if (cm.getResource().equals(srcRes) && 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 (resourceNode.getInSideResources().contains(cm.getResource()) && cm.isOutside()) { - outsideOutputResource = true; // Regarded as push transfer. - break; - } - } - if ((((PushPullAttribute) re.getAttribute()).getSelectedOption() != PushPullValue.PUSH && !outsideOutputResource) || outsideInputResource) { - noPullTransfer = false; - } - } - } - // Declare the state field in the parent component. - ResourceHierarchy res = resourceNode.getResourceHierarchy(); - if (((StoreAttribute) resourceNode.getAttribute()).isStored() && noPullTransfer && res.getNumParameters() == 0) { - String resName = getComponentName(res); - FieldDeclaration stateField = new FieldDeclaration(res.getResourceStateType(), toVariableName(resName)); - fields.add(new AbstractMap.SimpleEntry<>(resourceNode.getParent().getResourceHierarchy(), stateField)); - constructorParams.add(new AbstractMap.SimpleEntry<>(resourceNode.getParent().getResourceHierarchy(), new VariableDeclaration(res.getResourceStateType(), toVariableName(resName)))); - } - } - - // (#2) Declare the getter method to obtain the resource state in an ancestor component. (complementary to #1) - if (component == null) { - // No component is created for this resource. - ResourceNode ancestorNode = resourceNode; - Stack ancestors = new Stack<>(); - do { - ancestors.push(ancestorNode); - ancestorNode = ancestorNode.getParent(); - } while (!generatesComponent(ancestorNode.getResourceHierarchy())); - List getterParams = new ArrayList<>(); - int v = 1; - while (ancestors.size() > 0) { - ResourceNode curAncestor = ancestors.pop(); - Expression param = curAncestor.getPrimaryResourcePath().getLastParam(); - if (param instanceof Variable) { - Variable var = (Variable) param; - getterParams.add(new VariableDeclaration(var.getType(), var.getName())); - } else if (param instanceof Term) { - Term var = (Term) param; - getterParams.add(new VariableDeclaration(var.getType(), "v" + v)); - } - v++; - } - String getterName = "get" + getComponentName(resourceNode.getResourceHierarchy()); - boolean bExists = false; - for (Map.Entry entry: getters) { - ResourceHierarchy r = entry.getKey(); - MethodDeclaration m = entry.getValue(); - if (r == ancestorNode.getResourceHierarchy() && m.getName().equals(getterName) - && (m.getParameters() == null ? 0 : m.getParameters().size()) == getterParams.size()) { - bExists = true; - break; - } - } - if (!bExists) { - Type resType = getImplStateType(resourceNode.getResourceHierarchy()); - MethodDeclaration stateGetter = null; - if (getterParams.size() == 0) { - stateGetter = new MethodDeclaration(getterName, resType); - } else { - stateGetter = new MethodDeclaration(getterName, false, resType, getterParams); - } - getters.add(new AbstractMap.SimpleEntry<>(ancestorNode.getResourceHierarchy(), stateGetter)); - - // Declare the accessor method in the main type to call the getter method. - declareAccessorMethodInMainComponent(resourceNode, mainComponent); - } - } - - // Declare reference fields for push data transfer. - for (Edge resToCh : resourceNode.getOutEdges()) { - DataFlowEdge re = (DataFlowEdge) resToCh; - ChannelNode directDstChNode = (ChannelNode) re.getDestination(); - DataTransferChannel directDstCh = directDstChNode.getChannel(); - // Check if the input resource is outside of the channel scope. - boolean outsideInputResource = false; - for (ChannelMember cm: directDstCh.getInputChannelMembers()) { - if (cm.getResource().equals(resourceNode.getOutSideResource(directDstCh)) && cm.isOutside()) { - outsideInputResource = true; // Regarded as pull transfer. - break; - } - } - // Should take into account the channel hierarchy. - Set ancestorDstChannels = directDstChNode.getAncestors(); - Set descendantDstChannels = directDstChNode.getDescendants(); - Set outEdges = new HashSet<>(); - outEdges.addAll(directDstChNode.getOutEdges()); - for (ChannelNode ancestorDst: ancestorDstChannels) { - outEdges.addAll(ancestorDst.getOutEdges()); - } - for (ChannelNode descendantDst: descendantDstChannels) { - outEdges.addAll(descendantDst.getOutEdges()); - } - for (Edge chToRes: outEdges) { - ResourceHierarchy dstRes = ((ResourceNode) chToRes.getDestination()).getResourceHierarchy(); - ChannelNode chNode = (ChannelNode) chToRes.getSource(); - DataTransferChannel ch = chNode.getChannel(); - // Check if the output resource is outside of the channel scope. - boolean outsideOutputResource = false; - for (ChannelMember cm: ch.getOutputChannelMembers()) { - if (((ResourceNode) chToRes.getDestination()).getInSideResources().contains(cm.getResource()) && cm.isOutside()) { - outsideOutputResource = true; // Regarded as push transfer. - break; - } - } - // Also take into account the channel hierarchy to determine push/pull transfer. - if (descendantDstChannels.contains(chNode)) { - outsideOutputResource = true; // Regarded as (broadcasting) push transfer. - } - if (ancestorDstChannels.contains(chNode)) { - outsideInputResource = true; // Regarded as (collecting) pull transfer. - } - if ((((PushPullAttribute) re.getAttribute()).getSelectedOption() == PushPullValue.PUSH && !outsideInputResource) || outsideOutputResource) { - // Declare a field to refer to the destination resource of push transfer. - if (!generatesComponent(dstRes)) { - dstRes = dstRes.getParent(); - } - String dstResName = getComponentName(dstRes); - depends.add(dstRes); - FieldDeclaration dstRefField = new FieldDeclaration(new Type(dstResName, dstResName), toVariableName(dstResName)); - VariableDeclaration dstRefVar = new VariableDeclaration(new Type(dstResName, dstResName), toVariableName(dstResName)); - if (component != null) { - // A component is created for this resource. - if (resourceNode.getResourceHierarchy() != dstRes) { - component.addField(dstRefField); - if (!outsideOutputResource) { - constructorParams.add(new AbstractMap.SimpleEntry<>(resourceNode.getResourceHierarchy(), dstRefVar)); - } - } - } else { - // No component is created for this resource. - if (resourceNode.getParent().getResourceHierarchy() != dstRes) { - fields.add(new AbstractMap.SimpleEntry<>(resourceNode.getParent().getResourceHierarchy(), dstRefField)); - if (!outsideOutputResource) { - constructorParams.add(new AbstractMap.SimpleEntry<>(resourceNode.getParent().getResourceHierarchy(), dstRefVar)); - } - } - } - if (outsideOutputResource) { - // When the reference to the destination resource can vary. - if (dstRes.getParent() != null) { - // Reference to root resource. - ResourceHierarchy dstRootRes = dstRes.getRoot(); - String dstRootResName = getComponentName(dstRootRes); - FieldDeclaration dstRootRefField = new FieldDeclaration(new Type(dstRootResName, dstRootResName), toVariableName(dstRootResName)); - VariableDeclaration dstRootRefVar = new VariableDeclaration(new Type(dstRootResName, dstRootResName), toVariableName(dstRootResName)); - if (component != null) { - // A component is created for this resource. - component.addField(dstRootRefField); - constructorParams.add(new AbstractMap.SimpleEntry<>(resourceNode.getResourceHierarchy(), dstRootRefVar)); - } else { - // No component is created for this resource. - fields.add(new AbstractMap.SimpleEntry<>(resourceNode.getParent().getResourceHierarchy(), dstRootRefField)); - constructorParams.add(new AbstractMap.SimpleEntry<>(resourceNode.getParent().getResourceHierarchy(), dstRootRefVar)); - } - } - } - } - } - } - // Declare update methods called by other resources for push data transfer - // and reference fields for pull data transfer. - for (Edge chToRes : resourceNode.getInEdges()) { - ChannelNode directSrcChannel = (ChannelNode) chToRes.getSource(); - DataTransferChannel ch = directSrcChannel.getChannel(); - // Should take into account the channel hierarchy. - Set ancestorSrcChannels = directSrcChannel.getAncestors(); - Set descendantSrcChannels = directSrcChannel.getDescendants(); - Set inEdges = new HashSet<>(); - inEdges.addAll(directSrcChannel.getInEdges()); - for (ChannelNode ancestorSrc: ancestorSrcChannels) { - inEdges.addAll(ancestorSrc.getInEdges()); - } - for (ChannelNode descendantSrc: descendantSrcChannels) { - inEdges.addAll(descendantSrc.getInEdges()); - } - for (Edge resToCh: inEdges) { - // For each data transfer from srcResPath:ResourcePath to resourceNode:ResourceNode. - DataFlowEdge re = (DataFlowEdge) resToCh; - ChannelNode indirectSrcChNode = (ChannelNode) re.getDestination(); - DataTransferChannel indirectSrcCh = indirectSrcChNode.getChannel(); - ResourcePath srcResPath = ((ResourceNode) re.getSource()).getOutSideResource(indirectSrcCh); - // Check if the input resource is outside of the channel scope. - boolean outsideInputResource = false; - for (ChannelMember cm: indirectSrcCh.getInputChannelMembers()) { - if (cm.getResource().equals(srcResPath) && cm.isOutside()) { - outsideInputResource = true; // Regarded as pull transfer. - break; - } - } - // 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())) { - out = cm; - if (cm.isOutside()) { - outsideOutputResource = true; // Regarded as push transfer. - break; - } - } - } - // Also take into account the channel hierarchy to determine push/pull transfer. - if (ancestorSrcChannels.contains(indirectSrcChNode)) { - outsideOutputResource = true; // Regarded as (broadcasting) push transfer. - } - if (descendantSrcChannels.contains(indirectSrcChNode)) { - outsideInputResource = true; // Regarded as (collecting) pull transfer. - } - String srcResName = getComponentName(srcResPath.getResourceHierarchy()); - ResourcePath srcRes2 = srcResPath; - String srcResName2 = srcResName; - if (!generatesComponent(srcResPath.getResourceHierarchy())) { - srcRes2 = srcResPath.getParent(); - srcResName2 = getComponentName(srcRes2.getResourceHierarchy()); - } - if ((((PushPullAttribute) re.getAttribute()).getSelectedOption() != PushPullValue.PUSH && !outsideOutputResource) || outsideInputResource) { - // Declare a field to refer to the source resource of pull transfer. - depends.add(srcRes2.getResourceHierarchy()); - FieldDeclaration srcRefField = new FieldDeclaration(new Type(srcResName2, srcResName2), toVariableName(srcResName2)); - VariableDeclaration srcRefVar = new VariableDeclaration(new Type(srcResName2, srcResName2), toVariableName(srcResName2)); - if (component != null) { - // A component is created for this resource. - if (resourceNode.getResourceHierarchy() != srcRes2.getResourceHierarchy()) { - component.addField(srcRefField); - if (!outsideInputResource) { - constructorParams.add(new AbstractMap.SimpleEntry<>(resourceNode.getResourceHierarchy(), srcRefVar)); - } - } - } else { - // No component is created for this resource. - if (resourceNode.getParent().getResourceHierarchy() != srcRes2.getResourceHierarchy()) { - fields.add(new AbstractMap.SimpleEntry<>(resourceNode.getParent().getResourceHierarchy(), srcRefField)); - if (!outsideInputResource) { - constructorParams.add(new AbstractMap.SimpleEntry<>(resourceNode.getParent().getResourceHierarchy(), srcRefVar)); - } - } - } - if (outsideInputResource) { - // When the reference to the source resource can vary. - if (srcRes2.getParent() != null) { - // Reference to its root resource. - ResourcePath srcRootRes = srcRes2.getRoot(); - String srcRootResName = getComponentName(srcRootRes.getResourceHierarchy()); - FieldDeclaration srcRootRefField = new FieldDeclaration(new Type(srcRootResName, srcRootResName), toVariableName(srcRootResName)); - VariableDeclaration srcRootRefVar = new VariableDeclaration(new Type(srcRootResName, srcRootResName), toVariableName(srcRootResName)); - if (component != null) { - // A component is created for this resource. - component.addField(srcRootRefField); - constructorParams.add(new AbstractMap.SimpleEntry<>(resourceNode.getResourceHierarchy(), srcRootRefVar)); - } else { - // No component is created for this resource. - fields.add(new AbstractMap.SimpleEntry<>(resourceNode.getParent().getResourceHierarchy(), srcRootRefField)); - constructorParams.add(new AbstractMap.SimpleEntry<>(resourceNode.getParent().getResourceHierarchy(), srcRootRefVar)); - } - } - } - } else { - // Declare an update method in the type of the destination resource. - ArrayList params = new ArrayList<>(); - int v = 1; - for (Expression exp: out.getResource().getPathParams()) { - if (exp instanceof Variable) { - Variable pathVar = (Variable) 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. - } 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. - } - v++; - } - for (Selector selector: ch.getAllSelectors()) { - if (selector.getExpression() instanceof Variable) { - Variable selVar = (Variable) selector.getExpression(); - VariableDeclaration chParam = new VariableDeclaration(selVar.getType(), selVar.getName()); - params.add(chParam); // A channel parameter to specify the context of the collaboration. - } - } - 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(), toVariableName(getComponentName(ref.getResourceHierarchy())))); - } - } - MethodDeclaration update = null; - if (component != null) { - // A component is created for this resource. - update = new MethodDeclaration("updateFrom" + srcResName, false, typeVoid, params); - component.addMethod(update); - } else { - // No component is created for this resource. - String resourceName = getComponentName(resourceNode.getResourceHierarchy()); - String updateMethodName = "update" + resourceName + "From" + srcResName; - Map nameToMethod = updates.get(resourceNode.getParent().getResourceHierarchy()); - if (nameToMethod == null) { - nameToMethod = new HashMap<>(); - updates.put(resourceNode.getParent().getResourceHierarchy(), nameToMethod); - } - if (nameToMethod.get(updateMethodName) == null) { - update = new MethodDeclaration(updateMethodName, false, typeVoid, params); - nameToMethod.put(updateMethodName, update); - } - } - } - } - } - // Declare a field to refer to outside resources. - if (resourceNode.getParent() == null) { - for (ResourceHierarchy dependedRes: dependedRootComponentGraph.keySet()) { - for (ResourceHierarchy dependingRes: dependedRootComponentGraph.get(dependedRes)) { - if (resourceNode.getResourceHierarchy().equals(dependingRes)) { - // Declare a field to refer to outside resources. - depends.add(dependedRes); - String resName = getComponentName(dependedRes); - FieldDeclaration refField = new FieldDeclaration(new Type(resName, resName), toVariableName(resName)); - VariableDeclaration refVar = new VariableDeclaration(new Type(resName, resName), toVariableName(resName)); - if (component != null) { - // A component is created for this resource. - boolean existsField = false; - for (FieldDeclaration field: component.getFields()) { - if (field.getName().equals(refVar.getName())) { - existsField = true; - break; - } - } - if (!existsField) { - component.addField(refField); - } - constructorParams.add(new AbstractMap.SimpleEntry<>(resourceNode.getResourceHierarchy(), refVar)); - } else { - // No component is created for this resource. - fields.add(new AbstractMap.SimpleEntry<>(resourceNode.getParent().getResourceHierarchy(), refField)); - constructorParams.add(new AbstractMap.SimpleEntry<>(resourceNode.getParent().getResourceHierarchy(), refVar)); - } - } - } - } - } - // Declare a field to refer to the reference resource. - for (Channel ch : model.getChannels()) { - DataTransferChannel c = (DataTransferChannel) ch; - if (resourceNode.getOutSideResource(c) != null) { - for (ResourcePath res: c.getReferenceResources()) { - if (!refs.contains(res) && !depends.contains(res.getResourceHierarchy())) { - refs.add(res); - String refResName = getComponentName(res.getResourceHierarchy()); - FieldDeclaration refResField = new FieldDeclaration(new Type(refResName, refResName), res.getLeafResourceName()); - VariableDeclaration refResVar = new VariableDeclaration(new Type(refResName, refResName), res.getLeafResourceName()); - if (component != null) { - // A component is created for this resource. - component.addField(refResField); - constructorParams.add(new AbstractMap.SimpleEntry<>(resourceNode.getResourceHierarchy(), refResVar)); - } else { - // No component is created for this resource. - fields.add(new AbstractMap.SimpleEntry<>(resourceNode.getParent().getResourceHierarchy(), refResField)); - constructorParams.add(new AbstractMap.SimpleEntry<>(resourceNode.getParent().getResourceHierarchy(), refResVar)); - } - } - } - } - } - - // Declare the input method in this component and the main component. - for (Channel ch : model.getInputChannels()) { - for (ChannelMember cm : ((DataTransferChannel) ch).getOutputChannelMembers()) { - if (resourceNode.getInSideResources().contains(cm.getResource())) { - Expression message = cm.getStateTransition().getMessageExpression(); - if (message instanceof Term) { - // In each resource. - ArrayList resInputParams = new ArrayList<>(); - ArrayList mainInputParams = new ArrayList<>(); - // 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. - - // Channel parameters to specify the context of the collaboration. - int v = 1; - for (Selector selector: ch.getSelectors()) { - if (selector.getExpression() instanceof Variable) { - Variable selVar = (Variable) selector.getExpression(); - resInputParams.add(new VariableDeclaration(selVar.getType(), selVar.getName())); - mainInputParams.add(new VariableDeclaration(selVar.getType(), selVar.getName())); - } else if (selector.getExpression() instanceof Term) { - Term var = (Term) selector.getExpression(); - resInputParams.add(new VariableDeclaration(var.getType(), "v" + v)); - mainInputParams.add(new VariableDeclaration(var.getType(), "v" + v)); - } - v++; - } - if (ch.getParent() != null) { - for (Selector selector: ch.getParent().getAllSelectors()) { - if (selector.getExpression() instanceof Variable) { - Variable selVar = (Variable) selector.getExpression(); - mainInputParams.add(new VariableDeclaration(selVar.getType(), selVar.getName())); - } else if (selector.getExpression() instanceof Term) { - Term var = (Term) selector.getExpression(); - mainInputParams.add(new VariableDeclaration(var.getType(), "v" + v)); - } - v++; - } - } - // Message parameters to carry the data-flows. - for (Map.Entry varEnt: message.getVariables().entrySet()) { - Variable var = varEnt.getValue(); - String refVarName = null; - for (ChannelMember refCm: ((DataTransferChannel) ch).getReferenceChannelMembers()) { - Expression varExp = refCm.getStateTransition().getMessageExpression().getSubTerm(varEnt.getKey()); - if (varExp != null && varExp instanceof Variable) { - if (refCm.getStateTransition().getCurStateExpression().contains(varExp)) { - refVarName = refCm.getResource().getLeafResourceName(); - break; - } - } - } - if (refVarName != null) { - // var has come from a reference resource. - resInputParams.add(new VariableDeclaration(var.getType(), refVarName)); - } else { - // var has not come from a reference resource. - resInputParams.add(new VariableDeclaration(var.getType(), var.getName())); - boolean bExists = false; - for (VariableDeclaration mainParam: mainInputParams) { - if (mainParam.getName().equals(var.getName()) ) { - bExists = true; - break; - } - } - if (!bExists) { - mainInputParams.add(new VariableDeclaration(var.getType(), var.getName())); - } - } - } - String inputMethodName = ((Term) message).getSymbol().getImplName(); - if (((DataTransferChannel) ch).getOutputChannelMembers().size() > 1) { - inputMethodName += "For" + getComponentName(cm.getResource().getResourceHierarchy()); - } - MethodDeclaration input = new MethodDeclaration(inputMethodName, false, typeVoid, resInputParams); - if (component != null) { - // A component is created for this resource. - component.addMethod(input); - } else { - // No component is created for this resource. - Map nameToMethod = inputs.get(resourceNode.getParent().getResourceHierarchy()); - if (nameToMethod == null) { - nameToMethod = new HashMap<>(); - inputs.put(resourceNode.getParent().getResourceHierarchy(), nameToMethod); - } - if (nameToMethod.get(inputMethodName) == null) { - nameToMethod.put(inputMethodName, input); - } - } - - // In the main type. - String messageSymbol = ((Term) message).getSymbol().getImplName(); - input = getMethod(mainComponent, messageSymbol, mainInputParams); - if (input == null) { - input = new MethodDeclaration(messageSymbol, false, typeVoid, mainInputParams); - mainComponent.addMethod(input); - } else { - // Add type to a parameter without type. - for (VariableDeclaration param: input.getParameters()) { - if (param.getType() == null) { - for (VariableDeclaration p: mainInputParams) { - if (param.getName().equals(p.getName()) && p.getType() != null) { - param.setType(p.getType()); - } - } - } - } - } - } else if (message instanceof Variable) { - // In each resource. - ArrayList resInputParams = new ArrayList<>(); - ArrayList mainInputParams = new ArrayList<>(); - int v = 1; - if (cm.getResource().getLastParam() != null) { - Expression param = cm.getResource().getLastParam(); - if (param instanceof Variable) { - Variable var = (Variable) param; - resInputParams.add(new VariableDeclaration(var.getType(), var.getName())); - mainInputParams.add(new VariableDeclaration(var.getType(), var.getName())); - } else if (param instanceof Term) { - Term var = (Term) param; - resInputParams.add(new VariableDeclaration(var.getType(), "v" + v)); - mainInputParams.add(new VariableDeclaration(var.getType(), "v" + v)); - } - v++; - } - if (cm.getResource().getParent() != null) { - for (Expression param: cm.getResource().getParent().getPathParams()) { - if (param instanceof Variable) { - Variable var = (Variable) param; - mainInputParams.add(new VariableDeclaration(var.getType(), var.getName())); - } else if (param instanceof Term) { - Term var = (Term) param; - mainInputParams.add(new VariableDeclaration(var.getType(), "v" + v)); - } - v++; - } - } - String inputMethodName = ((Variable) message).getName(); - if (((DataTransferChannel) ch).getOutputChannelMembers().size() > 1) { - inputMethodName += "For" + getComponentName(cm.getResource().getResourceHierarchy()); - } - MethodDeclaration input = null; - if (resInputParams.size() > 0) { - input = new MethodDeclaration(inputMethodName, false, typeVoid, resInputParams); - } else { - input = new MethodDeclaration(inputMethodName, false, typeVoid, null); - } - if (component != null) { - // A component is created for this resource. - component.addMethod(input); - } else { - // No component is created for this resource. - Map nameToMethod = inputs.get(resourceNode.getParent().getResourceHierarchy()); - if (nameToMethod == null) { - nameToMethod = new HashMap<>(); - inputs.put(resourceNode.getParent().getResourceHierarchy(), nameToMethod); - } - if (nameToMethod.get(inputMethodName) == null) { - nameToMethod.put(inputMethodName, input); - } - } - - // In the main type. - String messageSymbol = ((Variable) message).getName(); - input = getMethod(mainComponent, messageSymbol, mainInputParams); - if (input == null) { - if (mainInputParams.size() > 0) { - input = new MethodDeclaration(messageSymbol, false, typeVoid, mainInputParams); - } else { - input = new MethodDeclaration(messageSymbol, false, typeVoid, null); - } - mainComponent.addMethod(input); - } - } - } - } - } - } - - // Add leaf getter methods to the parent components. - for (Map.Entry entry: getters) { - resourceComponents.get(entry.getKey()).addMethod(entry.getValue()); - } - - // Add leaf update methods to the parent components. - for (Map.Entry> entry: updates.entrySet()) { - for (MethodDeclaration update: entry.getValue().values()) { - resourceComponents.get(entry.getKey()).addMethod(update); - } - } - - // Add leaf input methods to the parent components. - for (Map.Entry> entry: inputs.entrySet()) { - for (MethodDeclaration input: entry.getValue().values()) { - resourceComponents.get(entry.getKey()).addMethod(input); - } - } - - // Add leaf reference fields to the parent components. - for (Map.Entry entry: fields) { - boolean existsField = false; - for (FieldDeclaration field: resourceComponents.get(entry.getKey()).getFields()) { - if (field.getName().equals(entry.getValue().getName())) { - existsField = true; - break; - } - } - if (!existsField) { - resourceComponents.get(entry.getKey()).addField(entry.getValue()); - } - } - - // Add constructor parameters to the ancestor components. - for (ResourceNode root: graph.getRootResourceNodes()) { - addConstructorParameters(root.getResourceHierarchy(), resourceComponents, resourceConstructors, constructorParams); - } - - // Declare the Pair class. - boolean isCreatedPair = false; - for (ResourceNode rn : resources) { - if (isCreatedPair) continue; - if (rn.getResourceStateType() != null && model.getType("Pair").isAncestorOf(rn.getResourceStateType())) { - TypeDeclaration type = new TypeDeclaration("Pair"); - type.addField(new FieldDeclaration(new Type("Double", "T"), "left")); - type.addField(new FieldDeclaration(new Type("Double", "T"), "right")); - - MethodDeclaration constructor = new MethodDeclaration("Pair", true); - constructor.addParameter(new VariableDeclaration(new Type("Double", "T"), "left")); - constructor.addParameter(new VariableDeclaration(new Type("Double", "T"), "right")); - Block block = new Block(); - block.addStatement("this.left = left;"); - block.addStatement("this.right = right;"); - constructor.setBody(block); - type.addMethod(constructor); - - for(FieldDeclaration field : type.getFields()) { - MethodDeclaration getter = new MethodDeclaration( - "get" + field.getName().substring(0,1).toUpperCase() + field.getName().substring(1), - new Type("Double","T")); - getter.setBody(new Block()); - getter.getBody().addStatement("return " + field.getName() + ";"); - type.addMethod(getter); - } - - CompilationUnit cu = new CompilationUnit(type); - cu.addImport(new ImportDeclaration("java.util.*")); - codes.add(cu); - - isCreatedPair = true; - } - } - -// HashSet tmps = new HashSet<>(); -// HashSet cont = new HashSet<>(); -// for (MethodDeclaration method : mainType.getMethods()) { -// if (!tmps.contains(method.getName())) -// tmps.add(method.getName()); -// else -// cont.add(method.getName()); -// } -// for (MethodDeclaration method : mainType.getMethods()) { -// if (cont.contains(method.getName())) { -// method.setName(method.getName() + method.getParameters().get(0).getName().substring(0, 1).toUpperCase() -// + method.getParameters().get(0).getName().substring(1)); -// } -// } - return codes; - } - - private static Map> getDependedRootComponentGraph(DataTransferModel model) { - Map> dependedComponentGraph = new HashMap<>(); - for (Channel ch: model.getChannels()) { - Set inRes = new HashSet<>(); - Set outRes = new HashSet<>(); - getDependedRootComponentGraphSub(ch, inRes, outRes, true); - if (outRes.size() > 0 && inRes.size() > 0) { - for (ResourceHierarchy out: outRes) { - for (ResourceHierarchy in: inRes) { - Set dependings = dependedComponentGraph.get(out.getRoot()); - if (dependings == null) { - dependings = new HashSet<>(); - dependedComponentGraph.put(out.getRoot(), dependings); - } - if (!out.getRoot().equals(in.getRoot())) { - dependings.add(in.getRoot()); - } - } - } - } - } - return dependedComponentGraph; - } - - private static void getDependedRootComponentGraphSub(Channel ch, Set inRes, Set outRes, boolean isRoot) { - DataTransferChannel dtCh = (DataTransferChannel) ch; - for (ChannelMember cm: dtCh.getChannelMembers()) { - if (!isRoot && !cm.isOutside()) { - outRes.add(cm.getResource().getResourceHierarchy()); // dependency to a descendant channel resource. - } - if (cm.isOutside()) { - outRes.add(cm.getResource().getResourceHierarchy()); // dependency to an outside resource. - } else { - inRes.add(cm.getResource().getResourceHierarchy()); // dependency from an inside resource. - } - } - for (Channel childCh: ch.getChildren()) { - getDependedRootComponentGraphSub(childCh, inRes, outRes, false); - } - } - - private static ArrayList determineResourceOrder(DataFlowGraph graph, Map> dependedRootComponentGraph) { - ArrayList resources = new ArrayList<>(); - Set visited = new HashSet<>(); - for (Node n : graph.getResourceNodes()) { - ResourceNode resNode = (ResourceNode) n; - topologicalSort(resNode, graph, dependedRootComponentGraph, visited, resources); - } - return resources; - } - - static private void topologicalSort(ResourceNode curResNode, DataFlowGraph graph, Map> dependedRootComponentGraph, Set visited, List orderedList) { - if (visited.contains(curResNode)) return; - visited.add(curResNode); - // For each incoming PUSH transfer. - for (Edge chToRes: curResNode.getInEdges()) { - for (Edge resToCh: chToRes.getSource().getInEdges()) { - DataFlowEdge re = (DataFlowEdge) resToCh; - if (((PushPullAttribute) re.getAttribute()).getSelectedOption() == PushPullValue.PUSH) { - topologicalSort((ResourceNode) re.getSource(), graph, dependedRootComponentGraph, visited, orderedList); - } - } - } - // For each outgoing PULL transfer. - for (Edge resToCh: curResNode.getOutEdges()) { - DataFlowEdge de = (DataFlowEdge) resToCh; - if (((PushPullAttribute) de.getAttribute()).getSelectedOption() != PushPullValue.PUSH) { - for (Edge chToRes : resToCh.getDestination().getOutEdges()) { - topologicalSort((ResourceNode) chToRes.getDestination(), graph, dependedRootComponentGraph, visited, orderedList); - } - } - } - // For each depending root node. - if (dependedRootComponentGraph.get(curResNode.getResourceHierarchy()) != null) { - for (ResourceHierarchy dependingRes: dependedRootComponentGraph.get(curResNode.getResourceHierarchy())) { - for (ResourceNode root: graph.getRootResourceNodes()) { - if (root.getResourceHierarchy().equals(dependingRes)) { - topologicalSort(root, graph, dependedRootComponentGraph, visited, orderedList); - } - } - } - } - // For each reference resource. - for (Node n: graph.getResourceNodes()) { - ResourceNode resNode = (ResourceNode) n; - for (Edge resToCh : resNode.getOutEdges()) { - ChannelNode chNode = (ChannelNode) resToCh.getDestination(); - for (ChannelMember m: chNode.getChannel().getReferenceChannelMembers()) { - if (curResNode.getOutSideResources().contains(m.getResource())) { - topologicalSort(resNode, graph, dependedRootComponentGraph, visited, orderedList); - } - } - } - } - orderedList.add(0, curResNode); - } - - private static void declareAccessorMethodInMainComponent(ResourceNode resourceNode, TypeDeclaration mainComponent) { - MethodDeclaration getterAccessor = null; - List mainGetterParams = new ArrayList<>(); - int v = 1; - for (Expression param: resourceNode.getPrimaryResourcePath().getPathParams()) { - if (param instanceof Variable) { - Variable var = (Variable) param; - mainGetterParams.add(new VariableDeclaration(var.getType(), var.getName())); - } else if (param instanceof Term) { - Term var = (Term) param; - mainGetterParams.add(new VariableDeclaration(var.getType(), "v" + v)); - } - v++; - } - ResourcePath resPath = new ResourcePath(resourceNode.getPrimaryResourcePath()); - for (int i = 0; i < mainGetterParams.size(); i++) { - Parameter pathParam = new Parameter(mainGetterParams.get(i).getName()); - resPath.replacePathParam(i, pathParam, null); - } - if (mainGetterParams.size() > 0) { - getterAccessor = new MethodDeclaration("get" + getComponentName(resourceNode.getResourceHierarchy()), - false, - getImplStateType(resourceNode.getResourceHierarchy()), - mainGetterParams); - } else { - getterAccessor = new MethodDeclaration("get" + getComponentName(resourceNode.getResourceHierarchy()), - getImplStateType(resourceNode.getResourceHierarchy())); - } - getterAccessor.setBody(new Block()); - Expression getState = JavaCodeGenerator.pullAccessor.getDirectStateAccessorFor(resPath, null); - getterAccessor.getBody().addStatement("return " + getState.toImplementation(new String[] {null}) + ";"); - mainComponent.addMethod(getterAccessor); - } - - private static List addConstructorParameters(ResourceHierarchy resource, - Map resourceComponents, - Map resourceConstructors, - List> constructorParams) { - List params = new ArrayList<>(); - for (ResourceHierarchy child: resource.getChildren()) { - params.addAll(addConstructorParameters(child, resourceComponents, resourceConstructors, constructorParams)); - } - for (Entry paramEnt: constructorParams) { - if (paramEnt.getKey().equals(resource)) { - params.add(paramEnt.getValue()); - } - } - if (params.size() > 0) { - MethodDeclaration constructor = resourceConstructors.get(resource); - if (constructor == null) { - if (resourceComponents.get(resource) != null) { - String resourceName = getComponentName(resource); - constructor = new MethodDeclaration(resourceName, true); - Block body = new Block(); - constructor.setBody(body); - resourceComponents.get(resource).addMethod(constructor); - resourceConstructors.put(resource, constructor); - } - } - if (constructor != null) { - for (VariableDeclaration param: params) { - boolean existsParam = false; - if (constructor.getParameters() != null) { - for (VariableDeclaration constParam: constructor.getParameters()) { - if (constParam.getName().equals(param.getName())) { - existsParam = true; - break; - } - } - } - if (!existsParam) { - constructor.addParameter(param); - constructor.getBody().addStatement("this." + toVariableName(param.getName()) + " = " + toVariableName(param.getName()) + ";"); - } - } - } - } - if (resource.getNumParameters() > 0) params.clear(); - return params; - } - - private static String getInitializer(ResourceHierarchy res) { - Type stateType = res.getResourceStateType(); - String initializer = null; - if (res.getInitialValue() != null) { - initializer = res.getInitialValue().toImplementation(new String[] {""}); - } else if (stateType != null) { - initializer = DataConstraintModel.getDefaultValue(stateType); - } - return initializer; - } - - static public ArrayList getCodes(ArrayList codeTree) { - ArrayList codes = new ArrayList<>(); - for (TypeDeclaration type : codeTree) { - codes.add("public class " + type.getTypeName() + "{"); - for (FieldDeclaration field : type.getFields()) { - if (type.getTypeName() != mainTypeName) { - String cons = "\t" + "private " + field.getType().getInterfaceTypeName() + " " - + field.getName(); - if (DataConstraintModel.isListType(field.getType())) - cons += " = new ArrayList<>()"; - cons += ";"; - codes.add(cons); - } else { - String cons = "\t" + "private " + field.getType().getInterfaceTypeName() + " " - + field.getName() + " = new " + field.getType().getTypeName() + "("; - cons += ");"; - codes.add(cons); - } - } - codes.add(""); - for (MethodDeclaration method : type.getMethods()) { - String varstr = "\t" + "public " + method.getReturnType().getInterfaceTypeName() + " " - + method.getName() + "("; - if (method.getParameters() != null) { - for (VariableDeclaration var : method.getParameters()) { - varstr += var.getType().getInterfaceTypeName() + " " + var.getName() + ","; - } - if (!method.getParameters().isEmpty()) - varstr = varstr.substring(0, varstr.length() - 1); - } - if (method.getBody() != null) { - for (String str : method.getBody().getStatements()) { - codes.add("\t\t" + str + ";"); - } - } - codes.add(varstr + ")" + "{"); - codes.add("\t" + "}"); - codes.add(""); - } - codes.add("}"); - codes.add(""); - } - return codes; - } - - private static MethodDeclaration getMethod(TypeDeclaration type, String methodName, List params) { - for (MethodDeclaration m: type.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; - } - - static public IResourceStateAccessor pushAccessor = new IResourceStateAccessor() { - @Override - public Expression getCurrentStateAccessorFor(ChannelMember target, ChannelMember from) { - ResourcePath targetRes = target.getResource(); - ResourcePath fromRes = from.getResource(); - if (targetRes.equals(fromRes)) { - return new Field("value", - targetRes.getResourceStateType() != null ? targetRes.getResourceStateType() - : DataConstraintModel.typeInt); - } - // use the cached value as the current state - return new Field(toVariableName(getComponentName(targetRes.getResourceHierarchy())), - targetRes.getResourceStateType() != null ? targetRes.getResourceStateType() - : DataConstraintModel.typeInt); - } - - @Override - public Expression getNextStateAccessorFor(ChannelMember target, ChannelMember from) { - ResourcePath targetRes = target.getResource(); - return new Parameter(toVariableName(getComponentName(targetRes.getResourceHierarchy())), - targetRes.getResourceStateType() != null ? targetRes.getResourceStateType() - : DataConstraintModel.typeInt); - } - - @Override - public Expression getDirectStateAccessorFor(ResourcePath targetRes, ResourcePath fromRes) { - if (fromRes != null && targetRes.equals(fromRes)) { - return new Field("value", - targetRes.getResourceStateType() != null ? targetRes.getResourceStateType() - : DataConstraintModel.typeInt); - } - // for reference channel member - return new Parameter(toVariableName(getComponentName(targetRes.getResourceHierarchy())), - targetRes.getResourceStateType() != null ? targetRes.getResourceStateType() - : DataConstraintModel.typeInt); - } - }; - - static public IResourceStateAccessor pullAccessor = new IResourceStateAccessor() { - @Override - public Expression getCurrentStateAccessorFor(ChannelMember target, ChannelMember from) { - ResourcePath targetRes = target.getResource(); - if (from != null) { - ResourcePath fromRes = from.getResource(); - if (!target.isOutside()) { - return getDirectStateAccessorFor(targetRes, fromRes); - } - Term getter = null; - String targetComponentName = getComponentName(targetRes.getResourceHierarchy()); - if (generatesComponent(targetRes.getResourceHierarchy())) { - getter = new Term(new Symbol("getValue", 1, Symbol.Type.METHOD)); - getter.addChild(new Field(toVariableName(targetComponentName), targetRes.getResourceStateType())); - } else { - String parentName = toVariableName(getComponentName(targetRes.getResourceHierarchy().getParent())); - Type parentType = targetRes.getResourceHierarchy().getParent().getResourceStateType(); - getter = new Term(new Symbol("get" + targetComponentName, 1, Symbol.Type.METHOD)); - getter.addChild(new Field(parentName, parentType)); - } - return getter; - } else { - return getDirectStateAccessorFor(targetRes, null); - } - } - - @Override - public Expression getNextStateAccessorFor(ChannelMember target, ChannelMember from) { - ResourcePath targetRes = target.getResource(); - if (from != null) { - ResourcePath fromRes = from.getResource(); - if (!target.isOutside()) { - return getDirectStateAccessorFor(targetRes, fromRes); - } - // Get the next state by invoking a getter method. - Term getter = null; - String targetComponentName = getComponentName(targetRes.getResourceHierarchy()); - if (generatesComponent(targetRes.getResourceHierarchy())) { - getter = new Term(new Symbol("getValue", 1, Symbol.Type.METHOD)); - getter.addChild(new Field(toVariableName(targetComponentName), targetRes.getResourceStateType())); - } else { - String parentName = toVariableName(getComponentName(targetRes.getResourceHierarchy().getParent())); - Type parentType = targetRes.getResourceHierarchy().getParent().getResourceStateType(); - getter = new Term(new Symbol("get" + targetComponentName, 1, Symbol.Type.METHOD)); - getter.addChild(new Field(parentName, parentType)); - } - return getter; - } else { - return getDirectStateAccessorFor(targetRes, null); - } - } - - @Override - public Expression getDirectStateAccessorFor(ResourcePath targetRes, ResourcePath fromRes) { - if (fromRes != null) { - if (targetRes.equals(fromRes)) { - return new Field("value", - targetRes.getResourceStateType() != null ? targetRes.getResourceStateType() - : DataConstraintModel.typeInt); - } - // for reference channel member - if (fromRes.isAncestorOf(targetRes)) { - Stack pathStack = new Stack<>(); - ResourcePath curPath = targetRes; - do { - pathStack.push(curPath); - curPath = curPath.getParent(); - } while (!curPath.equals(fromRes)); - // iterate from the fromRes resource - return getRelativePath(targetRes, pathStack); - } - if (generatesComponent(targetRes.getResourceHierarchy())) { - Term getter = new Term(new Symbol("getValue", 1, Symbol.Type.METHOD)); - getter.addChild(new Field(toVariableName(getComponentName(targetRes.getResourceHierarchy())), targetRes.getResourceStateType())); - return getter; - } else { - return new Field(toVariableName(getComponentName(targetRes.getResourceHierarchy())), targetRes.getResourceStateType()); - } - } else { - // (#3) access from the outside of the hierarchy (must be kept consistent with #4) - Stack pathStack = new Stack<>(); - ResourcePath curPath = targetRes; - do { - pathStack.push(curPath); - curPath = curPath.getParent(); - } while (curPath != null); - // iterate from the root resource - return getRelativePath(targetRes, pathStack); - } - } - - private Expression getRelativePath(ResourcePath targetRes, Stack pathStack) { - ResourcePath curPath; - Term getter = null; - int arity = 2; - boolean doesChainInvocations = true; - while (!pathStack.empty()) { - curPath = pathStack.pop(); - String typeName = getComponentName(curPath.getResourceHierarchy()); - if (getter == null && generatesComponent(curPath.getResourceHierarchy())) { - // root resource - String fieldName = toVariableName(typeName); - getter = new Field(fieldName, new Type(typeName, typeName)); - } else { - if (generatesComponent(curPath.getResourceHierarchy())) { - if (arity == 2) { - Term newGetter = new Term(new Symbol("get" + typeName, -1, Symbol.Type.METHOD)); - newGetter.addChild(getter); - if (curPath.getResourceHierarchy().getNumParameters() > 0) { - Expression param = curPath.getLastParam(); - if (param != null) { - newGetter.addChild(param); - newGetter.getSymbol().setArity(2); - } - } - getter = newGetter; - } else { - // add the last path parameter. - if (curPath.getResourceHierarchy().getNumParameters() > 0) { - Expression param = curPath.getLastParam(); - if (param != null) { - getter.getSymbol().setArity(arity); - getter.addChild(param); - } - } - } - arity = 2; - doesChainInvocations = true; - } else { - // to get a descendant resource directly. (e.g, .todos.{year}.{month}.{day}.{id} ==> .getTodos().getTodo(year, month, day, id)) - if (doesChainInvocations) { - Term newGetter = new Term(new Symbol("get" + typeName, -1, Symbol.Type.METHOD)); - newGetter.addChild(getter); - getter = newGetter; - doesChainInvocations = false; - } - if (curPath.getResourceHierarchy().getNumParameters() > 0) { - // may change the symbol name - getter.getSymbol().changeName("get" + typeName); - // add a path parameter. - Expression param = curPath.getLastParam(); - if (param != null) { - getter.getSymbol().setArity(arity); - getter.addChild(param); - arity++; - } - } - } - } - } - if (generatesComponent(targetRes.getResourceHierarchy())) { - Term newGetter = new Term(new Symbol("getValue", 1, Symbol.Type.METHOD)); - newGetter.addChild(getter); - getter = newGetter; - } - return getter; - } - }; - - static public IResourceStateAccessor refAccessor = new IResourceStateAccessor() { - @Override - public Expression getCurrentStateAccessorFor(ChannelMember target, ChannelMember from) { - ResourcePath targetRes = target.getResource(); - ResourcePath fromRes = from.getResource(); - if (targetRes.equals(fromRes)) { - return new Field("value", - targetRes.getResourceStateType() != null ? targetRes.getResourceStateType() - : DataConstraintModel.typeInt); - } - // for reference channel member - return new Parameter(toVariableName(getComponentName(targetRes.getResourceHierarchy())), - targetRes.getResourceStateType() != null ? targetRes.getResourceStateType() - : DataConstraintModel.typeInt); - } - - @Override - public Expression getNextStateAccessorFor(ChannelMember target, ChannelMember from) { - ResourcePath targetRes = target.getResource(); - return new Parameter(toVariableName(getComponentName(targetRes.getResourceHierarchy())), - targetRes.getResourceStateType() != null ? targetRes.getResourceStateType() - : DataConstraintModel.typeInt); - } - - @Override - public Expression getDirectStateAccessorFor(ResourcePath targetRes, ResourcePath fromRes) { - if (fromRes != null && targetRes.equals(fromRes)) { - return new Field("value", - targetRes.getResourceStateType() != null ? targetRes.getResourceStateType() - : DataConstraintModel.typeInt); - } - // for reference channel member - return new Parameter(toVariableName(getComponentName(targetRes.getResourceHierarchy())), - targetRes.getResourceStateType() != null ? targetRes.getResourceStateType() - : DataConstraintModel.typeInt); - } - }; -} diff --git a/AlgebraicDataflowArchitectureModel/src/generators/JavaMethodBodyGenerator.java b/AlgebraicDataflowArchitectureModel/src/generators/JavaMethodBodyGenerator.java deleted file mode 100644 index 8d1fca4..0000000 --- a/AlgebraicDataflowArchitectureModel/src/generators/JavaMethodBodyGenerator.java +++ /dev/null @@ -1,1472 +0,0 @@ -package generators; - -import java.util.AbstractMap; -import java.util.ArrayList; -import java.util.HashMap; -import java.util.HashSet; -import java.util.Iterator; -import java.util.List; -import java.util.Map; -import java.util.Set; -import java.util.Stack; -import java.util.Map.Entry; - -import code.ast.CompilationUnit; -import code.ast.MethodDeclaration; -import code.ast.TypeDeclaration; -import code.ast.VariableDeclaration; -import models.Edge; -import models.algebra.Constant; -import models.algebra.Expression; -import models.algebra.Field; -import models.algebra.InvalidMessage; -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; -import models.algebra.ValueUndefined; -import models.algebra.Variable; -import models.dataConstraintModel.Channel; -import models.dataConstraintModel.ChannelMember; -import models.dataConstraintModel.DataConstraintModel; -import models.dataConstraintModel.JsonAccessor; -import models.dataConstraintModel.JsonTerm; -import models.dataConstraintModel.ResourceHierarchy; -import models.dataConstraintModel.ResourcePath; -import models.dataConstraintModel.Selector; -import models.dataFlowModel.DataTransferModel; -import models.dataFlowModel.DataTransferChannel; -import models.dataFlowModel.DataTransferChannel.IResourceStateAccessor; -import models.dataFlowModel.PushPullAttribute; -import models.dataFlowModel.PushPullValue; -import models.dataFlowModel.ChannelNode; -import models.dataFlowModel.ResolvingMultipleDefinitionIsFutureWork; -import models.dataFlowModel.DataFlowEdge; -import models.dataFlowModel.DataFlowGraph; -import models.dataFlowModel.ResourceNode; -import models.dataFlowModel.StoreAttribute; - -public class JavaMethodBodyGenerator { - public static ArrayList doGenerate(DataFlowGraph graph, DataTransferModel model, ArrayList codes) { - // Create a map from type names (lower case) to their types. - Map componentMap = new HashMap<>(); - for (CompilationUnit code: codes) { - for (TypeDeclaration component: code.types()) { - componentMap.put(component.getTypeName(), component); - } - } - - // Generate the body of each update or getter method. - try { - Map> referredResources = new HashMap<>(); - for (Edge e: graph.getEdges()) { - DataFlowEdge resToCh = (DataFlowEdge) e; - if (!resToCh.isChannelToResource()) { - PushPullAttribute pushPull = (PushPullAttribute) resToCh.getAttribute(); - ResourceNode src = (ResourceNode) resToCh.getSource(); - ChannelNode directDstChNode = (ChannelNode) resToCh.getDestination(); - DataTransferChannel directDstCh = directDstChNode.getChannel(); - // Should take into account the channel hierarchy. - Set ancestorDstChannels = directDstChNode.getAncestors(); - Set descendantDstChannels = directDstChNode.getDescendants(); - Set outEdges = new HashSet<>(); - outEdges.addAll(directDstChNode.getOutEdges()); - for (ChannelNode ancestorDst: ancestorDstChannels) { - outEdges.addAll(ancestorDst.getOutEdges()); - } - for (ChannelNode descendantDst: descendantDstChannels) { - outEdges.addAll(descendantDst.getOutEdges()); - } - for (Edge chToRes: outEdges) { - ResourceNode dst = (ResourceNode) chToRes.getDestination(); - String srcResourceName = JavaCodeGenerator.getComponentName(src.getResourceHierarchy()); - String dstResourceName = JavaCodeGenerator.getComponentName(dst.getResourceHierarchy()); - TypeDeclaration srcComponent = componentMap.get(srcResourceName); - TypeDeclaration dstComponent = componentMap.get(dstResourceName); - ChannelNode chNode = (ChannelNode) chToRes.getSource(); - DataTransferChannel ch = chNode.getChannel(); - for (ChannelMember out: ch.getOutputChannelMembers()) { - if (dst.getInSideResources().contains(out.getResource())) { - // Check if the input resource is outside of the channel scope. - boolean outsideInputResource = false; - for (ChannelMember cm: ch.getInputChannelMembers()) { - if (src.getOutSideResources().contains(cm.getResource()) && cm.isOutside()) { - outsideInputResource = true; // Regarded as pull transfer. - break; - } - } - // Check if the output resource is outside of the channel scope. - boolean outsideOutputResource = out.isOutside(); - // Take into account the channel hierarchy. - if (descendantDstChannels.contains(chNode)) { - outsideOutputResource = true; // Regarded as (broadcasting) push transfer. - } - if (ancestorDstChannels.contains(chNode)) { - outsideInputResource = true; // Regarded as (collecting) pull transfer. - } - if ((pushPull.getSelectedOption() == PushPullValue.PUSH && !outsideInputResource) || outsideOutputResource) { - // for push data transfer - MethodDeclaration update = null; - if (dstComponent == null) { - String dstParentResourceName = JavaCodeGenerator.getComponentName(dst.getResourceHierarchy().getParent()); - dstComponent = componentMap.get(dstParentResourceName); - update = getUpdateMethod(dstComponent, dstResourceName, srcResourceName); - } else { - update = getUpdateMethod(dstComponent, null, srcResourceName); - } - if (((StoreAttribute) dst.getAttribute()).isStored()) { - // update stored state of dst side resource (when every incoming edge is in push style) - Term unifiedMassage = null; - if (directDstCh != ch) { - unifiedMassage = directDstCh.fillOutsideResourcePaths(out, JavaCodeGenerator.pushAccessor, null).getValue(); - } - Expression updateExp = null; - if (ch.getReferenceChannelMembers().size() == 0) { - Term message = ch.fillOutsideResourcePaths(out, JavaCodeGenerator.pushAccessor, null).getValue(); - if (unifiedMassage == null) { - unifiedMassage = message; - } else { - unifiedMassage = (Term) unifiedMassage.unify(message); - } - updateExp = ch.deriveUpdateExpressionOf(out, unifiedMassage, JavaCodeGenerator.pushAccessor); - } else { - // if there exists one or more reference channel member. - HashMap inputResourceToStateAccessor = new HashMap<>(); - for (ChannelMember in: ch.getInputChannelMembers()) { - inputResourceToStateAccessor.put(in, JavaCodeGenerator.pushAccessor); - } - for (ChannelMember c: ch.getReferenceChannelMembers()) { - inputResourceToStateAccessor.put(c, JavaCodeGenerator.refAccessor); - } - Term message = ch.fillOutsideResourcePaths(out, JavaCodeGenerator.pushAccessor, inputResourceToStateAccessor).getValue(); - if (unifiedMassage == null) { - unifiedMassage = message; - } else { - unifiedMassage = (Term) unifiedMassage.unify(message); - } - updateExp = ch.deriveUpdateExpressionOf(out, unifiedMassage, JavaCodeGenerator.pushAccessor); - } - // Replace Json constructor with a constructor of a descendant resource. - ResourceHierarchy outRes = out.getResource().getResourceHierarchy(); - if (outRes.getChildren().size() == 1 && outRes.getChildren().iterator().next().getNumParameters() > 0) { - ResourceHierarchy descendantRes = outRes.getChildren().iterator().next(); - Set children; - do { - if (JavaCodeGenerator.generatesComponent(descendantRes)) break; - children = descendantRes.getChildren(); - } while (children != null && children.size() == 1 && (descendantRes = children.iterator().next()) != null); - Type descendantStateType = descendantRes.getResourceStateType(); - String descendantComponentName = JavaCodeGenerator.getComponentName(descendantRes); - TypeDeclaration descendantComponent = componentMap.get(descendantComponentName); - if (DataConstraintModel.typeJson.isAncestorOf(descendantStateType)) { - replaceJsonTermWithConstructorInvocation(updateExp, descendantStateType, descendantComponentName, descendantComponent); - } - } - // Replace the type of the state field. - Type fieldType = JavaCodeGenerator.getImplStateType(outRes); - if (updateExp instanceof Term) { - ((Term) updateExp).setType(fieldType); - for (Map.Entry varEnt: ((Term) updateExp).getVariables().entrySet()) { - if (varEnt.getValue().getName().equals("value")) { - varEnt.getValue().setType(fieldType); - } - } - } else if (updateExp instanceof Variable) { - ((Variable) updateExp).setType(fieldType); - } - // 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 (JavaCodeGenerator.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] + "this.value = " + newState + ";"; - } - } else { - if (sideEffects[0] != null) { - updateStatement = sideEffects[0]; - updateStatement = updateStatement.replace(".value", "." + JavaCodeGenerator.toVariableName(JavaCodeGenerator.getComponentName(outRes))); - if (updateStatement.endsWith("\n")) { - updateStatement = updateStatement.substring(0, updateStatement.length() - 1); - } - } - if (DataConstraintModel.typeList.isAncestorOf(outRes.getParent().getResourceStateType())) { - Term selector = new Term(DataConstraintModel.set); - selector.addChild(new Field("value")); - 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(outRes.getParent().getResourceStateType())) { - Term selector = new Term(DataConstraintModel.insert); - selector.addChild(new Field("value")); - 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())) { - updateStatement += "this." + JavaCodeGenerator.toVariableName(JavaCodeGenerator.getComponentName(outRes)) + " = " + newState + ";"; - } - } - // add an update statement of the state of dst side resource. - if (numOfOutResourcesWithTheSameHierarchy == 1) { - update.addFirstStatement(updateStatement); - } else { - Term conditions = null; - int v = 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(v - 1); - } - Term condition = new Term(DataConstraintModel.eq, new Expression[] { - new Parameter("self" + (v > 1 ? v : ""), DataConstraintModel.typeString), - arg}); - if (conditions == null) { - conditions = condition; - } else { - conditions = new Term(DataConstraintModel.and, new Expression[] { - conditions, - condition}); - } - } - v++; - } - String ifStatement = "if (" + conditions.toImplementation(new String[] {""})+ ") {\n"; - update.addFirstStatement(ifStatement + "\t" + updateStatement.replace("\n", "\n\t") + "\n}"); - } - } - // Calculate in-degree (PUSH transfer) of the destination resource. - int inDegree = 0; - Set inEdges = new HashSet<>(); - inEdges.addAll(chNode.getInEdges()); - for (ChannelNode ancestor: chNode.getAncestors()) { - inEdges.addAll(ancestor.getInEdges()); - } - for (ChannelNode descendant: chNode.getDescendants()) { - inEdges.addAll(descendant.getInEdges()); - } - for (Edge resToCh2: inEdges) { - DataFlowEdge df =(DataFlowEdge) resToCh2; - if (((PushPullAttribute) df.getAttribute()).getSelectedOption() == PushPullValue.PUSH) { - inDegree++; - } - } - if (inDegree > 1 - || (inDegree == 1 && directDstCh.getInputChannelMembers().iterator().next().getStateTransition().isRightPartial())) { - // update a cache of src side resource (when incoming edges are multiple) - String cacheStatement = "this." + JavaCodeGenerator.toVariableName(srcResourceName) + " = " + JavaCodeGenerator.toVariableName(srcResourceName) + ";"; - if (update.getBody() == null || !update.getBody().getStatements().contains(cacheStatement)) { - update.addStatement(cacheStatement); - } - } - if (((StoreAttribute) dst.getAttribute()).isStored()) { - // returns the current state stored in a field. - MethodDeclaration getter = null; - if (JavaCodeGenerator.generatesComponent(dst.getResourceHierarchy())) { - getter = getMethod(dstComponent, "getValue"); - } else { - getter = getGetterMethod(dstComponent, dstResourceName); - } - if (getter.getBody() == null || getter.getBody().getStatements().size() == 0) { - Type resourceType = dst.getResourceStateType(); - if (dst.getResourceHierarchy().getNumParameters() == 0) { - if (JavaCodeGenerator.generatesComponent(dst.getResourceHierarchy())) { - // dst has a component. - if (model.isPrimitiveType(resourceType)) { - getter.addStatement("return value;"); - } else { - // copy the current state to be returned as a 'value' - String implTypeName = resourceType.getImplementationTypeName(); - getter.addStatement("return new " + implTypeName + "(value);"); - } - } else { - // dst has no component. - String dstResName = JavaCodeGenerator.toVariableName(JavaCodeGenerator.getComponentName(dst.getResourceHierarchy())); - if (model.isPrimitiveType(resourceType)) { - getter.addStatement("return " + dstResName + ";"); - } else { - // copy the current state to be returned as a 'value' - String implTypeName = resourceType.getImplementationTypeName(); - getter.addStatement("return new " + implTypeName + "(" + dstResName + ");"); - } - } - } else { - String[] sideEffects = new String[] {""}; - if (DataConstraintModel.typeList.isAncestorOf(dst.getParent().getResourceStateType())) { - Term selector = new Term(DataConstraintModel.get); - selector.addChild(new Field("value")); - selector.addChild(dst.getSelectors().get(dst.getSelectors().size() - 1).getExpression()); - String curState = selector.toImplementation(sideEffects); - getter.addStatement(sideEffects[0] + "return " + curState + ";"); - } else if (DataConstraintModel.typeMap.isAncestorOf(dst.getParent().getResourceStateType())) { - Term selector = new Term(DataConstraintModel.lookup); - selector.addChild(new Field("value")); - selector.addChild(dst.getSelectors().get(dst.getSelectors().size() - 1).getExpression()); - String curState = selector.toImplementation(sideEffects); - getter.addStatement(sideEffects[0] + "return " + curState + ";"); - } - } - } - } - // src side (for a chain of update method invocations) - ChannelMember in = null; - for (ChannelMember cm: directDstCh.getInputChannelMembers()) { - if (src.getOutSideResources().contains(cm.getResource())) { - in = cm; - break; - } - } - String srcResName = null; - if (srcComponent == null) { - String srcParentResourceName = JavaCodeGenerator.getComponentName(src.getResourceHierarchy().getParent()); - srcComponent = componentMap.get(srcParentResourceName); - srcResName = srcResourceName; - } - // For caller update methods - for (MethodDeclaration srcUpdate: getUpdateMethods(srcComponent, srcResName)) { - ResourcePath dstRes = out.getResource(); - // Get the value of reference member to call the update method. - String refParams = ""; - Set referredSet = referredResources.get(srcUpdate); - for (ChannelMember rc: ch.getReferenceChannelMembers()) { - ResourcePath ref = rc.getResource(); - if (referredSet == null) { - referredSet = new HashSet<>(); - referredResources.put(srcUpdate, referredSet); - } - if (!dst.getInSideResources().contains(ref)) { - String refVarName = JavaCodeGenerator.toVariableName(JavaCodeGenerator.getComponentName(ref.getResourceHierarchy())); - if (!referredSet.contains(ref)) { - referredSet.add(ref); - ResourcePath srcRes = in.getResource(); - if (!JavaCodeGenerator.generatesComponent(srcRes.getResourceHierarchy())) { - srcRes = srcRes.getParent(); - } - Expression refGetter = JavaCodeGenerator.pullAccessor.getDirectStateAccessorFor(ref, srcRes); - String[] sideEffects = new String[] {""}; - String refExp = refGetter.toImplementation(sideEffects); - String refTypeName = ref.getResourceStateType().getInterfaceTypeName(); - srcUpdate.addStatement(sideEffects[0] + refTypeName + " " + refVarName + " = " + refExp + ";"); - } - refParams += ", " + refVarName; - } - } - // Update fields to refer to outside resources. - ResourcePath filledOutsideResourcePath = null; - Map>> resourcePaths = ch.fillOutsideResourcePaths(out, JavaCodeGenerator.pullAccessor); - if (resourcePaths != null && resourcePaths.size() > 0) { - for (ChannelMember outsideMember: resourcePaths.keySet()) { - ResourcePath outsidePath = resourcePaths.get(outsideMember).getKey(); - if (out.equals(outsideMember)) { - filledOutsideResourcePath = outsidePath; - } - if (!JavaCodeGenerator.generatesComponent(outsidePath.getResourceHierarchy())) { - outsidePath = outsidePath.getParent(); - } - String outsideResName = JavaCodeGenerator.toVariableName(JavaCodeGenerator.getComponentName(outsidePath.getResourceHierarchy())); - Expression outsideExp = JavaCodeGenerator.pullAccessor.getDirectStateAccessorFor(outsidePath, null); - if (JavaCodeGenerator.generatesComponent(outsidePath.getResourceHierarchy())) { - outsideExp = ((Term) outsideExp).getChild(0); - } - if (outsideExp instanceof Field) { - outsideExp = new Variable(((Field) outsideExp).getSymbol().getName(), ((Field) outsideExp).getType()); - } else if (outsideExp instanceof Term) { - for (Entry fieldEnt: ((Term) outsideExp).getSubTerms(Field.class).entrySet()) { - Position pos = fieldEnt.getKey(); - Field field = fieldEnt.getValue(); - Variable var = new Variable(field.getSymbol().getName(), field.getType()); - ((Term) outsideExp).replaceSubTerm(pos, var); - } - } - String[] sideEffects = new String[] {""}; - String outsideAccessor = outsideExp.toImplementation(sideEffects); - srcUpdate.addStatement("this." + outsideResName + " = " + outsideAccessor + ";"); // change the reference field. - } - } - // Values of path parameters to call the update method. - if (filledOutsideResourcePath == null) { - filledOutsideResourcePath = dstRes; - } - String pathParams = ""; - for (Expression pathParam: filledOutsideResourcePath.getPathParams()) { - if (pathParam instanceof Variable) { - Variable pathVar = (Variable) pathParam; - pathParams += pathVar.getName() + ", "; - } else if (pathParam instanceof Constant) { - Constant pathVar = (Constant) pathParam; - pathParams += pathVar.getSymbol().getName() + ", "; - } - } - // Values of channel parameters to call the update method. - String chParams = ""; - for (Selector selector: ch.getAllSelectors()) { - if (selector.getExpression() instanceof Variable) { - Variable selVar = (Variable) selector.getExpression(); - chParams += selVar.getName() + ", "; - } - } - // Value of the source side (input side) resource. - String srcFieldName = "value"; - if (!JavaCodeGenerator.generatesComponent(src.getResourceHierarchy())) { - srcFieldName = JavaCodeGenerator.toVariableName(srcResourceName); - } - // Call the update method. - String updateMethodName = null; - if (JavaCodeGenerator.generatesComponent(dst.getResourceHierarchy())) { - updateMethodName = "updateFrom" + srcResourceName; - } else { - updateMethodName = "update" + dstResourceName + "From" + srcResourceName; - } - if (!outsideOutputResource) { - // The destination resource is not outside. - if (srcComponent != dstComponent) { - srcUpdate.addStatement("this." + JavaCodeGenerator.toVariableName(dstComponent.getTypeName()) + "." + updateMethodName + "(" + pathParams + chParams + srcFieldName + refParams + ");"); - } else { - srcUpdate.addStatement("this." + updateMethodName + "(" + pathParams + chParams + srcFieldName + refParams + ");"); - } - } else { - // Use the reference field to refer to outside destination resource. - srcUpdate.addStatement("this." + JavaCodeGenerator.toVariableName(dstComponent.getTypeName()) + "." + updateMethodName + "(" + pathParams + chParams + srcFieldName + refParams + ");"); - } - if (descendantDstChannels.contains(chNode)) { - // For hierarchical channels (broadcasting push transfer). - if (ch.getSelectors() != null && ch.getSelectors().size() > 0) { - Expression selExp = ch.getSelectors().get(0).getExpression(); - Type selType = null; - String forVarName = null; - if (selExp instanceof Variable) { - selType = ((Variable) selExp).getType(); - forVarName = ((Variable) selExp).getName(); - ChannelMember insideChMem = null; - for (ChannelMember cm :ch.getInputChannelMembers()) { - if (!cm.isOutside()) { - insideChMem = cm; - break; - } - } - if (insideChMem == null) { - for (ChannelMember cm :ch.getReferenceChannelMembers()) { - if (!cm.isOutside()) { - insideChMem = cm; - break; - } - } - } - if (insideChMem == null) { - for (ChannelMember cm :ch.getOutputChannelMembers()) { - if (!cm.isOutside()) { - insideChMem = cm; - break; - } - } - } - ResourcePath insideResPath = insideChMem.getResource(); - while (insideResPath.getParent() != null && (insideResPath.getLastParam() == null || !insideResPath.getLastParam().equals(selExp))) { - insideResPath = insideResPath.getParent(); - } - insideResPath = insideResPath.getParent(); - if (insideResPath != null) { - String parent = JavaCodeGenerator.pullAccessor.getDirectStateAccessorFor(insideResPath, src.getOutSideResource(directDstCh)).toImplementation(new String[] {""}); - if (selType.equals(DataConstraintModel.typeInt)) { - // make a for loop (for a list) for broadcasting. - srcUpdate.addFirstStatement("for (int " + forVarName + " = 0; " + forVarName +" < " + parent + ".size(); " + forVarName + "++) {"); - srcUpdate.addStatement("}"); - } else if (selType.equals(DataConstraintModel.typeString)) { - // make a for loop (for a map) for broadcasting. - srcUpdate.addFirstStatement("for (String " + forVarName + ": " + parent + ".keySet()) {"); - srcUpdate.addStatement("}"); - } - } - } else if (selExp instanceof Term) { - // not supported. - } - } - } - } - // For caller input methods - for (MethodDeclaration srcInput: getInputMethods(srcComponent, src, model)) { - ResourcePath dstRes = out.getResource(); - // Get the value of reference member to call the update method. - String refParams = ""; - Set referredSet = referredResources.get(srcInput); - for (ChannelMember rc: ch.getReferenceChannelMembers()) { - ResourcePath ref = rc.getResource(); - if (referredSet == null) { - referredSet = new HashSet<>(); - referredResources.put(srcInput, referredSet); - } - if (!dst.getInSideResources().contains(ref)) { - String refVarName = JavaCodeGenerator.toVariableName(JavaCodeGenerator.getComponentName(ref.getResourceHierarchy())); - if (!referredSet.contains(ref)) { - referredSet.add(ref); - ResourcePath srcRes = in.getResource(); - if (!JavaCodeGenerator.generatesComponent(srcRes.getResourceHierarchy())) { - srcRes = srcRes.getParent(); - } - Expression refGetter = JavaCodeGenerator.pullAccessor.getDirectStateAccessorFor(ref, srcRes); - String[] sideEffects = new String[] {""}; - String refExp = refGetter.toImplementation(sideEffects); - String refTypeName = ref.getResourceStateType().getInterfaceTypeName(); - srcInput.addStatement(sideEffects[0] + refTypeName + " " + refVarName + " = " + refExp + ";"); - } - refParams += ", " + refVarName; - } - } - // Update fields to refer to outside resources. - ResourcePath filledOutsideResourcePath = null; - Map>> resourcePaths = ch.fillOutsideResourcePaths(out, JavaCodeGenerator.pullAccessor); - if (resourcePaths != null && resourcePaths.size() > 0) { - for (ChannelMember outsideMember: resourcePaths.keySet()) { - ResourcePath outsidePath = resourcePaths.get(outsideMember).getKey(); - if (out.equals(outsideMember)) { - filledOutsideResourcePath = outsidePath; - } - if (!JavaCodeGenerator.generatesComponent(outsidePath.getResourceHierarchy())) { - outsidePath = outsidePath.getParent(); - } - String outsideResName = JavaCodeGenerator.toVariableName(JavaCodeGenerator.getComponentName(outsidePath.getResourceHierarchy())); - Expression outsideExp = JavaCodeGenerator.pullAccessor.getDirectStateAccessorFor(outsidePath, null); - if (JavaCodeGenerator.generatesComponent(outsidePath.getResourceHierarchy())) { - outsideExp = ((Term) outsideExp).getChild(0); - } - if (outsideExp instanceof Field) { - outsideExp = new Variable(((Field) outsideExp).getSymbol().getName(), ((Field) outsideExp).getType()); - } else if (outsideExp instanceof Term) { - for (Entry fieldEnt: ((Term) outsideExp).getSubTerms(Field.class).entrySet()) { - Position pos = fieldEnt.getKey(); - Field field = fieldEnt.getValue(); - Variable var = new Variable(field.getSymbol().getName(), field.getType()); - ((Term) outsideExp).replaceSubTerm(pos, var); - } - } - String[] sideEffects = new String[] {""}; - String outsideAccessor = outsideExp.toImplementation(sideEffects); - srcInput.addStatement("this." + outsideResName + " = " + outsideAccessor + ";"); // change the reference field. - } - } - // Values of path parameters to call the update method. - if (filledOutsideResourcePath == null) { - filledOutsideResourcePath = dstRes; - } - String pathParams = ""; - for (Expression pathParam: filledOutsideResourcePath.getPathParams()) { - if (pathParam instanceof Variable) { - Variable pathVar = (Variable) pathParam; - pathParams += pathVar.getName() + ", "; - } else if (pathParam instanceof Constant) { - Constant pathVar = (Constant) pathParam; - pathParams += pathVar.getSymbol().getName() + ", "; - } - } - // Values of channel parameters to call the update method. - String chParams = ""; - for (Selector selector: ch.getAllSelectors()) { - if (selector.getExpression() instanceof Variable) { - Variable selVar = (Variable) selector.getExpression(); - chParams += selVar.getName() + ", "; - } - } - // Call the update method. - String updateMethodName = null; - if (JavaCodeGenerator.generatesComponent(dst.getResourceHierarchy())) { - updateMethodName = "updateFrom" + srcResourceName; - } else { - updateMethodName = "update" + dstResourceName + "From" + srcResourceName; - } - // Value of the source side (input side) resource. - 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 + "(" + pathParams + chParams + srcFieldName + refParams + ");"); - } else { - srcInput.addStatement("this." + updateMethodName + "(" + pathParams + chParams + srcFieldName + refParams + ");"); - } - } else { - // Use the reference field to refer to outside destination resource. - srcInput.addStatement("this." + JavaCodeGenerator.toVariableName(dstComponent.getTypeName()) + "." + updateMethodName + "(" + pathParams + chParams + srcFieldName + refParams + ");"); - } - if (descendantDstChannels.contains(chNode)) { - // For hierarchical channels (broadcasting push transfer). - if (ch.getSelectors() != null && ch.getSelectors().size() > 0) { - Expression selExp = ch.getSelectors().get(0).getExpression(); - Type selType = null; - String varName = null; - if (selExp instanceof Variable) { - selType = ((Variable) selExp).getType(); - varName = ((Variable) selExp).getName(); - ChannelMember insideChMem = null; - for (ChannelMember cm :ch.getInputChannelMembers()) { - if (!cm.isOutside()) { - insideChMem = cm; - break; - } - } - if (insideChMem == null) { - for (ChannelMember cm :ch.getReferenceChannelMembers()) { - if (!cm.isOutside()) { - insideChMem = cm; - break; - } - } - } - if (insideChMem == null) { - for (ChannelMember cm :ch.getOutputChannelMembers()) { - if (!cm.isOutside()) { - insideChMem = cm; - break; - } - } - } - ResourcePath insideResPath = insideChMem.getResource(); - while (insideResPath.getParent() != null && (insideResPath.getLastParam() == null || !insideResPath.getLastParam().equals(selExp))) { - insideResPath = insideResPath.getParent(); - } - insideResPath = insideResPath.getParent(); - if (insideResPath != null) { - String parent = JavaCodeGenerator.pullAccessor.getDirectStateAccessorFor(insideResPath, src.getOutSideResource(directDstCh)).toImplementation(new String[] {""}); - if (selType.equals(DataConstraintModel.typeInt)) { - // make a for loop (for a list) for broadcasting. - srcInput.addFirstStatement("for (int " + varName + " = 0; " + varName +" < " + parent + ".size(); " + varName + "++) {"); - srcInput.addStatement("}"); - } else if (selType.equals(DataConstraintModel.typeString)) { - // make a for loop (for a map) for broadcasting. - srcInput.addFirstStatement("for (String " + varName + ": " + parent + ".keySet()) {"); - srcInput.addStatement("}"); - } - } - } else if (selExp instanceof Term) { - // not supported. - } - } - } - } - } else if ((pushPull.getSelectedOption() != PushPullValue.PUSH && !outsideOutputResource) || outsideInputResource) { - // for pull (or push/pull) data transfer - if (dstComponent == null) { - String dstParentResourceName = JavaCodeGenerator.getComponentName(dst.getResourceHierarchy().getParent()); - dstComponent = componentMap.get(dstParentResourceName); - } - MethodDeclaration getter = null; - if (JavaCodeGenerator.generatesComponent(dst.getResourceHierarchy())) { - getter = getMethod(dstComponent, "getValue"); - } else { - getter = getGetterMethod(dstComponent, dstResourceName); - } - if (getter.getBody() == null || getter.getBody().getStatements().size() == 0) { - // The first time to fill the getter method's body. - // Data transfer on the same channel hierarchy. - String[] sideEffects = new String[] {""}; - boolean isContainedPush = false; - Map inputResourceToStateAccessor = new HashMap<>(); - for (Edge chToRes2: dst.getInEdges()) { - DataTransferChannel ch2 = ((ChannelNode) chToRes2.getSource()).getChannel(); - for (Edge resToCh2: chToRes2.getSource().getInEdges()) { - DataFlowEdge dIn = (DataFlowEdge) resToCh2; - ChannelMember in = null; - for (ChannelMember cm: ch2.getInputChannelMembers()) { - if (((ResourceNode) dIn.getSource()).getOutSideResources().contains(cm.getResource())) { - in = cm; - break; - } - } - if (((PushPullAttribute) dIn.getAttribute()).getSelectedOption() == PushPullValue.PUSH) { - isContainedPush = true; - inputResourceToStateAccessor.put(in, JavaCodeGenerator.pushAccessor); - } else { - inputResourceToStateAccessor.put(in, JavaCodeGenerator.pullAccessor); - } - } - } - // for reference channel members - for (ChannelMember c: ch.getReferenceChannelMembers()) { - inputResourceToStateAccessor.put(c, JavaCodeGenerator.pullAccessor); // by pull data transfer - } - Map.Entry>>, Term> resourcePathsAndMessage; - - // Construct the base message. - if (!isContainedPush) { - // All incoming edges are in PULL-style. - resourcePathsAndMessage = ch.fillOutsideResourcePaths(out, JavaCodeGenerator.pullAccessor, null); - } else { - // At least one incoming edge is in PUSH-style. - resourcePathsAndMessage = ch.fillOutsideResourcePaths(out, JavaCodeGenerator.pullAccessor, inputResourceToStateAccessor); - } - Map>> resourcePaths = resourcePathsAndMessage.getKey(); - Term messageTerm = resourcePathsAndMessage.getValue(); - // Data transfer from the descendant channel hierarchies. - Stack> channelItrStack = new Stack<>(); - DataTransferChannel curChannel = ch; - if (curChannel.getChildren() != null && curChannel.getChildren().size() > 0) { - // retrieve descendant channels recursively. - Iterator chItr = curChannel.getChildren().iterator(); - do { - if (!chItr.hasNext()) { - chItr = channelItrStack.pop(); - } else { - curChannel = (DataTransferChannel) chItr.next(); - // generate pull data transfers. - Set chMems = new HashSet<>(curChannel.getInputChannelMembers()); - chMems.addAll(curChannel.getReferenceChannelMembers()); - for (ChannelMember cm2: chMems) { - if (resourcePaths == null || !resourcePaths.keySet().contains(cm2)) { - // not a depending channel member. - ResourcePath src2 = cm2.getResource(); - Type srcResType2 = src2.getResourceStateType(); - String srcResName2 = JerseyCodeGenerator.toVariableName(JerseyCodeGenerator.getComponentName(src2.getResourceHierarchy())); - String srcGetter = JavaCodeGenerator.pullAccessor.getDirectStateAccessorFor(src2, dst.getInSideResource(curChannel)).toImplementation(new String[] {""}); - getter.addStatement(srcResType2.getInterfaceTypeName() + " " + srcResName2 + " = " + srcGetter + ";"); - } else { - // a depending channel member. - ResourcePath src2 = resourcePaths.get(cm2).getKey(); - // get outside src2 resource state by pull data transfer. - if (cm2.isOutside() || src2.getCommonPrefix(dst.getInSideResource(curChannel)) == null) { - // generate a pull data transfer from a depending in/ref resource. - Type srcResType2 = src2.getResourceStateType(); - String srcResName2 = JerseyCodeGenerator.toVariableName(JerseyCodeGenerator.getComponentName(src2.getResourceHierarchy())); - String dependingGetter = JavaCodeGenerator.pullAccessor.getDirectStateAccessorFor(src2, dst.getInSideResource(curChannel)).toImplementation(new String[] {""}); - getter.addStatement(srcResType2.getInterfaceTypeName() + " " + srcResName2 + " = " + dependingGetter + ";"); - } - } - } - // collect the message constraints by a descendant channel. - List varsForSideEffects = new ArrayList<>(); - int v = 0; - resourcePathsAndMessage = curChannel.fillOutsideResourcePaths(out, JavaCodeGenerator.pullAccessor, null); - if (resourcePathsAndMessage != null) { - resourcePaths = resourcePathsAndMessage.getKey(); - Term messageTermSub = resourcePathsAndMessage.getValue(); - for (Entry fieldEnt: ((Term) messageTermSub).getSubTerms(Field.class).entrySet()) { - Position pos = fieldEnt.getKey(); - Field field = fieldEnt.getValue(); - Variable var = new Variable(field.getSymbol().getName(), field.getType()); - ((Term) messageTermSub).replaceSubTerm(pos, var); - } - for (Map.Entry subTermEnt: messageTermSub.getSubTerms(Term.class).entrySet()) { - Term subTerm = subTermEnt.getValue(); - if (!(subTerm instanceof Constant) && subTerm.getSymbol().isImplWithSideEffect()) { - Variable var = new Variable("v" + v, subTerm.getType()); - varsForSideEffects.add(var); - v++; - // Add a side effect statement within the loop - Position pos = new Position(); - pos.addHeadOrder(0); - subTerm.replaceSubTerm(pos, var); - sideEffects = new String[] {""}; - String curState = messageTermSub.toImplementation(sideEffects); - getter.addStatement(sideEffects[0].replaceAll("\n", "")); - // Cancel the side effects in the return value. - pos = subTermEnt.getKey(); - messageTermSub.replaceSubTerm(pos, var); - } - } - if (messageTerm == null) { - messageTerm = messageTermSub; - } else { - messageTerm = (Term) messageTerm.unify(messageTermSub); - } - if (messageTerm == null) { - throw new UnificationFailed(); - } - } - // enclosed by a for loop - Expression selExp = curChannel.getSelectors().get(0).getExpression(); - Type selType = null; - String varName = null; - if (selExp instanceof Variable) { - selType = ((Variable) selExp).getType(); - varName = ((Variable) selExp).getName(); - ChannelMember insideChMem = null; - for (ChannelMember cm2 :curChannel.getInputChannelMembers()) { - if (!cm2.isOutside()) { - insideChMem = cm2; - break; - } - } - if (insideChMem == null) { - for (ChannelMember cm2 :curChannel.getReferenceChannelMembers()) { - if (!cm2.isOutside()) { - insideChMem = cm2; - break; - } - } - } - ResourcePath insideResPath = insideChMem.getResource(); - while (insideResPath.getParent() != null && (insideResPath.getLastParam() == null || !insideResPath.getLastParam().equals(selExp))) { - insideResPath = insideResPath.getParent(); - } - insideResPath = insideResPath.getParent(); - if (insideResPath != null) { - String parent = JavaCodeGenerator.pullAccessor.getDirectStateAccessorFor(insideResPath, dst.getInSideResource(ch)).toImplementation(new String[] {""}); - if (selType.equals(DataConstraintModel.typeInt)) { - // make a for loop (for a list) for data collecting. - getter.addFirstStatement("for (int " + varName + " = 0; " + varName +" < " + parent + ".size(); " + varName + "++) {"); - } else if (selType.equals(DataConstraintModel.typeString)) { - // make a for loop (for a map) for data collecting. - getter.addFirstStatement("for (String " + varName + ": " + parent + ".keySet()) {"); - } - } - } - // initialize the variables to hold side effects within the loop. - for (Variable var: varsForSideEffects) { - getter.addFirstStatement(var.getType().getInterfaceTypeName() + " " + var.getName() + " = new " + var.getType().getImplementationTypeName() + "();"); - } - // end of the loop - getter.addStatement("}"); - if (curChannel.getChildren() != null && curChannel.getChildren().size() > 0) { - channelItrStack.push(chItr); - chItr = curChannel.getChildren().iterator(); - } - } - } while (!channelItrStack.isEmpty()); - } - // generate a return statement. - sideEffects = new String[] {""}; - String curState = ch.deriveUpdateExpressionOf(out, messageTerm, JavaCodeGenerator.pullAccessor).toImplementation(sideEffects); - getter.addStatement(sideEffects[0] + "return " + curState + ";"); - } - if (outsideInputResource) { - // Update fields to refer to outside resources. - Map>> resourcePaths = ch.fillOutsideResourcePaths(out, JavaCodeGenerator.pullAccessor); - if (resourcePaths != null && resourcePaths.size() > 0) { - for (ChannelMember outsideMember: resourcePaths.keySet()) { - ResourcePath outsidePath = resourcePaths.get(outsideMember).getKey(); - if (!JavaCodeGenerator.generatesComponent(outsidePath.getResourceHierarchy())) { - outsidePath = outsidePath.getParent(); - } - String outsideResName = JavaCodeGenerator.toVariableName(JavaCodeGenerator.getComponentName(outsidePath.getResourceHierarchy())); - Set dependedMembers = resourcePaths.get(outsideMember).getValue(); - for (ChannelMember dependedMember: dependedMembers) { - ResourcePath dependedRes = dependedMember.getResource(); - ResourceNode dependedNode = null; - PushPullAttribute pushPull2 = null; - for (Edge resToCh2: resToCh.getDestination().getInEdges()) { - if (((ResourceNode) resToCh2.getSource()).getOutSideResources().contains(dependedRes)) { - dependedNode = (ResourceNode) resToCh2.getSource(); - pushPull2 = (PushPullAttribute) resToCh.getAttribute(); - } - } - TypeDeclaration dependedComponent = null; - if (JavaCodeGenerator.generatesComponent(dependedRes.getResourceHierarchy())) { - String dependedResourceName = JavaCodeGenerator.getComponentName(dependedRes.getResourceHierarchy()); - dependedComponent = componentMap.get(dependedResourceName); - } else { - String dependedParentResourceName = JavaCodeGenerator.getComponentName(dependedRes.getParent().getResourceHierarchy()); - dependedComponent = componentMap.get(dependedParentResourceName); - } - Expression outsideExp = JavaCodeGenerator.pullAccessor.getDirectStateAccessorFor(outsidePath, null); - if (JavaCodeGenerator.generatesComponent(outsidePath.getResourceHierarchy())) { - outsideExp = ((Term) outsideExp).getChild(0); - } - if (dstComponent == dependedComponent) { - // In the common parent. - if (dependedNode != null) { // Inspect further dependency. - for (Edge chToRes2: dependedNode.getInEdges()) { - DataTransferChannel ch2 = ((ChannelNode) chToRes2.getSource()).getChannel(); - if (ch2.getInputChannelMembers().size() == 0) { - // In an input method of the parent component. - Set outs = ch2.getOutputChannelMembers(); - MethodDeclaration input = getInputMethod(dependedComponent, outs.iterator().next(), outs.size()); - String[] sideEffects = new String[] {""}; - String outsideAccessor = outsideExp.toImplementation(sideEffects); - input.addStatement("this." + outsideResName + " = " + outsideAccessor + ";"); // change the reference field. - // Update constructor. - MethodDeclaration constructor = getConstructor(dependedComponent); - constructor.addStatement("this." + outsideResName + " = " + outsideAccessor + ";"); // initialize the reference field. - } else { - boolean isPush = true; - for (Edge resToCh2: chToRes2.getSource().getInEdges()) { - if (((PushPullAttribute) resToCh2.getAttribute()).getSelectedOption() != PushPullValue.PUSH) { - isPush = false; - break; - } - } - if (isPush) { - String[] sideEffects = new String[] {""}; - String outsideAccessor = outsideExp.toImplementation(sideEffects); - for (Edge resToCh2: chToRes2.getSource().getInEdges()) { - // In an update method of the parent component. - ResourceNode dependingResSrc = (ResourceNode) resToCh2.getSource(); - MethodDeclaration update = null; - if (JavaCodeGenerator.generatesComponent(dependedRes.getResourceHierarchy())) { - update = getUpdateMethod(dependedComponent, null, JavaCodeGenerator.getComponentName(dependingResSrc.getResourceHierarchy())); - } else { - String dependingResName = JavaCodeGenerator.getComponentName(dependedRes.getResourceHierarchy()); - update = getUpdateMethod(dependedComponent, dependingResName, JavaCodeGenerator.getComponentName(dependingResSrc.getResourceHierarchy())); - } - update.addStatement("this." + outsideResName + " = " + outsideAccessor + ";"); // change the reference field. - } - // Update constructor. - MethodDeclaration constructor = getConstructor(dependedComponent); - constructor.addStatement("this." + outsideResName + " = " + outsideAccessor + ";"); // initialize the reference field. - } - } - } - } - } else { - if (pushPull2.getSelectedOption() == PushPullValue.PUSH) { - // In an update method of the destination component. - MethodDeclaration update = null; - if (JavaCodeGenerator.generatesComponent(dst.getResourceHierarchy())) { - update = getUpdateMethod(dstComponent, null, JavaCodeGenerator.getComponentName(dependedRes.getResourceHierarchy())); - } else { - String dstResName = JavaCodeGenerator.getComponentName(dst.getResourceHierarchy()); - update = getUpdateMethod(dstComponent, dstResName, JavaCodeGenerator.getComponentName(dependedRes.getResourceHierarchy())); - } - String[] sideEffects = new String[] {""}; - String outsideAccessor = outsideExp.toImplementation(sideEffects); - update.addStatement("this." + outsideResName + " = " + outsideAccessor + ";"); // change the reference field. - // Update constructor. - MethodDeclaration constructor = getConstructor(dstComponent); - constructor.addStatement("this." + outsideResName + " = " + outsideAccessor + ";"); // initialize the reference field. - } - } - } - } - } - } - } - } - } - } - } - } - - // for source nodes - TypeDeclaration mainComponent = componentMap.get(JavaCodeGenerator.mainTypeName); - for (ResourceHierarchy resource: model.getResourceHierarchies()) { - String resourceName = JavaCodeGenerator.getComponentName(resource); - TypeDeclaration component = componentMap.get(resourceName); - if (JavaCodeGenerator.generatesComponent(resource)) { - if (component != null) { - // state getter method - Type resourceType = JavaCodeGenerator.getImplStateType(resource); - MethodDeclaration stateGetter = getMethod(component, "getValue"); - if (stateGetter != null && (stateGetter.getBody() == null || stateGetter.getBody().getStatements().size() == 0)) { - if (model.isPrimitiveType(resourceType)) { - // primitive type - stateGetter.addStatement("return value;"); - } else { - if (resource.getChildren() != null && resource.getChildren().size() == 1 && resource.getChildren().iterator().next().getNumParameters() > 0) { - // list or map - String implTypeName = resourceType.getImplementationTypeName(); - // copy the current state to be returned as a 'value' - stateGetter.addStatement("return new " + implTypeName + "(value);"); - } else { - if (resource.getChildren() == null || resource.getChildren().size() == 0) { - // a leaf resource - String implTypeName = resourceType.getImplementationTypeName(); - stateGetter.addStatement("return new " + implTypeName + "(value);"); - } else { - Term composer = null; - Term composerSub = new Constant(DataConstraintModel.nil); - composerSub.setType(DataConstraintModel.typeMap); - for (ResourceHierarchy child: resource.getChildren()) { - String childTypeName = JavaCodeGenerator.getComponentName(child); - String fieldName = JavaCodeGenerator.toVariableName(childTypeName); - Term childGetter = null; - if (!JavaCodeGenerator.generatesComponent(child)) { - // the child is not a class - childGetter = new Term(new Symbol("get" + childTypeName, 1, Symbol.Type.METHOD)); - childGetter.addChild(new Constant("this")); - } else { - // the child is a class - childGetter = new Term(new Symbol("getValue", 1, Symbol.Type.METHOD)); - childGetter.addChild(new Field(fieldName, JavaCodeGenerator.getImplStateType(child))); - } - composer = new Term(DataConstraintModel.insert); - composer.addChild(composerSub); - composer.addChild(new Constant(fieldName, DataConstraintModel.typeString)); // key - composer.addChild(childGetter); // value - composer.setType(DataConstraintModel.typeMap); - composerSub = composer; - } - composer.setType(stateGetter.getReturnType()); - String[] sideEffects = new String[] {""}; - String returnValue = composer.toImplementation(sideEffects); - if (sideEffects[0] != null) { - stateGetter.addStatement(sideEffects[0] + "return " + returnValue+ ";"); - } else { - stateGetter.addStatement("return " + returnValue+ ";"); - } - } - } - } - } - - // (#4) descendant getter method (the implementation must be kept consistent with #3) - if (resource.getChildren().size() > 0) { - for (ResourceHierarchy child: resource.getChildren()) { - ResourceHierarchy parent = resource; - ResourceHierarchy descendant = child; - Set children; - Expression selector; - int params = 0; - if (DataConstraintModel.typeList.isAncestorOf(parent.getResourceStateType())) { - selector = new Field("value"); - params++; - } else if (DataConstraintModel.typeMap.isAncestorOf(parent.getResourceStateType())) { - selector = new Field("value"); - params++; - } else { - String fieldName = JavaCodeGenerator.getComponentName(descendant); - selector = new Field(JavaCodeGenerator.toVariableName(fieldName)); - } - do { - String methodName = JavaCodeGenerator.getComponentName(descendant); - MethodDeclaration descendantGetter = null; - for (MethodDeclaration getter: getGetterMethods(component, methodName)) { - if ((getter.getParameters() == null && params == 0) || (getter.getParameters() != null && getter.getParameters().size() == params)) { - descendantGetter = getter; - break; - } - } - if (descendantGetter != null) { - if (DataConstraintModel.typeList.isAncestorOf(parent.getResourceStateType())) { - Term newSelector = new Term(DataConstraintModel.get); - newSelector.addChild(selector); - newSelector.addChild(new Variable(descendantGetter.getParameters().get(descendantGetter.getParameters().size() - 1).getName())); - newSelector.setType(descendantGetter.getReturnType()); - selector = newSelector; - } else if (DataConstraintModel.typeMap.isAncestorOf(parent.getResourceStateType())) { - Term newSelector = new Term(DataConstraintModel.lookup); - newSelector.addChild(selector); - newSelector.addChild(new Variable(descendantGetter.getParameters().get(descendantGetter.getParameters().size() - 1).getName())); - newSelector.setType(descendantGetter.getReturnType()); - selector = newSelector; - } - if (descendantGetter != null && (descendantGetter.getBody() == null || descendantGetter.getBody().getStatements().size() == 0)) { - String[] sideEffects = new String[] {null}; - String returnValue = selector.toImplementation(sideEffects); - if (sideEffects[0] != null) descendantGetter.addStatement(sideEffects[0]); - descendantGetter.addStatement("return " + returnValue + ";"); - } - } - if (JavaCodeGenerator.generatesComponent(descendant)) { - // If the descendant generates a component. - break; - } - parent = descendant; - if (DataConstraintModel.typeList.isAncestorOf(parent.getResourceStateType())) { - params++; - } else if (DataConstraintModel.typeMap.isAncestorOf(parent.getResourceStateType())) { - params++; - } - children = descendant.getChildren(); - } while (children != null && children.size() == 1 && (descendant = children.iterator().next()) != null); - } - } - } - } - - // methods for input events - Map> ioChannelsAndMembers = getIOChannelsAndMembers(resource, model); - for (Map.Entry> entry: ioChannelsAndMembers.entrySet()) { - Set outs = entry.getValue(); - DataTransferChannel ch = entry.getKey(); - for (ChannelMember out: outs) { - MethodDeclaration input = null; - if (JavaCodeGenerator.generatesComponent(resource)) { - // A component is generated for this resource. - input = getInputMethod(component, out, ch.getOutputChannelMembers().size()); - } else { - // No component is generated for this resource. - ResourceHierarchy parent = resource.getParent(); - if (parent != null) { - TypeDeclaration parentType = componentMap.get(JavaCodeGenerator.getComponentName(parent)); - input = getInputMethod(parentType, out, ch.getOutputChannelMembers().size()); - } - } - if (input != null) { - // In each resource - Expression updateExp = ch.deriveUpdateExpressionOf(out, JavaCodeGenerator.refAccessor).getKey(); - // Replace Json constructor with a constructor of a descendant resource. - ResourceHierarchy outRes = out.getResource().getResourceHierarchy(); - if (outRes.getChildren().size() == 1 && outRes.getChildren().iterator().next().getNumParameters() > 0) { - ResourceHierarchy descendantRes = outRes.getChildren().iterator().next(); - Set children; - do { - if (JavaCodeGenerator.generatesComponent(descendantRes)) break; - children = descendantRes.getChildren(); - } while (children != null && children.size() == 1 && (descendantRes = children.iterator().next()) != null); - Type descendantStateType = descendantRes.getResourceStateType(); - String descendantComponentName = JavaCodeGenerator.getComponentName(descendantRes); - TypeDeclaration descendantComponent = componentMap.get(descendantComponentName); - if (DataConstraintModel.typeJson.isAncestorOf(descendantStateType)) { - replaceJsonTermWithConstructorInvocation(updateExp, descendantStateType, descendantComponentName, descendantComponent); - } - } - // Replace the type of the state field. - Type fieldType = JavaCodeGenerator.getImplStateType(outRes); - if (updateExp instanceof Term) { - ((Term) updateExp).setType(fieldType); - for (Map.Entry varEnt: ((Term) updateExp).getVariables().entrySet()) { - if (varEnt.getValue().getName().equals("value")) { - varEnt.getValue().setType(fieldType); - } - } - } else if (updateExp instanceof Variable) { - ((Variable) updateExp).setType(fieldType); - } - // Add statements to the input method. - String[] sideEffects = new String[] {""}; - String newState = updateExp.toImplementation(sideEffects); - if (JavaCodeGenerator.generatesComponent(resource)) { - String updateStatement; - 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] + "this.value = " + newState + ";"; - } - if (input.getBody() == null || !input.getBody().getStatements().contains(updateStatement)) { - input.addFirstStatement(updateStatement); - } - } else { - String updateStatement = ""; - if (sideEffects[0] != null) { - updateStatement = sideEffects[0]; - updateStatement = updateStatement.replace(".value", "." + JavaCodeGenerator.toVariableName(JavaCodeGenerator.getComponentName(resource))); - if (updateStatement.endsWith("\n")) { - updateStatement = updateStatement.substring(0, updateStatement.length() - 1); - } - } - if (DataConstraintModel.typeList.isAncestorOf(resource.getParent().getResourceStateType())) { - Term selector = new Term(DataConstraintModel.set); - selector.addChild(new Field("value")); - selector.addChild(new Variable(input.getParameters().get(input.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(resource.getParent().getResourceStateType())) { - Term selector = new Term(DataConstraintModel.insert); - selector.addChild(new Field("value")); - selector.addChild(new Variable(input.getParameters().get(input.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())) { - updateStatement += "this." + JavaCodeGenerator.toVariableName(JavaCodeGenerator.getComponentName(resource)) + " = " + newState + ";"; - } - if (updateStatement != null && (input.getBody() == null || !input.getBody().getStatements().contains(updateStatement))) { - input.addFirstStatement(updateStatement); - } - } - - // In the main type - if (mainComponent != null) { - Expression message = out.getStateTransition().getMessageExpression(); - String inputAccessorName = input.getName(); - if (message instanceof Term) { - inputAccessorName = ((Term) message).getSymbol().getImplName(); - } else if (message instanceof Variable) { - inputAccessorName = ((Variable) message).getName(); - } - MethodDeclaration inputAccessor = getMethod(mainComponent, inputAccessorName); - if (inputAccessor != null) { - Set referredSet = referredResources.get(input); - for (ChannelMember rc: ch.getReferenceChannelMembers()) { - // For each reference channel member, get the current state of the reference side resource by pull data transfer. - ResourcePath ref = rc.getResource(); - if (referredSet == null) { - referredSet = new HashSet<>(); - referredResources.put(input, referredSet); - } - if (!out.getResource().equals(ref)) { - String refVarName = ref.getLeafResourceName(); - if (!referredSet.contains(ref)) { - referredSet.add(ref); - Expression refGetter = JavaCodeGenerator.pullAccessor.getDirectStateAccessorFor(ref, null); - sideEffects = new String[] {""}; - String refExp = refGetter.toImplementation(sideEffects); - String refTypeName = ref.getResourceStateType().getInterfaceTypeName(); - inputAccessor.addFirstStatement(sideEffects[0] + refTypeName + " " + refVarName + " = " + refExp + ";"); - } - } - } - Expression resExp = JavaCodeGenerator.pullAccessor.getDirectStateAccessorFor(out.getResource(), null); - List args = new ArrayList<>(); - if (resExp instanceof Term) { - // To access the parent resource if the leaf resource is primitive and cannot declare the input method, or to remove getValue(). - if (((Term) resExp).getChildren().size() > 1 && ((Term) resExp).getChild(1) instanceof Variable) { - args.add(((Variable)((Term) resExp).getChild(1)).getName()); - } - resExp = ((Term) resExp).getChild(0); - } - // Values of channel parameters. - for (Selector selector: ch.getAllSelectors()) { - if (selector.getExpression() instanceof Variable) { - Variable selVar = (Variable) selector.getExpression(); - if (!args.contains(selVar.getName())) { - args.add(selVar.getName()); - } - } - } - // Values of message parameters. - if (message instanceof Term) { - for (Map.Entry varEnt: message.getVariables().entrySet()) { - String refVarName = null; - for (ChannelMember rc: ch.getReferenceChannelMembers()) { - Expression varExp = rc.getStateTransition().getMessageExpression().getSubTerm(varEnt.getKey()); - if (varExp != null && rc.getStateTransition().getCurStateExpression().contains(varExp)) { - refVarName = rc.getResource().getLeafResourceName(); - break; - } - } - if (refVarName != null) { - if (!args.contains(refVarName)) { - args.add(refVarName); - } - } else { - if (!args.contains(varEnt.getValue().getName())) { - args.add(varEnt.getValue().getName()); - } - } - } - } - String argsStr = ""; - String delimiter = ""; - for (String arg: args) { - argsStr += delimiter + arg; - delimiter = ", "; - } - if (resExp != null) { - String resourceAccess = resExp.toImplementation(new String[] {null}); - inputAccessor.addStatement(resourceAccess + "." + input.getName() + "(" + argsStr + ");"); - } else { - inputAccessor.addStatement(input.getName() + "(" + argsStr + ");"); - } - } - } - } - } - } - } - } catch (ParameterizedIdentifierIsFutureWork | ResolvingMultipleDefinitionIsFutureWork - | InvalidMessage | UnificationFailed | ValueUndefined e1) { - e1.printStackTrace(); - } - return codes; - } - - private static void replaceJsonTermWithConstructorInvocation(Expression exp, Type replacedJsonType, String replacingClassName, TypeDeclaration descendantComponent) { - // Replace each json term in exp with the corresponding constructor invocation. - Type descendantType = new Type(replacingClassName, replacingClassName); - Map subTerms = ((Term) exp).getSubTerms(Term.class); - Iterator> termEntItr = subTerms.entrySet().iterator(); - while (termEntItr.hasNext()) { - Entry termEnt = termEntItr.next(); - Term jsonTerm = termEnt.getValue(); - if (jsonTerm.getType() != null) { - if (jsonTerm.getType().equals(replacedJsonType)) { - if (jsonTerm instanceof JsonTerm || jsonTerm.getSymbol().equals(DataConstraintModel.addMember)) { - String constructorInvocation = "new " + replacingClassName + "("; - MethodDeclaration descendantConstructor = getConstructor(descendantComponent); - String delimiter = ""; - if (descendantConstructor != null) { - for (VariableDeclaration var: descendantConstructor.getParameters()) { - // Extract the argument of each constructor parameter from jsonTerm. - JsonAccessor jsonMember = new JsonAccessor(DataConstraintModel.dot); - jsonMember.addChild(jsonTerm); - jsonMember.addChild(new Constant(var.getName(), DataConstraintModel.typeString)); - Expression param = jsonMember.reduce(); // Reduce {"name": "foo", age: 25}.name => "foo" - if (param != null) { - if (param instanceof Term) { - if (((Term) param).getType() == null) { - ((Term) param).setType(var.getType()); - } - } else if (param instanceof Variable) { - if (((Variable) param).getType() == null) { - ((Variable) param).setType(var.getType()); - } - } - constructorInvocation = constructorInvocation + delimiter + param.toImplementation(null); - } else { - constructorInvocation = constructorInvocation + delimiter + var.getName(); - } - delimiter = ", "; - } - } - constructorInvocation += ")"; - ((Term) exp).replaceSubTerm(termEnt.getKey(), new Constant(constructorInvocation, descendantType)); - subTerms = ((Term) exp).getSubTerms(Term.class); - termEntItr = subTerms.entrySet().iterator(); - } else { - jsonTerm.setType(descendantType); - } - } else { - Type oldType = jsonTerm.getType(); - Type newType = new Type(oldType.getTypeName(), - oldType.getImplementationTypeName().replace(replacedJsonType.getInterfaceTypeName(), replacingClassName), - oldType.getInterfaceTypeName().replace(replacedJsonType.getInterfaceTypeName(), replacingClassName)); - for (Type parent: oldType.getParentTypes()) { - newType.addParentType(parent); - } - jsonTerm.setType(newType); - } - } - } - } - - private static MethodDeclaration getConstructor(TypeDeclaration component) { - for (MethodDeclaration m: component.getMethods()) { - if (m.isConstructor()) return m; - } - return null; - } - - private static MethodDeclaration getUpdateMethod(TypeDeclaration component, String dstResName, String srcResName) { - for (MethodDeclaration m: component.getMethods()) { - if (dstResName == null) { - if (m.getName().equals("updateFrom" + srcResName)) return m; - } else { - if (m.getName().equals("update" + dstResName + "From" + srcResName)) return m; - } - } - return null; - } - - private static List getUpdateMethods(TypeDeclaration component, String resName) { - List updates = new ArrayList<>(); - for (MethodDeclaration m: component.getMethods()) { - if (resName == null) { - if (m.getName().startsWith("updateFrom")) { - updates.add(m); - } - } else { - if (m.getName().startsWith("update" + resName + "From")) { - updates.add(m); - } - } - } - return updates; - } - - private static MethodDeclaration getGetterMethod(TypeDeclaration component, String resourceName) { - for (MethodDeclaration m: component.getMethods()) { - if (m.getName().startsWith("get" + resourceName)) return m; - } - return null; - } - - private static List getGetterMethods(TypeDeclaration component, String resourceName) { - List getters = new ArrayList<>(); - for (MethodDeclaration m: component.getMethods()) { - if (m.getName().equals("get" + resourceName)) { - getters.add(m); - } - } - return getters; - } - - private static Map> getIOChannelsAndMembers(ResourceHierarchy resource, DataTransferModel model) { - Map> ioChannelsAndMembers = new HashMap<>(); - for (Channel c: model.getInputChannels()) { - DataTransferChannel ch = (DataTransferChannel) c; - // I/O channel - for (ChannelMember out: ch.getOutputChannelMembers()) { - if (resource.equals(out.getResource().getResourceHierarchy())) { - if (out.getStateTransition().getMessageExpression() instanceof Term || out.getStateTransition().getMessageExpression() instanceof Variable) { - Set channelMembers = ioChannelsAndMembers.get(ch); - if (channelMembers == null) { - channelMembers = new HashSet<>(); - ioChannelsAndMembers.put(ch, channelMembers); - } - channelMembers.add(out); - } - } - } - } - return ioChannelsAndMembers; - } - - private static List getInputMethods(TypeDeclaration component, ResourceNode resource, DataTransferModel model) { - List inputs = new ArrayList<>(); - for (Channel c: model.getInputChannels()) { - DataTransferChannel channel = (DataTransferChannel) c; - // I/O channel - for (ChannelMember out: channel.getOutputChannelMembers()) { - if (resource.getInSideResources().contains(out.getResource())) { - MethodDeclaration input = getInputMethod(component, out, channel.getOutputChannelMembers().size()); - inputs.add(input); - } - } - } - return inputs; - } - - private static List getInputMethods(TypeDeclaration component, ResourceHierarchy resource, DataTransferModel model) { - List inputs = new ArrayList<>(); - for (Channel c: model.getInputChannels()) { - DataTransferChannel channel = (DataTransferChannel) c; - // I/O channel - for (ChannelMember out: channel.getOutputChannelMembers()) { - if (resource.equals(out.getResource().getResourceHierarchy())) { - MethodDeclaration input = getInputMethod(component, out, channel.getOutputChannelMembers().size()); - inputs.add(input); - } - } - } - return inputs; - } - - private static MethodDeclaration getInputMethod(TypeDeclaration component, ChannelMember cm, int outNumber) { - String inputMethodName = null; - if (cm.getStateTransition().getMessageExpression() instanceof Term) { - Term message = (Term) cm.getStateTransition().getMessageExpression(); - inputMethodName =message.getSymbol().getImplName(); - } else if (cm.getStateTransition().getMessageExpression() instanceof Variable) { - Variable message = (Variable) cm.getStateTransition().getMessageExpression(); - inputMethodName = message.getName(); - } - if (outNumber > 1) { - inputMethodName += "For" + JavaCodeGenerator.getComponentName(cm.getResource().getResourceHierarchy()); - } - MethodDeclaration input = getMethod(component, inputMethodName); - return input; - } - - private static MethodDeclaration getMethod(TypeDeclaration component, String methodName) { - for (MethodDeclaration m: component.getMethods()) { - if (m.getName().equals(methodName)) return m; - } - return null; - } -} diff --git a/AlgebraicDataflowArchitectureModel/src/generators/JerseyCodeGenerator.java b/AlgebraicDataflowArchitectureModel/src/generators/JerseyCodeGenerator.java deleted file mode 100644 index 68e4aa9..0000000 --- a/AlgebraicDataflowArchitectureModel/src/generators/JerseyCodeGenerator.java +++ /dev/null @@ -1,1604 +0,0 @@ -package generators; - -import java.util.AbstractMap; -import java.util.ArrayList; -import java.util.Collection; -import java.util.HashMap; -import java.util.HashSet; -import java.util.List; -import java.util.Map; -import java.util.Set; -import java.util.Stack; - -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; -import models.Edge; -import models.Node; -import models.algebra.Expression; -import models.algebra.Field; -import models.algebra.Parameter; -import models.algebra.Position; -import models.algebra.Symbol; -import models.algebra.Term; -import models.algebra.Type; -import models.algebra.Variable; -import models.dataConstraintModel.Channel; -import models.dataConstraintModel.ChannelMember; -import models.dataConstraintModel.DataConstraintModel; -import models.dataConstraintModel.ResourceHierarchy; -import models.dataConstraintModel.ResourcePath; -import models.dataConstraintModel.Selector; -import models.dataFlowModel.DataTransferModel; -import models.dataFlowModel.DataTransferChannel; -import models.dataFlowModel.DataTransferChannel.IResourceStateAccessor; -import models.dataFlowModel.PushPullAttribute; -import models.dataFlowModel.PushPullValue; -import models.dataFlowModel.DataFlowEdge; -import models.dataFlowModel.DataFlowGraph; -import models.dataFlowModel.ResourceNode; -import models.dataFlowModel.ChannelNode; -import models.dataFlowModel.StoreAttribute; - -/** - * Generator for Jersey prototypes - * - * @author Nitta - * - */ -public class JerseyCodeGenerator { - public static final Type typeVoid = new Type("Void", "void"); - public static final Type typeClient = new Type("Client", "Client"); - public static boolean differentTreesAsDifferentServices = true; - private static String defaultMainTypeName = "Main"; - static String mainTypeName = defaultMainTypeName; - - public static String getMainTypeName() { - return mainTypeName; - } - - public static void setMainTypeName(String mainTypeName) { - JerseyCodeGenerator.mainTypeName = mainTypeName; - } - - public static void resetMainTypeName() { - JerseyCodeGenerator.mainTypeName = defaultMainTypeName; - } - - public static String getComponentName(ResourceHierarchy res) { - String name = res.getResourceName(); - if (res.getNumParameters() > 0) { - if (name.length() > 3 && name.endsWith("ies")) { - name = name.substring(0, name.length() - 3) + "y"; - } else if (name.length() > 1 && name.endsWith("s")) { - name = name.substring(0, name.length() - 1); - } else { - name += "Element"; - } - } - return name.substring(0, 1).toUpperCase() + name.substring(1); - } - - public static String toVariableName(String name) { - return name.substring(0, 1).toLowerCase() + name.substring(1); - } - - public static Type getImplStateType(ResourceHierarchy res) { - Set children = res.getChildren(); - if (children == null || children.size() == 0) { - // leaf resource. - return res.getResourceStateType(); - } else { - ResourceHierarchy child = children.iterator().next(); - if (children.size() == 1 && child.getNumParameters() > 0) { - // map or list. - if (DataConstraintModel.typeList.isAncestorOf(res.getResourceStateType())) { - // list. - if (generatesComponent(child)) { - return new Type("List", "ArrayList<>", "List<" + getComponentName(child) + ">", DataConstraintModel.typeList); - } else { - return new Type("List", "ArrayList<>", "List<" + getImplStateType(child).getInterfaceTypeName() + ">", DataConstraintModel.typeList); - } - } else if (DataConstraintModel.typeMap.isAncestorOf(res.getResourceStateType())) { - // map. - if (generatesComponent(child)) { - return new Type("Map", "HashMap<>", "Map", DataConstraintModel.typeMap); - } else { - return new Type("Map", "HashMap<>", "Map", DataConstraintModel.typeMap); - } - } - return null; - } else { - // class - return res.getResourceStateType(); - } - } - } - - public static boolean generatesComponent(ResourceHierarchy res) { - if (res.getParent() == null) return true; - if (res.getChildren() == null || res.getChildren().size() == 0) return false; - if (res.getNumParameters() > 0 && res.getChildren().size() == 1 && res.getChildren().iterator().next().getNumParameters() > 0) return false; - if (res.getChildren().size() == 1 && res.getChildren().iterator().next().getNumParameters() > 0 - && (res.getChildren().iterator().next().getChildren() == null || res.getChildren().iterator().next().getChildren().size() == 0)) return false; - return true; -// return res.getParent() == null || !(res.getChildren() == null || res.getChildren().size() == 0); - } - - static public ArrayList doGenerate(DataFlowGraph graph, DataTransferModel model) { - ArrayList codes = new ArrayList<>(); -// ArrayList resources = StoreResourceCheck(graph); - Collection resources = graph.getResourceNodes(); - Map resourceComponents = new HashMap<>(); - Map resourceConstructors = new HashMap<>(); - List> getters = new ArrayList<>(); - Map> updates = new HashMap<>(); - Map> inputs = new HashMap<>(); - List> fields = new ArrayList<>(); - Map> descendantGetters = new HashMap<>(); - Map getterAccessors = new HashMap<>(); - Map> inputAccessors = new HashMap<>(); - Map> constructorParams = new HashMap<>(); - Map priorMemberForInputChannel = new HashMap<>(); - - // For each resource node. - for (Node n : resources) { - ResourceNode resourceNode = (ResourceNode) n; - TypeDeclaration component = null; - if (generatesComponent(resourceNode.getResourceHierarchy())) { - String resourceName = getComponentName(resourceNode.getResourceHierarchy()); - - component = resourceComponents.get(resourceNode.getResourceHierarchy()); - if (component == null) { - // Add compilation unit for each resource. - component = new TypeDeclaration(resourceName); - if (resourceNode.getResourceHierarchy().getParent() == null) { - // For a root node. - component.addAnnotation(new Annotation("Component")); - component.addAnnotation(new Annotation("Path", "\"/" + resourceNode.getResourceName() + "\"")); - } - resourceComponents.put(resourceNode.getResourceHierarchy(), component); - - CompilationUnit cu = new CompilationUnit(component); - cu.addImport(new ImportDeclaration("java.util.*")); - if (resourceNode.getResourceHierarchy().getParent() == null) { - // For a root node. - cu.addImport(new ImportDeclaration("jakarta.ws.rs.*")); - cu.addImport(new ImportDeclaration("jakarta.ws.rs.client.*")); - cu.addImport(new ImportDeclaration("jakarta.ws.rs.core.*")); - cu.addImport(new ImportDeclaration("org.springframework.stereotype.Component")); - cu.addImport(new ImportDeclaration("com.fasterxml.jackson.databind.ObjectMapper")); - cu.addImport(new ImportDeclaration("com.fasterxml.jackson.core.JsonProcessingException")); - } - codes.add(cu); - - // Declare the field to store the state in the type of each resource. - if (((StoreAttribute) resourceNode.getAttribute()).isStored()) { - ResourceHierarchy res = resourceNode.getResourceHierarchy(); - Set children = res.getChildren(); - if (children == null || children.size() == 0) { - // leaf resource. - Type fieldType = getImplStateType(res); - component.addField(new FieldDeclaration(fieldType, "value", getInitializer(res))); - // Add a parameter to initialize the state field to the constructor. -// Map nameToParam = constructorParams.get(res); -// if (nameToParam == null) { -// nameToParam = new HashMap<>(); -// constructorParams.put(resourceNode.getResourceHierarchy(), nameToParam); -// } -// String varName = "value"; -// if (nameToParam.get(varName) == null) { -// nameToParam.put(varName, new VariableDeclaration(fieldType, varName)); -// } - } else { - ResourceHierarchy child = children.iterator().next(); - if (children.size() == 1 && child.getNumParameters() > 0) { - // map or list. - component.addField(new FieldDeclaration(getImplStateType(res), "value", getInitializer(res))); - } else { - // class - for (ResourceHierarchy c: children) { - String childTypeName = getComponentName(c); - Type childType = null; - if (generatesComponent(c)) { - // The child has a component. - childType = new Type(childTypeName, childTypeName); - String fieldName = toVariableName(childTypeName); - component.addField(new FieldDeclaration(childType, fieldName, "new " + childTypeName + "()")); - } - } - } - } - } - - // Declare the getter method to obtain the resource state in the component of each resource. - MethodDeclaration stateGetter = new MethodDeclaration("getValue", getImplStateType(resourceNode.getResourceHierarchy())); - if (resourceNode.getResourceHierarchy().getParent() == null) { - // Since this getter is also an accessor. - stateGetter.addAnnotation(new Annotation("Produces", "MediaType.APPLICATION_JSON")); - stateGetter.addAnnotation(new Annotation("GET")); - } - component.addMethod(stateGetter); - } - if (component != null) { - // (#1) Declare the getter methods in this resource to obtain descendant resources. (complementary to #2) - Set descendants = descendantGetters.get(resourceNode.getResourceHierarchy()); - if (descendants == null) { - descendants = new HashSet<>(); - descendantGetters.put(resourceNode.getResourceHierarchy(), descendants); - } - for (ResourceNode child: resourceNode.getChildren()) { - // A descendant of the child may generate a component. - List pathParams = new ArrayList<>(); - int v = 1; - ResourceNode descendant = child; - Set childNodes; - do { - Expression pathParam = descendant.getPrimaryResourcePath().getLastParam(); - if (pathParam != null) { - if (pathParam instanceof Variable) { - Variable var = (Variable) pathParam; - pathParams.add(new VariableDeclaration(var.getType(), var.getName())); - } else if (pathParam instanceof Term) { - Term var = (Term) pathParam; - pathParams.add(new VariableDeclaration(var.getType(), "v" + v)); - } - v++; - } - if (generatesComponent(descendant.getResourceHierarchy())) { - // If the descendant generates a component. - if (!descendants.contains(descendant.getResourceHierarchy())) { - descendants.add(descendant.getResourceHierarchy()); - String descendantCompName = getComponentName(descendant.getResourceHierarchy()); - Type descendantType = new Type(descendantCompName, descendantCompName); - MethodDeclaration descendantGetter = null; - if (pathParams.size() == 0) { - descendantGetter = new MethodDeclaration("get" + descendantCompName, descendantType); - } else { - descendantGetter = new MethodDeclaration("get" + descendantCompName, false, descendantType, pathParams); - } - component.addMethod(descendantGetter); - } - break; - } - childNodes = descendant.getChildren(); - } while (childNodes != null && childNodes.size() == 1 && (descendant = childNodes.iterator().next()) != null); - } - } - -// // Declare a client field to connect to the source resource of reference transfer. -// if (!bDeclareClientField) { -// for (ChannelGenerator cg : model.getChannelGenerators()) { -// DataflowChannelGenerator dcg = ((DataflowChannelGenerator) cg); -// for (ChannelMember cm : dcg.getOutputChannelMembers()) { -// if (cm.getIdentifierTemplate().getResourceName().equals(type.getTypeName().toLowerCase())) { -// if (dcg.getReferenceChannelMembers().size() > 0) { -// // If there exists one or more reference channel member. -// type.addField(new FieldDeclaration(typeClient, "client", "ClientBuilder.newClient()")); -// bDeclareClientField = true; -// break; -// } -// } -// } -// if (bDeclareClientField) break; -// } -// } - } - - // Declare the state field and reference fields in the parent component. - boolean bDeclareClientField = false; - if (component == null) { - // Declare reference fields for push/pull data transfer. - boolean noPullTransfer = true; - for (Edge resToCh : resourceNode.getOutEdges()) { - DataFlowEdge re = (DataFlowEdge) resToCh; - DataTransferChannel ch = ((ChannelNode) re.getDestination()).getChannel(); - for (Edge chToRes: re.getDestination().getOutEdges()) { - ResourceHierarchy dstRes = ((ResourceNode) chToRes.getDestination()).getResourceHierarchy(); - // Check if the output resource is outside of the channel scope. - boolean outsideOutputResource = false; - for (ChannelMember cm: ch.getOutputChannelMembers()) { - if (((ResourceNode) chToRes.getDestination()).getInSideResources().contains(cm.getResource()) && cm.isOutside()) { - outsideOutputResource = true; // Regarded as push transfer. - break; - } - } - if (outsideOutputResource) { - // Declare a field in the parent component to refer to the destination resource of push transfer. - if (!generatesComponent(dstRes)) { - dstRes = dstRes.getParent(); - } - String dstResName = getComponentName(dstRes); -// if (resourceNode.getOutSideResource().getCommonPrefix(dstRes) == null && differentTreesAsDifferentServices) { - // Inter-service - if (!bDeclareClientField) { - // Declare a client field to connect to the destination resource of push transfer. - FieldDeclaration clientField = new FieldDeclaration(typeClient, "client", "ClientBuilder.newClient()"); - 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)); -// } -// } - } - } - } - for (Edge chToRes : resourceNode.getInEdges()) { - for (Edge resToCh: chToRes.getSource().getInEdges()) { - DataFlowEdge re = (DataFlowEdge) resToCh; - DataTransferChannel ch = ((ChannelNode) re.getDestination()).getChannel(); - ResourcePath srcRes = ((ResourceNode) re.getSource()).getOutSideResource(ch); - // Check if the input resource is outside of the channel scope. - boolean outsideInputResource = false; - for (ChannelMember cm: ch.getInputChannelMembers()) { - if (cm.getResource().equals(srcRes) && cm.isOutside()) { - outsideInputResource = true; // Regarded as pull transfer. - break; - } - } - if (outsideInputResource) { - // Declare a field in the parent component to refer to the source resource of pull transfer. - if (!generatesComponent(srcRes.getResourceHierarchy())) { - srcRes = srcRes.getParent(); - } - String srcResName = getComponentName(srcRes.getResourceHierarchy()); -// if (resourceNode.getOutSideResource().getCommonPrefix(srcRes) == null && differentTreesAsDifferentServices) { - // Inter-service - if (!bDeclareClientField) { - // Declare a client field to connect to the source resource of pull transfer. - FieldDeclaration clientField = new FieldDeclaration(typeClient, "client", "ClientBuilder.newClient()"); - 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)); -// } -// } - noPullTransfer = false; - } - } - } - // Declare the state field in the parent component. - ResourceHierarchy res = resourceNode.getResourceHierarchy(); - if (((StoreAttribute) resourceNode.getAttribute()).isStored() && noPullTransfer && res.getNumParameters() == 0) { - String resName = getComponentName(res); - FieldDeclaration stateField = new FieldDeclaration(res.getResourceStateType(), toVariableName(resName)); - fields.add(new AbstractMap.SimpleEntry<>(resourceNode.getParent().getResourceHierarchy(), stateField)); - - - Map nameToParam = constructorParams.get(resourceNode.getParent().getResourceHierarchy()); - if (nameToParam == null) { - nameToParam = new HashMap<>(); - constructorParams.put(resourceNode.getParent().getResourceHierarchy(), nameToParam); - } - String varName = toVariableName(resName); - if (nameToParam.get(varName) == null) { - nameToParam.put(varName, new VariableDeclaration(res.getResourceStateType(), varName)); - } - } - } - - // (#2) Declare the getter method to obtain the resource state in an ancestor component. (complementary to #1) - if (component == null) { - // No component is created for this resource. - ResourceNode ancestorNode = resourceNode; - Stack ancestors = new Stack<>(); - do { - ancestors.push(ancestorNode); - ancestorNode = ancestorNode.getParent(); - } while (!generatesComponent(ancestorNode.getResourceHierarchy())); - List pathParams = new ArrayList<>(); - int v = 1; - while (ancestors.size() > 0) { - ResourceNode curAncestor = ancestors.pop(); - Expression pathParam = curAncestor.getPrimaryResourcePath().getLastParam(); - if (pathParam instanceof Variable) { - Variable var = (Variable) pathParam; - pathParams.add(new VariableDeclaration(var.getType(), var.getName())); - } else if (pathParam instanceof Term) { - Term var = (Term) pathParam; - pathParams.add(new VariableDeclaration(var.getType(), "v" + v)); - } - v++; - } - String getterName = "get" + getComponentName(resourceNode.getResourceHierarchy()); - boolean bExists = false; - for (Map.Entry entry: getters) { - ResourceHierarchy r = entry.getKey(); - MethodDeclaration m = entry.getValue(); - if (r == ancestorNode.getResourceHierarchy() && m.getName().equals(getterName) - && (m.getParameters() == null ? 0 : m.getParameters().size()) == pathParams.size()) { - bExists = true; - break; - } - } - if (!bExists) { - Type resType = getImplStateType(resourceNode.getResourceHierarchy()); - MethodDeclaration stateGetter = null; - if (pathParams.size() == 0) { - stateGetter = new MethodDeclaration(getterName, resType); - } else { - stateGetter = new MethodDeclaration(getterName, false, resType, pathParams); - } - getters.add(new AbstractMap.SimpleEntry<>(ancestorNode.getResourceHierarchy(), stateGetter)); - } - } - - // Declare the getter accessor in the root resource. - if (resourceNode.getResourceHierarchy().getParent() != null) { - // For a non-root resource - MethodDeclaration getterAccessor = null; - List mainGetterParams = new ArrayList<>(); - String resourcePath = getGetterResourcePathAndPathParams(resourceNode.getPrimaryResourcePath(), mainGetterParams); - if (resourcePath.indexOf('/') > 0) { - // Remove the root resource from the path - resourcePath = resourcePath.substring(resourcePath.indexOf('/')); - } else { - resourcePath = ""; - } - if (mainGetterParams.size() > 0) { - getterAccessor = new MethodDeclaration("get" + getComponentName(resourceNode.getResourceHierarchy()) + "Value", - false, - getImplStateType(resourceNode.getResourceHierarchy()), - mainGetterParams); - } else { - getterAccessor = new MethodDeclaration("get" + getComponentName(resourceNode.getResourceHierarchy()) + "Value", - getImplStateType(resourceNode.getResourceHierarchy())); - } - getterAccessor.setBody(new Block()); - ResourcePath resPath = new ResourcePath(resourceNode.getPrimaryResourcePath()); - for (int i = 0; i < mainGetterParams.size(); i++) { - Parameter pathParam = new Parameter(mainGetterParams.get(i).getName()); - resPath.replacePathParam(i, pathParam, null); - } - Expression getState = JerseyCodeGenerator.pullAccessor.getDirectStateAccessorFor(resPath, resPath.getRoot()); - getterAccessor.getBody().addStatement("return " + getState.toImplementation(new String[] {null}) + ";"); - - getterAccessor.addAnnotation(new Annotation("Produces", "MediaType.APPLICATION_JSON")); - getterAccessor.addAnnotation(new Annotation("GET")); - if (resourcePath.length() > 0) { - getterAccessor.addAnnotation(new Annotation("Path", "\"" + resourcePath + "\"")); - } - getterAccessors.put(resourceNode.getResourceHierarchy(), getterAccessor); - } - - // Declare a client field for push data transfer. - for (Edge resToCh: resourceNode.getOutEdges()) { - DataFlowEdge re = (DataFlowEdge) resToCh; - ChannelNode directDstChNode = (ChannelNode) re.getDestination(); - DataTransferChannel directDstCh = directDstChNode.getChannel(); - // Check if the input resource is outside of the channel scope. - boolean outsideInputResource = false; - for (ChannelMember cm: directDstCh.getInputChannelMembers()) { - if (cm.getResource().equals(resourceNode.getOutSideResource(directDstCh)) && cm.isOutside()) { - outsideInputResource = true; // Regarded as pull transfer. - break; - } - } - // Should take into account the channel hierarchy. - Set ancestorDstChannels = directDstChNode.getAncestors(); - Set descendantDstChannels = directDstChNode.getDescendants(); - Set outEdges = new HashSet<>(); - outEdges.addAll(directDstChNode.getOutEdges()); - for (ChannelNode ancestorDst: ancestorDstChannels) { - outEdges.addAll(ancestorDst.getOutEdges()); - } - for (ChannelNode descendantDst: descendantDstChannels) { - outEdges.addAll(descendantDst.getOutEdges()); - } - for (Edge chToRes: outEdges) { - // For each data transfer to dstNode:ResourceNode. - ResourceNode dstNode = ((ResourceNode) chToRes.getDestination()); - ChannelNode chNode = (ChannelNode) chToRes.getSource(); - DataTransferChannel ch = chNode.getChannel(); - // Check if the output resource is outside of the channel scope. - boolean outsideOutputResource = false; - ChannelMember out = null; - for (ChannelMember cm: ch.getOutputChannelMembers()) { - if (dstNode.getInSideResources().contains(cm.getResource())) { - out = cm; - if (cm.isOutside()) { - outsideOutputResource = true; - break; - } - } - } - ResourcePath dstRes = out.getResource(); - // Also take into account the channel hierarchy to determine push/pull transfer. - if (descendantDstChannels.contains(chNode)) { - outsideOutputResource = true; // Regarded as (broadcasting) push transfer. - } - if (ancestorDstChannels.contains(chNode)) { - outsideInputResource = true; // Regarded as (collecting) pull transfer. - } - if (!bDeclareClientField && ((((PushPullAttribute) re.getAttribute()).getSelectedOption() == PushPullValue.PUSH && !outsideInputResource) || outsideOutputResource)) { - // For push transfer. - if (!generatesComponent(dstRes.getResourceHierarchy())) { - dstRes = dstRes.getParent(); - } - String dstResName = getComponentName(dstRes.getResourceHierarchy()); - if (outsideOutputResource || (resourceNode.getOutSideResource(ch).getCommonPrefix(dstRes) == null && differentTreesAsDifferentServices)) { - // Inter-service - if (!bDeclareClientField) { - // Declare a client field to connect to the destination resource of push transfer. - FieldDeclaration clientField = new FieldDeclaration(typeClient, "client", "ClientBuilder.newClient()"); - if (component != null) { - // A component is created for this resource. - component.addField(clientField); - } else { - // No component is created for this resource. - 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. - FieldDeclaration dstRefField = new FieldDeclaration(new Type(dstResName, dstResName), toVariableName(dstResName)); - if (component != null) { - // A component is created for this resource. - if (resourceNode.getResourceHierarchy() != dstRes.getResourceHierarchy()) { - component.addField(dstRefField); - } - } else { - // No component is created for this resource. - if (resourceNode.getParent().getResourceHierarchy() != dstRes.getResourceHierarchy()) { - fields.add(new AbstractMap.SimpleEntry<>(resourceNode.getParent().getResourceHierarchy(), dstRefField)); - } - } - } - } - } - } - // Declare update methods called by other resources for push data transfer - // and reference fields for pull data transfer. - for (Edge chToRes : resourceNode.getInEdges()) { - ChannelNode directSrcChannel = (ChannelNode) chToRes.getSource(); - DataTransferChannel ch = directSrcChannel.getChannel(); - // Should take into account the channel hierarchy. - Set ancestorSrcChannels = directSrcChannel.getAncestors(); - Set descendantSrcChannels = directSrcChannel.getDescendants(); - Set inEdges = new HashSet<>(); - inEdges.addAll(directSrcChannel.getInEdges()); - for (ChannelNode ancestorSrc: ancestorSrcChannels) { - inEdges.addAll(ancestorSrc.getInEdges()); - } - for (ChannelNode descendantSrc: descendantSrcChannels) { - inEdges.addAll(descendantSrc.getInEdges()); - } - for (Edge resToCh: inEdges) { - // For each data transfer from srcResPath:ResourcePath to resourceNode:ResourceNode. - DataFlowEdge re = (DataFlowEdge) resToCh; - ChannelNode indirectSrcChNode = (ChannelNode) re.getDestination(); - DataTransferChannel indirectSrcCh = indirectSrcChNode.getChannel(); - ResourcePath srcResPath = ((ResourceNode) re.getSource()).getOutSideResource(indirectSrcCh); - // Check if the input resource is outside of the channel scope. - boolean outsideInputResource = false; - for (ChannelMember cm: indirectSrcCh.getInputChannelMembers()) { - if (cm.getResource().equals(srcResPath) && cm.isOutside()) { - outsideInputResource = true; // Regarded as pull transfer. - break; - } - } - // 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())) { - out = cm; - if (cm.isOutside()) { - outsideOutputResource = true; // Regarded as push transfer. - break; - } - } - } - // Also take into account the channel hierarchy to determine push/pull transfer. - if (ancestorSrcChannels.contains(indirectSrcChNode)) { - outsideOutputResource = true; // Regarded as (broadcasting) push transfer. - } - if (descendantSrcChannels.contains(indirectSrcChNode)) { - outsideInputResource = true; // Regarded as (collecting) pull transfer. - } - String srcResName = getComponentName(srcResPath.getResourceHierarchy()); - Type srcType = srcResPath.getResourceStateType(); - if (!generatesComponent(srcResPath.getResourceHierarchy())) { - srcResPath = srcResPath.getParent(); - } - if ((((PushPullAttribute) re.getAttribute()).getSelectedOption() != PushPullValue.PUSH && !outsideOutputResource) || outsideInputResource) { - // For pull transfer. - if (outsideInputResource || (resourceNode.getInSideResource(ch).getCommonPrefix(srcResPath) == null && differentTreesAsDifferentServices)) { - // Inter-service - if (!bDeclareClientField) { - // Declare a client field to connect to the source resource of pull transfer. - FieldDeclaration clientField = new FieldDeclaration(typeClient, "client", "ClientBuilder.newClient()"); - if (component != null) { - // A component is created for this resource. - component.addField(clientField); - } else { - // No component is created for this resource. - 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. - FieldDeclaration srcRefField = new FieldDeclaration(new Type(srcResName, srcResName), toVariableName(srcResName)); - if (component != null) { - // A component is created for this resource. - if (resourceNode.getResourceHierarchy() != srcResPath.getResourceHierarchy()) { - component.addField(srcRefField); - } - } else { - // No component is created for this resource. - if (resourceNode.getParent().getResourceHierarchy() != srcResPath.getResourceHierarchy()) { - fields.add(new AbstractMap.SimpleEntry<>(resourceNode.getParent().getResourceHierarchy(), srcRefField)); - } - } - } - } else { - // For push transfer. - boolean hasRestAPI = false; - boolean isRestAPI = false; - if (outsideOutputResource || (resourceNode.getInSideResource(ch).getCommonPrefix(srcResPath) == 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 params = new ArrayList<>(); - getUpdateResourcePathAndPathParams(out.getResource(), params, isRestAPI); // Path parameters to identify the self resource. - for (Selector selector: ch.getAllSelectors()) { - if (selector.getExpression() instanceof Variable) { - Variable selVar = (Variable) selector.getExpression(); - VariableDeclaration chParam = new VariableDeclaration(selVar.getType(), selVar.getName()); - if (isRestAPI) chParam.addAnnotation(new Annotation("FormParam", "\"" + selVar.getName() + "\"")); - params.add(chParam); // A channel parameter to specify the context of the collaboration. - } - } - String srcName = toVariableName(srcResName); - VariableDeclaration param = new VariableDeclaration(srcType, srcName); - if (isRestAPI) param.addAnnotation(new Annotation("FormParam", "\"" + srcName + "\"")); - 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))) { - 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; - if (component != null) { - // A component is created for this resource. - update = new MethodDeclaration("updateFrom" + srcResName, false, typeVoid, params); - } else { - // No component is created for this resource. - String resourceName = getComponentName(resourceNode.getResourceHierarchy()); - update = new MethodDeclaration("update" + resourceName + "From" + srcResName, false, typeVoid, params); - } - // Determine whether the update method is put or post or delete. - boolean isPut = false; - boolean isDelete = false; - for (ChannelMember cm: ch.getOutputChannelMembers()) { - if (resourceNode.getInSideResources().contains(cm.getResource())) { - if (cm.getStateTransition().isRightUnary()) { - isPut = true; - } else { - isPut = 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; - } - } - } -// HashMap subTerms = ((Term) nextExp).getSubTerms(Term.class); -// for (Term subTerm: subTerms.values()) { -// Symbol rootSymbol = subTerm.getSymbol(); -// if (rootSymbol.equals(DataConstraintModel.delete) || rootSymbol.equals(DataConstraintModel.remove)) { -// isDelete = true; -// break; -// } -// } - } - } - } - } - if (isRestAPI) { - if (isPut) { - update.addAnnotation(new Annotation("PUT")); - } else { - if (!isDelete) { - update.addAnnotation(new Annotation("POST")); - } else { - update.addAnnotation(new Annotation("DELETE")); - } - } - } - // 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. - ResourceHierarchy cacheRes = ((ResourceNode) re.getSource()).getResourceHierarchy(); - FieldDeclaration cacheField = new FieldDeclaration(cacheRes.getResourceStateType(), srcName, getInitializer(cacheRes)); - if (component != null) { - // A component is created for this resource. - component.addField(cacheField); - } else { - // No component is created for this resource. - fields.add(new AbstractMap.SimpleEntry<>(resourceNode.getParent().getResourceHierarchy(), cacheField)); - } - if (inDegree > 1) { - // For each source resource, a child resource is defined in the destination resource so that its state can be updated separately. - if (isRestAPI) update.addAnnotation(new Annotation("Path", "\"/" + srcName + "\"")); - } - } - if (component != null) { - // A component is created for this resource. - component.addMethod(update); - } else { - // No component is created for this resource. - String updateMethodName = update.getName(); - Map nameToMethod = updates.get(resourceNode.getParent().getResourceHierarchy()); - if (nameToMethod == null) { - nameToMethod = new HashMap<>(); - updates.put(resourceNode.getParent().getResourceHierarchy(), nameToMethod); - } - if (nameToMethod.get(updateMethodName) == null) { - nameToMethod.put(updateMethodName, update); - } - } - if (hasRestAPI && !isRestAPI) { - // Declare an update accessor method in the type of root resource. - String updateMethodName = update.getName(); - params = new ArrayList<>(); - String resourcePath = getUpdateResourcePathAndPathParams(out.getResource(), params, true); // Path parameters to identify the self resource. - if (resourcePath.indexOf('/') > 0) { - // Remove the root resource from the path - resourcePath = resourcePath.substring(resourcePath.indexOf('/')); - } else { - resourcePath = ""; - } - for (Selector selector: ch.getAllSelectors()) { - if (selector.getExpression() instanceof Variable) { - Variable selVar = (Variable) selector.getExpression(); - VariableDeclaration chParam = new VariableDeclaration(selVar.getType(), selVar.getName()); - chParam.addAnnotation(new Annotation("FormParam", "\"" + selVar.getName() + "\"")); - params.add(chParam); // A channel parameter to specify the context of the collaboration. - } - } - param = new VariableDeclaration(srcType, srcName); - param.addAnnotation(new Annotation("FormParam", "\"" + srcName + "\"")); - 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))) { - String refName = toVariableName(getComponentName(refRes.getResourceHierarchy())); - param = new VariableDeclaration(refRes.getResourceStateType(), refName); - param.addAnnotation(new Annotation("FormParam", "\"" + refName + "\"")); - params.add(param); - } - } - MethodDeclaration updateAccessor = new MethodDeclaration(updateMethodName, false, typeVoid, params); - if (isPut) { - updateAccessor.addAnnotation(new Annotation("PUT")); - } else { - if (!isDelete) { - updateAccessor.addAnnotation(new Annotation("POST")); - } else { - updateAccessor.addAnnotation(new Annotation("DELETE")); - } - } - 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); - } - } - } - } - } - - // Declare the input method in each resource and the root resource. - 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 cm : ((DataTransferChannel) ch).getOutputChannelMembers()) { - if (resourceNode.getInSideResources().contains(cm.getResource())) { - Expression message = cm.getStateTransition().getMessageExpression(); - if (message instanceof Term) { - // In each resource. - ArrayList resInputParams = new ArrayList<>(); - ArrayList rootInputParams = new ArrayList<>(); - String resourcePath = getInputMethodResourcePathAndPathParams(cm.getResource(), rootInputParams); // Path parameters for the input REST API. - if (resourcePath.indexOf('/') > 0) { - // Remove the root resource from the path - 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. - - // Channel parameters to specify the context of the collaboration. - for (Selector selector: ch.getAllSelectors()) { - if (selector.getExpression() instanceof Variable) { - Variable selVar = (Variable) selector.getExpression(); - VariableDeclaration chParam = new VariableDeclaration(selVar.getType(), selVar.getName()); - resInputParams.add(chParam); - } - } - // Message parameters to carry the data-flows. - for (Map.Entry varEnt: message.getVariables().entrySet()) { - Variable var = varEnt.getValue(); - String refVarName = null; - for (ChannelMember refCm: ((DataTransferChannel) ch).getReferenceChannelMembers()) { - Expression varExp = refCm.getStateTransition().getMessageExpression().getSubTerm(varEnt.getKey()); - if (varExp != null && varExp instanceof Variable) { - if (refCm.getStateTransition().getCurStateExpression().contains(varExp)) { - refVarName = refCm.getResource().getLeafResourceName(); - break; - } - } - } - if (refVarName != null) { - // var has come from a reference resource. - VariableDeclaration param = new VariableDeclaration(var.getType(), refVarName); - resInputParams.add(param); - } else { - // var has not come from reference resource. - String paramName = var.getName(); - VariableDeclaration param = new VariableDeclaration(var.getType(), paramName); - resInputParams.add(param); - if (!resourcePath.contains("{" + paramName+ "}")) { - param = new VariableDeclaration(var.getType(), paramName); - param.addAnnotation(new Annotation("FormParam", "\"" + paramName + "\"")); - rootInputParams.add(param); - } - } - } - - if (resourceNode.getResourceHierarchy().getParent() != null && (component != null || resourceNode.getResourceHierarchy().getParent().getParent() != null)) { - // The case that the input accessor is needed. - String inputMethodName = ((Term) message).getSymbol().getImplName(); - if (((DataTransferChannel) ch).getOutputChannelMembers().size() > 1) { - inputMethodName += "For" + getComponentName(cm.getResource().getResourceHierarchy()); - } - MethodDeclaration input = new MethodDeclaration(inputMethodName, false, typeVoid, resInputParams); - if (component != null) { - // A component is created for this resource. - component.addMethod(input); - } else { - // No component is created for this resource. - Map nameToMethod = inputs.get(resourceNode.getParent().getResourceHierarchy()); - if (nameToMethod == null) { - nameToMethod = new HashMap<>(); - inputs.put(resourceNode.getParent().getResourceHierarchy(), nameToMethod); - } - if (nameToMethod.get(inputMethodName) == null) { - nameToMethod.put(inputMethodName, input); - } - } - } - - // For the root resource. - if (priorMemberForInputChannel.get(ch) ==null || cm == priorMemberForInputChannel.get(ch)) { - // If cm is the receiver of the input event. - priorMemberForInputChannel.put(ch, cm); - String messageSymbol = ((Term) message).getSymbol().getImplName(); - MethodDeclaration inputAccessor = new MethodDeclaration(messageSymbol, false, typeVoid, rootInputParams); - if (cm.getStateTransition().isRightUnary()) { - inputAccessor.addAnnotation(new Annotation("PUT")); - } else { - 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; - } - } - } -// HashMap subTerms = ((Term) nextExp).getSubTerms(Term.class); -// for (Term subTerm: subTerms.values()) { -// Symbol rootSymbol = subTerm.getSymbol(); -// if (rootSymbol.equals(DataConstraintModel.delete) || rootSymbol.equals(DataConstraintModel.remove)) { -// isDelete = true; -// break; -// } -// } - } - if (!isDelete) { - inputAccessor.addAnnotation(new Annotation("POST")); - } else { - inputAccessor.addAnnotation(new Annotation("DELETE")); - } - } - if (resourcePath.length() > 0) { - inputAccessor.addAnnotation(new Annotation("Path", "\"" + resourcePath + "\"")); - } - Map nameToMethod = inputAccessors.get(resourceNode.getResourceHierarchy()); - if (nameToMethod == null) { - nameToMethod = new HashMap<>(); - inputAccessors.put(resourceNode.getResourceHierarchy(), nameToMethod); - } - nameToMethod.put(messageSymbol, inputAccessor); - } - } else if (message instanceof Variable) { - // In each resource. - ArrayList resInputParams = new ArrayList<>(); - int v = 1; - if (cm.getResource().getLastParam() != null) { - Expression pathParam = cm.getResource().getLastParam(); - if (pathParam instanceof Variable) { - Variable var = (Variable) pathParam; - String paramName = var.getName(); - VariableDeclaration param = new VariableDeclaration(var.getType(), paramName); - resInputParams.add(param); - } else if (pathParam instanceof Term) { - Term var = (Term) pathParam; - String paramName = "v" + v; - VariableDeclaration param = new VariableDeclaration(var.getType(), paramName); - resInputParams.add(param); - } - v++; - } - if (cm.getResource().getResourceHierarchy().getParent() != null && cm.getResource().getResourceHierarchy().getParent().getParent() != null) { - String inputMethodName = ((Variable) message).getName(); - if (((DataTransferChannel) ch).getOutputChannelMembers().size() > 1) { - inputMethodName += "For" + getComponentName(cm.getResource().getResourceHierarchy()); - } - MethodDeclaration input = new MethodDeclaration(inputMethodName, false, typeVoid, null); - if (component != null) { - // A component is created for this resource. - component.addMethod(input); - } else { - // No component is created for this resource. - Map nameToMethod = inputs.get(cm.getResource().getParent().getResourceHierarchy()); - if (nameToMethod == null) { - nameToMethod = new HashMap<>(); - inputs.put(cm.getResource().getParent().getResourceHierarchy(), nameToMethod); - } - if (nameToMethod.get(inputMethodName) == null) { - nameToMethod.put(inputMethodName, input); - } - } - } - - // For the root resource. - if (priorMemberForInputChannel.get(ch) ==null || cm == priorMemberForInputChannel.get(ch)) { - // If cm is the receiver of the input event. - priorMemberForInputChannel.put(ch, cm); - ArrayList rootInputParams = new ArrayList<>(); - String resourcePath = getGetterResourcePathAndPathParams(cm.getResource(), rootInputParams); - if (resourcePath.indexOf('/') > 0) { - // Remove the root resource from the path - resourcePath = resourcePath.substring(resourcePath.indexOf('/')); - } else { - resourcePath = ""; - } - String messageSymbol = ((Variable) message).getName(); - MethodDeclaration inputAccessor = new MethodDeclaration(messageSymbol, false, typeVoid, rootInputParams); - if (cm.getStateTransition().isRightUnary()) { - inputAccessor.addAnnotation(new Annotation("PUT")); - } else { - 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; - } - } - } -// HashMap subTerms = ((Term) nextExp).getSubTerms(Term.class); -// for (Term subTerm: subTerms.values()) { -// Symbol rootSymbol = subTerm.getSymbol(); -// if (rootSymbol.equals(DataConstraintModel.delete) || rootSymbol.equals(DataConstraintModel.remove)) { -// isDelete = true; -// break; -// } -// } - } - if (!isDelete) { - inputAccessor.addAnnotation(new Annotation("POST")); - } else { - inputAccessor.addAnnotation(new Annotation("DELETE")); - } - } - if (resourcePath.length() > 0) { - inputAccessor.addAnnotation(new Annotation("Path", "\"" + resourcePath + "\"")); - } - Map nameToMethod = inputAccessors.get(resourceNode.getResourceHierarchy()); - if (nameToMethod == null) { - nameToMethod = new HashMap<>(); - inputAccessors.put(resourceNode.getResourceHierarchy(), nameToMethod); - } - nameToMethod.put(messageSymbol, inputAccessor); - } - } - } - } - } - } - - // Add leaf getter methods to the parent components. - for (Map.Entry entry: getters) { - resourceComponents.get(entry.getKey()).addMethod(entry.getValue()); - } - - // Add leaf update methods to the parent components. - for (Map.Entry> entry: updates.entrySet()) { - for (MethodDeclaration update: entry.getValue().values()) { - resourceComponents.get(entry.getKey()).addMethod(update); - } - } - - // Add leaf input methods to the parent components. - for (Map.Entry> entry: inputs.entrySet()) { - for (MethodDeclaration input: entry.getValue().values()) { - resourceComponents.get(entry.getKey()).addMethod(input); - } - } - - // Add leaf reference fields to the parent components. - for (Map.Entry entry: fields) { - ResourceHierarchy resource = entry.getKey(); - FieldDeclaration field = entry.getValue(); - TypeDeclaration component = resourceComponents.get(resource); - boolean existsField = false; - for (FieldDeclaration fld: component.getFields()) { - if (fld.getName().equals(field.getName())) { - existsField = true; - break; - } - } - if (!existsField) { - component.addField(field); - if (field.getType().equals(typeClient)) { - for (CompilationUnit cu: codes) { - if (cu.types().contains(component)) { - cu.addImport(new ImportDeclaration("jakarta.ws.rs.client.*")); - break; - } - } - } - } - } - - // Add constructor parameters to the ancestor components. - for (ResourceNode root: graph.getRootResourceNodes()) { - addConstructorParameters(root.getResourceHierarchy(), resourceComponents, resourceConstructors, constructorParams); - } - - // Add accessors. - for (ResourceHierarchy rootRes: model.getResourceHierarchies()) { - if (rootRes.getParent() == null) { - // root resource - TypeDeclaration rootComponent = resourceComponents.get(rootRes); - // Add getter accessors. - for (ResourceHierarchy res: getterAccessors.keySet()) { - if (rootRes.isAncestorOf(res)) { - rootComponent.addMethod(getterAccessors.get(res)); - } - } - // Add input accessors. - for (ResourceHierarchy res: inputAccessors.keySet()) { - if (rootRes.isAncestorOf(res)) { - for (MethodDeclaration inputAccessor: inputAccessors.get(res).values()) { - rootComponent.addMethod(inputAccessor); - } - } - } - } - } - - // Declare the Pair class. - boolean isCreatedPair = false; - for(Node n : resources) { - ResourceNode rn = (ResourceNode) n; - if(isCreatedPair) continue; - if(model.getType("Pair").isAncestorOf(rn.getResourceStateType())) { - TypeDeclaration type = new TypeDeclaration("Pair"); - type.addField(new FieldDeclaration(new Type("Double", "T"), "left")); - type.addField(new FieldDeclaration(new Type("Double", "T"), "right")); - - MethodDeclaration constructor = new MethodDeclaration("Pair", true); - constructor.addParameter(new VariableDeclaration(new Type("Double", "T"), "left")); - constructor.addParameter(new VariableDeclaration(new Type("Double", "T"), "right")); - Block block = new Block(); - block.addStatement("this.left = left;"); - block.addStatement("this.right = right;"); - constructor.setBody(block); - type.addMethod(constructor); - - for(FieldDeclaration field : type.getFields()) { - MethodDeclaration getter = new MethodDeclaration( - "get" + field.getName().substring(0,1).toUpperCase() + field.getName().substring(1), - new Type("Double","T")); - getter.setBody(new Block()); - getter.getBody().addStatement("return " + field.getName() + ";"); - type.addMethod(getter); - } - -// MethodDeclaration toStr = new MethodDeclaration("toString", false, DataConstraintModel.typeString, null); -// block = new Block(); -// block.addStatement("return \"{\\\"\" + left + \"\\\":\\\"\" + right + \"\\\"}\";"); -// toStr.setBody(block); -// type.addMethod(toStr); - - CompilationUnit cu = new CompilationUnit(type); - cu.addImport(new ImportDeclaration("java.util.*")); - codes.add(cu); - - isCreatedPair = true; - } - } - - return codes; - } - - private static List addConstructorParameters(ResourceHierarchy resource, - Map resourceComponents, - Map resourceConstructors, - Map> constructorParams) { - List params = new ArrayList<>(); - for (ResourceHierarchy child: resource.getChildren()) { - params.addAll(addConstructorParameters(child, resourceComponents, resourceConstructors, constructorParams)); - } - if (constructorParams.get(resource) != null) { - for (VariableDeclaration param: constructorParams.get(resource).values()) { - params.add(param); - } - } - if (params.size() > 0) { - MethodDeclaration constructor = resourceConstructors.get(resource); - if (constructor == null) { - if (resourceComponents.get(resource) != null) { - String resourceName = getComponentName(resource); - constructor = new MethodDeclaration(resourceName, true); - Block body = new Block(); - constructor.setBody(body); - resourceComponents.get(resource).addMethod(constructor); - resourceConstructors.put(resource, constructor); - } - } - if (constructor != null) { - for (VariableDeclaration param: params) { - constructor.addParameter(param); - constructor.getBody().addStatement("this." + toVariableName(param.getName()) + " = " + toVariableName(param.getName()) + ";"); - } - } - } - if (resource.getNumParameters() > 0) params.clear(); - return params; - } - - private static String getGetterResourcePathAndPathParams(ResourcePath resPath, List pathParams) { - 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 + "\"")); - pathParams.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 + "\"")); - pathParams.add(param); - } - v++; - } - return resPath.getResourceHierarchy().toResourcePath(params); - } - - private static String getUpdateResourcePathAndPathParams(ResourcePath resPath, ArrayList rootParams, boolean isRestAPI) { - 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 = new VariableDeclaration(var.getType(), paramName); - if (isRestAPI) param.addAnnotation(new Annotation("PathParam", "\"" + paramName + "\"")); - rootParams.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 = new VariableDeclaration(var.getType(), paramName); - if (isRestAPI) param.addAnnotation(new Annotation("PathParam", "\"" + paramName + "\"")); - rootParams.add(param); - } - v++; - } - return resPath.getResourceHierarchy().toResourcePath(params); - } - - private static String getInputMethodResourcePathAndPathParams(ResourcePath resPath, ArrayList rootInputParams) { - 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 = new VariableDeclaration(var.getType(), paramName); - param.addAnnotation(new Annotation("PathParam", "\"" + paramName + "\"")); - rootInputParams.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 + "\"")); - 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 = new VariableDeclaration(var.getType(), paramName); - param.addAnnotation(new Annotation("PathParam", "\"" + paramName + "\"")); - rootInputParams.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 + "\"")); - rootInputParams.add(param); - } - v++; - } - } - return resPath.getResourceHierarchy().toResourcePath(params); - } - - private static String getInitializer(ResourceHierarchy res) { - Type stateType = res.getResourceStateType(); - String initializer = null; - if (res.getInitialValue() != null) { - initializer = res.getInitialValue().toImplementation(new String[] {""}); - } else if (stateType != null) { - initializer = DataConstraintModel.getDefaultValue(stateType); - } - return initializer; - } - - static public ArrayList getCodes(ArrayList codeTree) { - ArrayList codes = new ArrayList<>(); - for (TypeDeclaration type : codeTree) { - codes.add("public class " + type.getTypeName() + "{"); - for (FieldDeclaration field : type.getFields()) { - if (type.getTypeName() != mainTypeName) { - String cons = "\t" + "private " + field.getType().getInterfaceTypeName() + " " - + field.getName(); - if (DataConstraintModel.isListType(field.getType())) - cons += " = new " + field.getType().getImplementationTypeName() + "()"; - cons += ";"; - codes.add(cons); - } else { - String cons = "\t" + "private " + field.getType().getInterfaceTypeName() + " " - + field.getName() + " = new " + field.getType().getTypeName() + "("; - cons += ");"; - codes.add(cons); - } - } - codes.add(""); - for (MethodDeclaration method : type.getMethods()) { - String varstr = "\t" + "public " + method.getReturnType().getInterfaceTypeName() + " " - + method.getName() + "("; - if (method.getParameters() != null) { - for (VariableDeclaration var : method.getParameters()) { - varstr += var.getType().getInterfaceTypeName() + " " + var.getName() + ","; - } - if (!method.getParameters().isEmpty()) - varstr = varstr.substring(0, varstr.length() - 1); - } - if (method.getBody() != null) { - for (String str : method.getBody().getStatements()) { - codes.add("\t\t" + str + ";"); - } - } - codes.add(varstr + ")" + "{"); - codes.add("\t" + "}"); - codes.add(""); - } - codes.add("}"); - codes.add(""); - } - return codes; - } - - static public IResourceStateAccessor pushAccessor = new IResourceStateAccessor() { - @Override - public Expression getCurrentStateAccessorFor(ChannelMember target, ChannelMember from) { - ResourcePath targetRes = target.getResource(); - ResourcePath fromRes = from.getResource(); - if (targetRes.equals(fromRes)) { - return new Field("value", - targetRes.getResourceStateType() != null ? targetRes.getResourceStateType() - : DataConstraintModel.typeInt); - } - // use the cached value as the current state - return new Field(toVariableName(getComponentName(targetRes.getResourceHierarchy())), - targetRes.getResourceStateType() != null ? targetRes.getResourceStateType() - : DataConstraintModel.typeInt); - } - - @Override - public Expression getNextStateAccessorFor(ChannelMember target, ChannelMember from) { - ResourcePath targetRes = target.getResource(); - return new Parameter(toVariableName(getComponentName(targetRes.getResourceHierarchy())), - targetRes.getResourceStateType() != null ? targetRes.getResourceStateType() - : DataConstraintModel.typeInt); - } - - @Override - public Expression getDirectStateAccessorFor(ResourcePath targetRes, ResourcePath fromRes) { - if (fromRes != null && targetRes.equals(fromRes)) { - return new Field("value", - targetRes.getResourceStateType() != null ? targetRes.getResourceStateType() - : DataConstraintModel.typeInt); - } - return null; - } - }; - static public IResourceStateAccessor pullAccessor = new IResourceStateAccessor() { - @Override - public Expression getCurrentStateAccessorFor(ChannelMember target, ChannelMember from) { - ResourcePath targetRes = target.getResource(); - if (from != null && !target.isOutside()) { - ResourcePath fromRes = from.getResource(); - if (targetRes.getCommonPrefix(fromRes) != null) { - return getDirectStateAccessorFor(targetRes, fromRes); - } - } - // for reference channel member - return new Parameter(toVariableName(getComponentName(targetRes.getResourceHierarchy())), - targetRes.getResourceStateType() != null ? targetRes.getResourceStateType() - : DataConstraintModel.typeInt); - } - - @Override - public Expression getNextStateAccessorFor(ChannelMember target, ChannelMember from) { - ResourcePath targetRes = target.getResource(); - if (from != null && !target.isOutside()) { - ResourcePath fromRes = from.getResource(); - if (targetRes.getCommonPrefix(fromRes) != null) { - return getDirectStateAccessorFor(targetRes, fromRes); - } - } - // Get the next state through a local variable which is to be initialized by a response of a GET API. - return new Parameter(toVariableName(getComponentName(targetRes.getResourceHierarchy())), - targetRes.getResourceStateType() != null ? targetRes.getResourceStateType() - : DataConstraintModel.typeInt); - } - - @Override - public Expression getDirectStateAccessorFor(ResourcePath targetRes, ResourcePath fromRes) { - if (fromRes != null && !fromRes.getResourceHierarchy().isAncestorOf(targetRes.getResourceHierarchy())) { - if (targetRes.equals(fromRes)) { - return new Field("value", - targetRes.getResourceStateType() != null ? targetRes.getResourceStateType() - : DataConstraintModel.typeInt); - } - // for reference channel member - return new Parameter(toVariableName(getComponentName(targetRes.getResourceHierarchy())), - targetRes.getResourceStateType() != null ? targetRes.getResourceStateType() - : DataConstraintModel.typeInt); - } else { - // (#3) access from an ancestor or outside of the hierarchy (must be kept consistent with #4) - Stack pathStack = new Stack<>(); - ResourcePath curPath = targetRes; - do { - if (fromRes != null && curPath.equals(fromRes)) break; - pathStack.push(curPath); - curPath = curPath.getParent(); - } while (curPath != null); - // iterate from the `from' resource - Term getter = null; - int arity = 2; - boolean doesChainInvocations = true; - while (!pathStack.empty()) { - curPath = pathStack.pop(); - String typeName = getComponentName(curPath.getResourceHierarchy()); - if (getter == null && fromRes == null) { - // root resource - String fieldName = toVariableName(typeName); - getter = new Field(fieldName, new Type(typeName, typeName)); - } else { - if (generatesComponent(curPath.getResourceHierarchy())) { - if (arity == 2) { - Term newGetter = new Term(new Symbol("get" + typeName, -1, Symbol.Type.METHOD)); - newGetter.addChild(getter); - if (curPath.getResourceHierarchy().getNumParameters() > 0) { - Expression param = curPath.getLastParam(); - if (param != null) { - newGetter.addChild(param); - newGetter.getSymbol().setArity(2); - } - } - getter = newGetter; - } else { - // add the last path parameter. - if (curPath.getResourceHierarchy().getNumParameters() > 0) { - Expression param = curPath.getLastParam(); - if (param != null) { - getter.getSymbol().setArity(arity); - getter.addChild(param); - } - } - } - arity = 2; - doesChainInvocations = true; - } else { - // to get a descendant resource directly. (e.g, .todos.{year}.{month}.{day}.{id} ==> .getTodos().getTodo(year, month, day, id)) - if (doesChainInvocations) { - Term newGetter = new Term(new Symbol("get" + typeName, -1, Symbol.Type.METHOD)); - newGetter.addChild(getter); - getter = newGetter; - doesChainInvocations = false; - } - if (curPath.getResourceHierarchy().getNumParameters() > 0) { - // may change the symbol name - getter.getSymbol().changeName("get" + typeName); - // add a path parameter. - Expression param = curPath.getLastParam(); - if (param != null) { - getter.getSymbol().setArity(arity); - getter.addChild(param); - arity++; - } - } - } - } - } - - if (generatesComponent(targetRes.getResourceHierarchy())) { - Term newGetter = new Term(new Symbol("getValue", 1, Symbol.Type.METHOD)); - newGetter.addChild(getter); - getter = newGetter; - } - return getter; - } - } - }; - static public IResourceStateAccessor refAccessor = new IResourceStateAccessor() { - @Override - public Expression getCurrentStateAccessorFor(ChannelMember target, ChannelMember from) { - ResourcePath targetRes = target.getResource(); - ResourcePath fromRes = from.getResource(); - if (targetRes.equals(fromRes)) { - return new Field("value", - targetRes.getResourceStateType() != null ? targetRes.getResourceStateType() - : DataConstraintModel.typeInt); - } - // for reference channel member - return new Parameter(toVariableName(getComponentName(targetRes.getResourceHierarchy())), - targetRes.getResourceStateType() != null ? targetRes.getResourceStateType() - : DataConstraintModel.typeInt); - } - - @Override - public Expression getNextStateAccessorFor(ChannelMember target, ChannelMember from) { - ResourcePath targetRes = target.getResource(); - return new Parameter(toVariableName(getComponentName(targetRes.getResourceHierarchy())), - targetRes.getResourceStateType() != null ? targetRes.getResourceStateType() - : DataConstraintModel.typeInt); - } - - @Override - public Expression getDirectStateAccessorFor(ResourcePath targetRes, ResourcePath fromRes) { - if (fromRes != null && targetRes.equals(fromRes)) { - return new Field("value", - targetRes.getResourceStateType() != null ? targetRes.getResourceStateType() - : DataConstraintModel.typeInt); - } - return null; - } - }; -} diff --git a/AlgebraicDataflowArchitectureModel/src/generators/JerseyMethodBodyGenerator.java b/AlgebraicDataflowArchitectureModel/src/generators/JerseyMethodBodyGenerator.java deleted file mode 100644 index afea683..0000000 --- a/AlgebraicDataflowArchitectureModel/src/generators/JerseyMethodBodyGenerator.java +++ /dev/null @@ -1,1739 +0,0 @@ -package generators; - -import java.util.AbstractMap; -import java.util.ArrayList; -import java.util.HashMap; -import java.util.HashSet; -import java.util.Iterator; -import java.util.List; -import java.util.Map; -import java.util.Map.Entry; -import java.util.Set; -import java.util.Stack; - -import code.ast.CodeUtil; -import code.ast.CompilationUnit; -import code.ast.MethodDeclaration; -import code.ast.TypeDeclaration; -import code.ast.VariableDeclaration; -import models.Edge; -import models.Node; -import models.algebra.Constant; -import models.algebra.Expression; -import models.algebra.Field; -import models.algebra.InvalidMessage; -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; -import models.algebra.ValueUndefined; -import models.algebra.Variable; -import models.dataConstraintModel.Channel; -import models.dataConstraintModel.ChannelMember; -import models.dataConstraintModel.DataConstraintModel; -import models.dataConstraintModel.JsonAccessor; -import models.dataConstraintModel.JsonTerm; -import models.dataConstraintModel.ResourceHierarchy; -import models.dataConstraintModel.ResourcePath; -import models.dataConstraintModel.Selector; -import models.dataFlowModel.DataTransferModel; -import models.dataFlowModel.DataTransferChannel; -import models.dataFlowModel.PushPullAttribute; -import models.dataFlowModel.PushPullValue; -import models.dataFlowModel.ResolvingMultipleDefinitionIsFutureWork; -import models.dataFlowModel.ChannelNode; -import models.dataFlowModel.DataFlowEdge; -import models.dataFlowModel.DataFlowGraph; -import models.dataFlowModel.ResourceNode; -import models.dataFlowModel.StoreAttribute; -import models.dataFlowModel.DataTransferChannel.IResourceStateAccessor; - -public class JerseyMethodBodyGenerator { - private static String baseURL = "http://localhost:8080"; - - public static ArrayList doGenerate(DataFlowGraph graph, DataTransferModel model, ArrayList codes) { - // Create a map from type names (lower case) to their types. - Map componentMap = new HashMap<>(); - for (CompilationUnit code: codes) { - for (TypeDeclaration component: code.types()) { - componentMap.put(component.getTypeName(), component); - } - } - - // Generate the body of each update or getter method. - try { - Set chainedCalls = new HashSet<>(); - Map> referredResources = new HashMap<>(); - for (Edge e: graph.getEdges()) { - DataFlowEdge resToCh = (DataFlowEdge) e; - if (!resToCh.isChannelToResource()) { - PushPullAttribute pushPull = (PushPullAttribute) resToCh.getAttribute(); - ResourceNode src = (ResourceNode) resToCh.getSource(); - ChannelNode directDstChNode = (ChannelNode) resToCh.getDestination(); - DataTransferChannel directDstCh = directDstChNode.getChannel(); - // Should take into account the channel hierarchy. - Set ancestorDstChannels = directDstChNode.getAncestors(); - Set descendantDstChannels = directDstChNode.getDescendants(); - Set outEdges = new HashSet<>(); - outEdges.addAll(directDstChNode.getOutEdges()); - for (ChannelNode ancestorDst: ancestorDstChannels) { - outEdges.addAll(ancestorDst.getOutEdges()); - } - for (ChannelNode descendantDst: descendantDstChannels) { - outEdges.addAll(descendantDst.getOutEdges()); - } - for (Edge chToRes: outEdges) { - // For each data transfer from src:ResourceNode to dst:ResourceNode. - ResourceNode dst = (ResourceNode) chToRes.getDestination(); - String srcResourceName = JerseyCodeGenerator.getComponentName(src.getResourceHierarchy()); - String dstResourceName = JerseyCodeGenerator.getComponentName(dst.getResourceHierarchy()); - TypeDeclaration srcComponent = componentMap.get(srcResourceName); - TypeDeclaration dstComponent = componentMap.get(dstResourceName); -// DataTransferChannel ch = ((ChannelNode) resToCh.getDestination()).getChannel(); - ChannelNode chNode = (ChannelNode) chToRes.getSource(); - DataTransferChannel ch = chNode.getChannel(); - for (ChannelMember out: ch.getOutputChannelMembers()) { - 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: directDstCh.getInputChannelMembers()) { - if (src.getOutSideResources().contains(cm.getResource())) { - 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 = out.isOutside(); - // Also take into account the channel hierarchy to determine push/pull transfer. - if (descendantDstChannels.contains(chNode)) { - outsideOutputResource = true; // Regarded as (broadcasting) push transfer. - } - if (ancestorDstChannels.contains(chNode)) { - outsideInputResource = true; // Regarded as (collecting) pull transfer. - } - if ((pushPull.getSelectedOption() == PushPullValue.PUSH && !outsideInputResource) || outsideOutputResource) { - // for push data transfer - MethodDeclaration update = null; - if (dstComponent == null) { - String dstParentResourceName = JerseyCodeGenerator.getComponentName(dst.getResourceHierarchy().getParent()); - dstComponent = componentMap.get(dstParentResourceName); - update = getUpdateMethod(dstComponent, dstResourceName, srcResourceName); - } else { - update = getUpdateMethod(dstComponent, null, srcResourceName); - } - if (((StoreAttribute) dst.getAttribute()).isStored()) { - // update stored state of dst side resource (when every incoming edge is in push style) - Term unifiedMassage = null; - if (directDstCh != ch) { - unifiedMassage = directDstCh.fillOutsideResourcePaths(out, JerseyCodeGenerator.pushAccessor, null).getValue(); - } - Expression updateExp = null; - if (ch.getReferenceChannelMembers().size() == 0) { - Term message = ch.fillOutsideResourcePaths(out, JerseyCodeGenerator.pushAccessor, null).getValue(); - if (unifiedMassage == null) { - unifiedMassage = message; - } else { - unifiedMassage = (Term) unifiedMassage.unify(message); - } - updateExp = ch.deriveUpdateExpressionOf(out, unifiedMassage, JerseyCodeGenerator.pushAccessor); - } else { - // if there exists one or more reference channel member. - HashMap inputResourceToStateAccessor = new HashMap<>(); - for (ChannelMember c: ch.getInputChannelMembers()) { - inputResourceToStateAccessor.put(c, JerseyCodeGenerator.pushAccessor); - } - for (ChannelMember c: ch.getReferenceChannelMembers()) { - inputResourceToStateAccessor.put(c, JerseyCodeGenerator.refAccessor); - } - Term message = ch.fillOutsideResourcePaths(out, JerseyCodeGenerator.pushAccessor, inputResourceToStateAccessor).getValue(); - if (unifiedMassage == null) { - unifiedMassage = message; - } else { - unifiedMassage = (Term) unifiedMassage.unify(message); - } - updateExp = ch.deriveUpdateExpressionOf(out, unifiedMassage, JerseyCodeGenerator.pushAccessor); - } - // Replace Json constructor with a constructor of a descendant resource. - ResourceHierarchy outRes = out.getResource().getResourceHierarchy(); - if (outRes.getChildren().size() == 1 && outRes.getChildren().iterator().next().getNumParameters() > 0) { - ResourceHierarchy descendantRes = outRes.getChildren().iterator().next(); - Set children; - do { - if (JerseyCodeGenerator.generatesComponent(descendantRes)) break; - children = descendantRes.getChildren(); - } while (children != null && children.size() == 1 && (descendantRes = children.iterator().next()) != null); - Type descendantStateType = descendantRes.getResourceStateType(); - String descendantComponentName = JerseyCodeGenerator.getComponentName(descendantRes); - TypeDeclaration descendantComponent = componentMap.get(descendantComponentName); - if (DataConstraintModel.typeJson.isAncestorOf(descendantStateType)) { - replaceJsonTermWithConstructorInvocation(updateExp, descendantStateType, descendantComponentName, descendantComponent); - } - } - // Replace the type of the state field. - Type fieldType = JerseyCodeGenerator.getImplStateType(outRes); - if (updateExp instanceof Term) { - ((Term) updateExp).setType(fieldType); - for (Map.Entry varEnt: ((Term) updateExp).getVariables().entrySet()) { - if (varEnt.getValue().getName().equals("value")) { - varEnt.getValue().setType(fieldType); - } - } - } else if (updateExp instanceof Variable) { - ((Variable) updateExp).setType(fieldType); - } - // 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 (JerseyCodeGenerator.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] + "this.value = " + newState + ";"; - } - } else { - if (sideEffects[0] != null) { - updateStatement = sideEffects[0]; - updateStatement = updateStatement.replace(".value", "." + JerseyCodeGenerator.toVariableName(JerseyCodeGenerator.getComponentName(outRes))); - if (updateStatement.endsWith("\n")) { - updateStatement = updateStatement.substring(0, updateStatement.length() - 1); - } - } - if (DataConstraintModel.typeList.isAncestorOf(outRes.getParent().getResourceStateType())) { - Term selector = new Term(DataConstraintModel.set); - selector.addChild(new Field("value")); - 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(outRes.getParent().getResourceStateType())) { - Term selector = new Term(DataConstraintModel.insert); - selector.addChild(new Field("value")); - 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())) { - updateStatement += "this." + JerseyCodeGenerator.toVariableName(JerseyCodeGenerator.getComponentName(outRes)) + " = " + newState + ";"; - } - } - // add an update statement of the state of dst side resource. - if (numOfOutResourcesWithTheSameHierarchy == 1) { - update.addFirstStatement(updateStatement); - } else { - Term conditions = null; - int v = 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(v - 1); - } - Term condition = new Term(DataConstraintModel.eq, new Expression[] { - new Parameter("self" + (v > 1 ? v : ""), DataConstraintModel.typeString), - arg}); - if (conditions == null) { - conditions = condition; - } else { - conditions = new Term(DataConstraintModel.and, new Expression[] { - conditions, - condition}); - } - } - v++; - } - String ifStatement = "if (" + conditions.toImplementation(new String[] {""})+ ") {\n"; - update.addFirstStatement(ifStatement + "\t" + updateStatement.replace("\n", "\n\t") + "\n}"); - } - } - // Calculate in-degree (PUSH transfer) of the destination resource. - int inDegree = 0; - Set inEdges = new HashSet<>(); - inEdges.addAll(chNode.getInEdges()); - for (ChannelNode ancestor: chNode.getAncestors()) { - inEdges.addAll(ancestor.getInEdges()); - } - for (ChannelNode descendant: chNode.getDescendants()) { - inEdges.addAll(descendant.getInEdges()); - } - for (Edge resToCh2: inEdges) { - DataFlowEdge df =(DataFlowEdge) resToCh2; - if (((PushPullAttribute) df.getAttribute()).getSelectedOption() == PushPullValue.PUSH) { - inDegree++; - } - } - if (inDegree > 1 - || (inDegree == 1 && directDstCh.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); - } - } - // 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. - ResourcePath outResPath = new ResourcePath(out.getResource()); - for (int i = 0; i < outResPath.getPathParams().size(); i++) { - Parameter pathParam = new Parameter(update.getParameters().get(i).getName()); - outResPath.replacePathParam(i, pathParam, null); - } - Expression resExp = JerseyCodeGenerator.pullAccessor.getDirectStateAccessorFor(outResPath, outResPath.getRoot()); - String args = ""; - String delimiter = ""; - if (resExp instanceof Term) { - // To access the parent resource if the leaf resource is primitive and cannot declare the update method, or to remove getValue(). - 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); - } - int v = 0; - for (VariableDeclaration var: update2.getParameters()) { - if (v < out.getResource().getPathParams().size()) { - if (out.getResource().getPathParams().get(v) instanceof Variable) { - args += delimiter + ((Variable) out.getResource().getPathParams().get(v)).getName(); - } else if (out.getResource().getPathParams().get(v) instanceof Term) { - args += delimiter + "v" + (v + 1); - } - } else { - args += delimiter + var.getName(); - } - delimiter = ", "; - v++; - } - if (resExp != null) { - String resourceAccess = resExp.toImplementation(new String[] {""}); - update.addStatement(resourceAccess + "." + update2.getName() + "(" + args + ");"); - } else { - update.addStatement(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() == null || !update.getBody().getStatements().contains(paramConverter))) { - update.addFirstStatement(paramConverter); - } - } - } - if (((StoreAttribute) dst.getAttribute()).isStored()) { - // returns the state stored in a field. - MethodDeclaration getter = null; - if (JerseyCodeGenerator.generatesComponent(dst.getResourceHierarchy())) { - getter = getMethod(dstComponent, "getValue"); - } else { - getter = getGetterMethod(dstComponent, dstResourceName); - } - if (getter.getBody() == null || getter.getBody().getStatements().size() == 0) { - if (dst.getResourceHierarchy().getNumParameters() == 0) { - if (JerseyCodeGenerator.generatesComponent(dst.getResourceHierarchy())) { - // dst has a component. - getter.addStatement("return value;"); - } else { - // dst has no component. - String dstResName = JerseyCodeGenerator.toVariableName(JerseyCodeGenerator.getComponentName(dst.getResourceHierarchy())); - getter.addStatement("return " + dstResName + ";"); - } - } else { - String[] sideEffects = new String[] {""}; - if (DataConstraintModel.typeList.isAncestorOf(dst.getParent().getResourceStateType())) { - Term selector = new Term(DataConstraintModel.get); - selector.addChild(new Field("value")); - selector.addChild(dst.getSelectors().get(dst.getSelectors().size() - 1).getExpression()); - String curState = selector.toImplementation(sideEffects); - getter.addStatement(sideEffects[0] + "return " + curState + ";"); - } else if (DataConstraintModel.typeMap.isAncestorOf(dst.getParent().getResourceStateType())) { - Term selector = new Term(DataConstraintModel.lookup); - selector.addChild(new Field("value")); - selector.addChild(dst.getSelectors().get(dst.getSelectors().size() - 1).getExpression()); - String curState = selector.toImplementation(sideEffects); - getter.addStatement(sideEffects[0] + "return " + curState + ";"); - } - } - } - } - // src side (for a chain of update method invocations) - String httpMethod = null; - if (out.getStateTransition().isRightUnary()) { - httpMethod = "put"; - } else { - httpMethod = "post"; - } - String srcName = null; - if (srcComponent == null) { - String srcParentResourceName = JerseyCodeGenerator.getComponentName(src.getResourceHierarchy().getParent()); - srcComponent = componentMap.get(srcParentResourceName); - srcName = srcResourceName; - } - // For caller update methods - for (MethodDeclaration srcUpdate: getUpdateMethods(srcComponent, srcName)) { - if (srcUpdate != null) { - List>> params = new ArrayList<>(); - ResourcePath dstRes = out.getResource(); - // Values of channel parameters. - for (Selector selector: ch.getAllSelectors()) { - if (selector.getExpression() instanceof Variable) { - Variable selVar = (Variable) selector.getExpression(); - params.add(new AbstractMap.SimpleEntry<>(selVar.getType(), - new AbstractMap.SimpleEntry<>(selVar.getName(), selVar.getName()))); - } - } - // Value of the source side (input side) resource. - String srcFieldName = "this.value"; - if (!JerseyCodeGenerator.generatesComponent(src.getResourceHierarchy())) { - srcFieldName = JerseyCodeGenerator.toVariableName(srcResourceName); - } - params.add(new AbstractMap.SimpleEntry<>(src.getResourceStateType(), - new AbstractMap.SimpleEntry<>(JerseyCodeGenerator.toVariableName(srcResourceName), srcFieldName))); - // Get the value of reference member to call the update method. - Set referredSet = referredResources.get(srcUpdate); - if (ch.getReferenceChannelMembers().size() > 0) { - for (ChannelMember rc: ch.getReferenceChannelMembers()) { - // For each reference channel member, get the current state of the reference side resource by pull data transfer. - ResourcePath ref = rc.getResource(); - if (referredSet == null) { - referredSet = new HashSet<>(); - referredResources.put(srcUpdate, referredSet); - } - if (!dst.getInSideResources().contains(ref)) { - String refResourceName = JerseyCodeGenerator.toVariableName(JerseyCodeGenerator.getComponentName(ref.getResourceHierarchy())); - Type refResourceType = ref.getResourceStateType(); - if (!referredSet.contains(ref)) { - referredSet.add(ref); - String[] sideEffects = new String[] {""}; - ResourcePath srcRes = in.getResource(); - if (!JerseyCodeGenerator.generatesComponent(srcRes.getResourceHierarchy())) { - srcRes = srcRes.getParent(); - } - if (rc.isOutside() || (ref.getCommonPrefix(srcRes) == null && JerseyCodeGenerator.differentTreesAsDifferentServices)) { - List pathParams = new ArrayList<>(); - for (Expression pathExp: ref.getPathParams()) { - pathParams.add("\" + " + pathExp.toImplementation(sideEffects) + " + \""); - } - generatePullDataTransfer(srcUpdate, refResourceName, ref.getResourceHierarchy().toResourcePath(pathParams), refResourceType); - } else { - 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 (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; - } - Map>> filledPaths = ch.fillOutsideResourcePaths(out, JerseyCodeGenerator.pushAccessor); - String dstPath = null; - if (filledPaths != null && filledPaths.get(out) != null) { - ResourcePath filledDstPath = filledPaths.get(out).getKey(); - dstPath = filledDstPath.toResourcePath().replaceAll(":.*\\}","\\}").replaceAll("\\{", "\"+").replaceAll("\\}", "+\""); - } else { - dstPath = dstRes.getResourceHierarchy().toResourcePath(pathParams); - } - // Call the update method. - 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, dstPath, srcResName, httpMethod)); - srcUpdate.addThrow("JsonProcessingException"); - 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, dstPath, srcResName, httpMethod)); - srcUpdate.addThrow("JsonProcessingException"); - } - if (descendantDstChannels.contains(chNode)) { - // For hierarchical channels (broadcasting push transfer). - if (ch.getSelectors() != null && ch.getSelectors().size() > 0) { - Expression selExp = ch.getSelectors().get(0).getExpression(); - Type selType = null; - String varName = null; - if (selExp instanceof Variable) { - selType = ((Variable) selExp).getType(); - varName = ((Variable) selExp).getName(); - ChannelMember insideChMem = null; - for (ChannelMember cm :ch.getInputChannelMembers()) { - if (!cm.isOutside()) { - insideChMem = cm; - break; - } - } - if (insideChMem == null) { - for (ChannelMember cm :ch.getReferenceChannelMembers()) { - if (!cm.isOutside()) { - insideChMem = cm; - break; - } - } - } - if (insideChMem == null) { - for (ChannelMember cm :ch.getOutputChannelMembers()) { - if (!cm.isOutside()) { - insideChMem = cm; - break; - } - } - } - ResourcePath insideResPath = insideChMem.getResource(); - while (insideResPath.getParent() != null && (insideResPath.getLastParam() == null || !insideResPath.getLastParam().equals(selExp))) { - insideResPath = insideResPath.getParent(); - } - insideResPath = insideResPath.getParent(); - String parent = null; - if (JerseyCodeGenerator.generatesComponent(insideResPath.getResourceHierarchy())) { - Expression getter = JerseyCodeGenerator.pullAccessor.getDirectStateAccessorFor(insideResPath, src.getPrimaryResourcePath()); - Term valueGetter = new Term(new Symbol("getValue", 1, Symbol.Type.METHOD)); - valueGetter.addChild(getter); - parent = valueGetter.toImplementation(new String[] {""}); - } else { - parent = JerseyCodeGenerator.pullAccessor.getDirectStateAccessorFor(insideResPath, src.getPrimaryResourcePath()).toImplementation(new String[] {""}); - } - if (insideResPath != null) { - if (selType.equals(DataConstraintModel.typeInt)) { - // make a for loop (for a list) for broadcasting. - srcUpdate.addFirstStatement("for (int " + varName + " = 0; " + varName +" < " + parent + ".size(); " + varName + "++) {"); - srcUpdate.addStatement("}"); - } else if (selType.equals(DataConstraintModel.typeString)) { - // make a for loop (for a map) for broadcasting. - srcUpdate.addFirstStatement("for (String " + varName + ": " + parent + ".keySet()) {"); - srcUpdate.addStatement("}"); - } - } - } else if (selExp instanceof Term) { - // not supported. - } - } - } - srcUpdate.addThrow("JsonProcessingException"); - } else { - // Intra-service - String updateMethodName = null; - if (JerseyCodeGenerator.generatesComponent(dst.getResourceHierarchy())) { - updateMethodName = "updateFrom" + srcResourceName; - } else { - updateMethodName = "update" + dstResourceName + "From" + srcResourceName; - } - String callParams = ""; - String delimiter = ""; - // Values of path parameters. - for (Expression pathParam: dstRes.getPathParams()) { - if (pathParam instanceof Variable) { - Variable pathVar = (Variable) pathParam; - callParams += delimiter + pathVar.getName(); - delimiter = ", "; - } - } - // Values of other parameters. - for (Map.Entry> paramEnt: params) { - callParams += delimiter + paramEnt.getValue().getValue(); - delimiter = ", "; - } - // Call the update method. - if (srcComponent != dstComponent) { - srcUpdate.addStatement("this." + JerseyCodeGenerator.toVariableName(dstResourceName) + "." + updateMethodName + "(" + callParams + ");"); - } else { - srcUpdate.addStatement("this." + updateMethodName + "(" + callParams + ");"); - } - if (update != null && update.getThrows() != null && update.getThrows().getExceptions().contains("JsonProcessingException")) { - srcUpdate.addThrow("JsonProcessingException"); - } - } - } - } - // For caller input methods - for (MethodDeclaration srcInput: getInputMethods(srcComponent, src, model)) { - List>> params = new ArrayList<>(); - ResourcePath dstRes = out.getResource(); - // Values of channel parameters. - for (Selector selector: ch.getAllSelectors()) { - if (selector.getExpression() instanceof Variable) { - Variable selVar = (Variable) selector.getExpression(); - params.add(new AbstractMap.SimpleEntry<>(selVar.getType(), - new AbstractMap.SimpleEntry<>(selVar.getName(), selVar.getName()))); - } - } - // Value of the source side (input side) resource. - String srcFieldName = "this.value"; - if (!JerseyCodeGenerator.generatesComponent(src.getResourceHierarchy())) { - srcFieldName = JerseyCodeGenerator.toVariableName(srcResourceName); - } - params.add(new AbstractMap.SimpleEntry<>(src.getResourceStateType(), - new AbstractMap.SimpleEntry<>(JerseyCodeGenerator.toVariableName(srcResourceName), srcFieldName))); - // Get the value of reference member to call the update method. - Set referredSet = referredResources.get(srcInput); - for (ChannelMember rc: ch.getReferenceChannelMembers()) { - // For each reference channel member, get the current state of the reference side resource by pull data transfer. - ResourcePath ref = rc.getResource(); - if (referredSet == null) { - referredSet = new HashSet<>(); - referredResources.put(srcInput, referredSet); - } - if (!dst.getInSideResources().contains(ref)) { - String refResourceName = JerseyCodeGenerator.toVariableName(JerseyCodeGenerator.getComponentName(ref.getResourceHierarchy())); - Type refResourceType = ref.getResourceStateType(); - if (!referredSet.contains(ref)) { - referredSet.add(ref); - String[] sideEffects = new String[] {""}; - ResourcePath srcRes = in.getResource(); - if (!JerseyCodeGenerator.generatesComponent(srcRes.getResourceHierarchy())) { - srcRes = srcRes.getParent(); - } - if (rc.isOutside() || (ref.getCommonPrefix(srcRes) == null && JerseyCodeGenerator.differentTreesAsDifferentServices)) { - List pathParams = new ArrayList<>(); - for (Expression pathExp: ref.getPathParams()) { - pathParams.add("\" + " + pathExp.toImplementation(sideEffects) + " + \""); - } - generatePullDataTransfer(srcInput, refResourceName, ref.getResourceHierarchy().toResourcePath(pathParams), refResourceType); - } else { - Expression refGetter = JerseyCodeGenerator.pullAccessor.getDirectStateAccessorFor(ref, srcRes); - String refExp = refGetter.toImplementation(sideEffects); - String refTypeName = ref.getResourceStateType().getInterfaceTypeName(); - srcInput.addFirstStatement(sideEffects[0] + refTypeName + " " + refResourceName + " = " + refExp + ";"); - } - } - // Value of a reference side resource. - params.add(new AbstractMap.SimpleEntry<>(refResourceType, new AbstractMap.SimpleEntry<>(refResourceName, refResourceName))); - } - } - 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; - } - Map>> filledPaths = ch.fillOutsideResourcePaths(out, JerseyCodeGenerator.pushAccessor); - String dstPath = null; - if (filledPaths != null && filledPaths.get(out) != null) { - ResourcePath filledDstPath = filledPaths.get(out).getKey(); - dstPath = filledDstPath.toResourcePath().replaceAll(":.*\\}","\\}").replaceAll("\\{", "\"+").replaceAll("\\}", "+\""); - } else { - dstPath = dstRes.getResourceHierarchy().toResourcePath(pathParams); - } - // Call the update method. - 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, dstPath, srcResName, httpMethod)); - srcInput.addThrow("JsonProcessingException"); - 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, dstPath, srcResName, httpMethod)); - srcInput.addThrow("JsonProcessingException"); - } - if (descendantDstChannels.contains(chNode)) { - // For hierarchical channels (broadcasting push transfer). - if (ch.getSelectors() != null && ch.getSelectors().size() > 0) { - Expression selExp = ch.getSelectors().get(0).getExpression(); - Type selType = null; - String forVarName = null; - if (selExp instanceof Variable) { - selType = ((Variable) selExp).getType(); - forVarName = ((Variable) selExp).getName(); - ChannelMember insideChMem = null; - for (ChannelMember cm :ch.getInputChannelMembers()) { - if (!cm.isOutside()) { - insideChMem = cm; - break; - } - } - if (insideChMem == null) { - for (ChannelMember cm :ch.getReferenceChannelMembers()) { - if (!cm.isOutside()) { - insideChMem = cm; - break; - } - } - } - if (insideChMem == null) { - for (ChannelMember cm :ch.getOutputChannelMembers()) { - if (!cm.isOutside()) { - insideChMem = cm; - break; - } - } - } - ResourcePath insideResPath = insideChMem.getResource(); - while (insideResPath.getParent() != null && (insideResPath.getLastParam() == null || !insideResPath.getLastParam().equals(selExp))) { - insideResPath = insideResPath.getParent(); - } - insideResPath = insideResPath.getParent(); - String parent = null; - if (JerseyCodeGenerator.generatesComponent(insideResPath.getResourceHierarchy())) { - Expression getter = JerseyCodeGenerator.pullAccessor.getDirectStateAccessorFor(insideResPath, src.getPrimaryResourcePath()); - Term valueGetter = new Term(new Symbol("getValue", 1, Symbol.Type.METHOD)); - valueGetter.addChild(getter); - parent = valueGetter.toImplementation(new String[] {""}); - } else { - parent = JerseyCodeGenerator.pullAccessor.getDirectStateAccessorFor(insideResPath, src.getPrimaryResourcePath()).toImplementation(new String[] {""}); - } - if (insideResPath != null) { - if (selType.equals(DataConstraintModel.typeInt)) { - // make a for loop (for a list) for broadcasting. - srcInput.addFirstStatement("for (int " + forVarName + " = 0; " + forVarName +" < " + parent + ".size(); " + forVarName + "++) {"); - srcInput.addStatement("}"); - } else if (selType.equals(DataConstraintModel.typeString)) { - // make a for loop (for a map) for broadcasting. - srcInput.addFirstStatement("for (String " + forVarName + ": " + parent + ".keySet()) {"); - srcInput.addStatement("}"); - } - } - } else if (selExp instanceof Term) { - // not supported. - } - } - } - srcInput.addThrow("JsonProcessingException"); - } else { - // Intra-service - String updateMethodName = null; - if (JerseyCodeGenerator.generatesComponent(dst.getResourceHierarchy())) { - updateMethodName = "updateFrom" + srcResourceName; - } else { - updateMethodName = "update" + dstResourceName + "From" + srcResourceName; - } - String callParams = ""; - String delimiter = ""; - // Values of path parameters. - for (Expression pathParam: dstRes.getPathParams()) { - if (pathParam instanceof Variable) { - Variable pathVar = (Variable) pathParam; - callParams += delimiter + pathVar.getName(); - delimiter = ", "; - } - } - // Values of other parameters. - for (Map.Entry> paramEnt: params) { - callParams += delimiter + paramEnt.getValue().getValue(); - delimiter = ", "; - } - // Call the update method. - if (srcComponent != dstComponent) { - srcInput.addStatement("this." + JerseyCodeGenerator.toVariableName(dstResourceName) + "." + updateMethodName + "(" + callParams + ");"); - } else { - srcInput.addStatement("this." + updateMethodName + "(" + callParams + ");"); - } - if (update != null && update.getThrows() != null && update.getThrows().getExceptions().contains("JsonProcessingException")) { - srcInput.addThrow("JsonProcessingException"); - } - } - } - } else if ((pushPull.getSelectedOption() != PushPullValue.PUSH && !outsideOutputResource) || outsideInputResource) { - // for pull (or push/pull) data transfer - if (dstComponent == null) { - String dstParentResourceName = JerseyCodeGenerator.getComponentName(dst.getResourceHierarchy().getParent()); - dstComponent = componentMap.get(dstParentResourceName); - } - MethodDeclaration getter = null; - if (JerseyCodeGenerator.generatesComponent(dst.getResourceHierarchy())) { - getter = getMethod(dstComponent, "getValue"); - } else { - getter = getGetterMethod(dstComponent, dstResourceName); - } - if (getter.getBody() == null || getter.getBody().getStatements().size() == 0) { - // The first time to fill the getter method's body. - - // Data transfer on the same channel hierarchy. - String[] sideEffects = new String[] {""}; - // For each reference channel member, get the current state of the reference side resource by pull data transfer. - for (ChannelMember rc: ch.getReferenceChannelMembers()) { - ResourcePath refRes = rc.getResource(); - String refResourceName = JerseyCodeGenerator.toVariableName(JerseyCodeGenerator.getComponentName(refRes.getResourceHierarchy())); - Type refResourceType = refRes.getResourceStateType(); - ResourcePath dstRes = out.getResource(); - if (!JerseyCodeGenerator.generatesComponent(dstRes.getResourceHierarchy())) { - dstRes = dstRes.getParent(); - } - if (rc.isOutside() || (refRes.getCommonPrefix(dstRes) == null && JerseyCodeGenerator.differentTreesAsDifferentServices)) { - List pathParams = new ArrayList<>(); - for (Expression pathExp: refRes.getPathParams()) { - sideEffects = new String[] {""}; - pathParams.add("\" + " + pathExp.toImplementation(sideEffects) + " + \""); - } - generatePullDataTransfer(getter, refResourceName, refRes.getResourceHierarchy().toResourcePath(pathParams), refResourceType); - } else { - Expression refGetter = JerseyCodeGenerator.pullAccessor.getDirectStateAccessorFor(refRes, dstRes); - sideEffects = new String[] {""}; - String refExp = refGetter.toImplementation(sideEffects); - String refTypeName = refResourceType.getInterfaceTypeName(); - getter.addFirstStatement(sideEffects[0] + refTypeName + " " + refResourceName + " = " + refExp + ";"); - } - } - - // Construct the base message. - Map.Entry>>, Term> resourcePathsAndMessage = ch.fillOutsideResourcePaths(out, JerseyCodeGenerator.pullAccessor, null); - Map>> resourcePaths = resourcePathsAndMessage.getKey(); - Term messageTerm = resourcePathsAndMessage.getValue(); - - // Data transfer from path depending resource. - for (Entry>> pathEnt: resourcePaths.entrySet()) { - ChannelMember cm = pathEnt.getKey(); - ResourcePath src2 = pathEnt.getValue().getKey(); - // get outside src2 resource state by pull data transfer. - if (cm.isOutside() || src2.getCommonPrefix(dst.getInSideResource(ch)) == null) { - // Data transfer from an outside input resource is regarded as PULL transfer. - List pathParams = new ArrayList<>(); - for (Expression pathExp: src2.getPathParams()) { - sideEffects = new String[] {""}; - pathParams.add("\" + " + pathExp.toImplementation(sideEffects) + " + \""); - } - // generate a pull data transfer from a depending in/ref resource. - Type srcResourceType = src2.getResourceStateType(); - String srcResName2 = JerseyCodeGenerator.toVariableName(JerseyCodeGenerator.getComponentName(src2.getResourceHierarchy())); - String srcPath2 = src2.toResourcePath().replaceAll("\\{", "\"+").replaceAll("\\}", "+\""); - generatePullDataTransfer(getter, srcResName2, srcPath2, srcResourceType); - } - } - - // Data transfer from the descendant channel hierarchies. - Stack> channelItrStack = new Stack<>(); - DataTransferChannel curChannel = ch; - if (curChannel.getChildren() != null && curChannel.getChildren().size() > 0) { - // retrieve descendant channels recursively. - // (For each descendant channel, data transfer from every input resource is regarded as PULL transfer.) - Iterator chItr = curChannel.getChildren().iterator(); - do { - if (!chItr.hasNext()) { - chItr = channelItrStack.pop(); - } else { - curChannel = (DataTransferChannel) chItr.next(); - // generate pull data transfers. - Set chMems = new HashSet<>(curChannel.getInputChannelMembers()); - chMems.addAll(curChannel.getReferenceChannelMembers()); - for (ChannelMember cm2: chMems) { - if (resourcePaths == null || !resourcePaths.keySet().contains(cm2)) { - // not a depending channel member. - ResourcePath src2 = cm2.getResource(); - Type srcResType2 = src2.getResourceStateType(); - String srcResName2 = JerseyCodeGenerator.toVariableName(JerseyCodeGenerator.getComponentName(src2.getResourceHierarchy())); - String srcPath2 = src2.toResourcePath().replaceAll(":.*\\}","\\}").replaceAll("\\{", "\"+").replaceAll("\\}", "+\""); - generatePullDataTransfer(getter, srcResName2, srcPath2, srcResType2); - } else { - // a depending channel member. - ResourcePath src2 = resourcePaths.get(cm2).getKey(); - // get outside src2 resource state by pull data transfer. - if (cm2.isOutside() || src2.getCommonPrefix(dst.getInSideResource(curChannel)) == null) { - // generate a pull data transfer from a depending in/ref resource. - Type srcResType2 = src2.getResourceStateType(); - String srcResName2 = JerseyCodeGenerator.toVariableName(JerseyCodeGenerator.getComponentName(src2.getResourceHierarchy())); - String srcPath2 = src2.toResourcePath().replaceAll(":.*\\}","\\}").replaceAll("\\{", "\"+").replaceAll("\\}", "+\""); - generatePullDataTransfer(getter, srcResName2, srcPath2, srcResType2); - } - } - } - // collect the message constraints by a descendant channel. - List varsForSideEffects = new ArrayList<>(); - int v = 0; - resourcePathsAndMessage = curChannel.fillOutsideResourcePaths(out, JerseyCodeGenerator.pullAccessor, null); - if (resourcePathsAndMessage != null) { - resourcePaths = resourcePathsAndMessage.getKey(); - Term messageTermSub = resourcePathsAndMessage.getValue(); - for (Map.Entry subTermEnt: messageTermSub.getSubTerms(Term.class).entrySet()) { - Term subTerm = subTermEnt.getValue(); - if (!(subTerm instanceof Constant) && subTerm.getSymbol().isImplWithSideEffect()) { - Variable var = new Variable("v" + v, subTerm.getType()); - varsForSideEffects.add(var); - v++; - // Add a side effect statement within the loop - Position pos = new Position(); - pos.addHeadOrder(0); - subTerm.replaceSubTerm(pos, var); - sideEffects = new String[] {""}; - String curState = messageTermSub.toImplementation(sideEffects); - getter.addStatement(sideEffects[0].replaceAll("\n", "")); - // Cancel the side effects in the return value. - pos = subTermEnt.getKey(); - messageTermSub.replaceSubTerm(pos, var); - } - } - if (messageTerm == null) { - messageTerm = messageTermSub; - } else { - messageTerm = (Term) messageTerm.unify(messageTermSub); - } - if (messageTerm == null) { - throw new UnificationFailed(); - } - } - // enclosed by a for loop - Expression selExp = curChannel.getSelectors().get(0).getExpression(); - Type selType = null; - String varName = null; - if (selExp instanceof Variable) { - selType = ((Variable) selExp).getType(); - varName = ((Variable) selExp).getName(); - ChannelMember insideChMem = null; - for (ChannelMember cm2 :curChannel.getInputChannelMembers()) { - if (!cm2.isOutside()) { - insideChMem = cm2; - break; - } - } - if (insideChMem == null) { - for (ChannelMember cm2 :curChannel.getReferenceChannelMembers()) { - if (!cm2.isOutside()) { - insideChMem = cm2; - break; - } - } - } - ResourcePath insideResPath = insideChMem.getResource(); - while (insideResPath.getParent() != null && (insideResPath.getLastParam() == null || !insideResPath.getLastParam().equals(selExp))) { - insideResPath = insideResPath.getParent(); - } - insideResPath = insideResPath.getParent(); - String parent = null; - if (insideResPath != null) { - if (insideResPath.getCommonPrefix(dst.getInSideResource(ch)) != null) { - if (JerseyCodeGenerator.generatesComponent(insideResPath.getResourceHierarchy())) { - Expression parentGetter = JerseyCodeGenerator.pullAccessor.getDirectStateAccessorFor(insideResPath, dst.getInSideResource(ch)); - Term valueGetter = new Term(new Symbol("getValue", 1, Symbol.Type.METHOD)); - valueGetter.addChild(parentGetter); - parent = valueGetter.toImplementation(new String[] {""}); - } else { - parent = JerseyCodeGenerator.pullAccessor.getDirectStateAccessorFor(insideResPath, dst.getInSideResource(ch)).toImplementation(new String[] {""}); - } - } else { - parent = JerseyCodeGenerator.toVariableName(JerseyCodeGenerator.getComponentName(insideResPath.getResourceHierarchy())); - } - if (selType.equals(DataConstraintModel.typeInt)) { - // make a for loop (for a list) for data collecting. - getter.addFirstStatement("for (int " + varName + " = 0; " + varName +" < " + parent + ".size(); " + varName + "++) {"); - } else if (selType.equals(DataConstraintModel.typeString)) { - // make a for loop (for a map) for data collecting. - getter.addFirstStatement("for (String " + varName + ": " + parent + ".keySet()) {"); - } - if (insideResPath.getCommonPrefix(dst.getInSideResource(ch)) == null) { - Type parentResType = insideResPath.getResourceStateType(); - String parentResName = JerseyCodeGenerator.toVariableName(JerseyCodeGenerator.getComponentName(insideResPath.getResourceHierarchy())); - String parentResPath = insideResPath.toString().replaceAll(":.*\\}","\\}").replaceAll("\\{", "\"+").replaceAll("\\}", "+\""); - generatePullDataTransfer(getter, parentResName, parentResPath, parentResType); - } - } - } - // initialize the variables to hold side effects within the loop - for (Variable var: varsForSideEffects) { - getter.addFirstStatement(var.getType().getInterfaceTypeName() + " " + var.getName() + " = new " + var.getType().getImplementationTypeName() + "();"); - } - // end of the loop - getter.addStatement("}"); - if (curChannel.getChildren() != null && curChannel.getChildren().size() > 0) { - channelItrStack.push(chItr); - chItr = curChannel.getChildren().iterator(); - } - } - } while (!channelItrStack.isEmpty()); - } - // generate a return statement. - Expression curExp = ch.deriveUpdateExpressionOf(out, messageTerm, JerseyCodeGenerator.pullAccessor); - sideEffects = new String[] {""}; - String curState = curExp.toImplementation(sideEffects); - if (ch.getChildren() == null || ch.getChildren().size() == 0) { - getter.addStatement(sideEffects[0] + "return " + curState + ";"); - } else { - getter.addStatement("return " + curState + ";"); - } - } - // get src resource state by pull data transfer. - if (src.getNumberOfParameters() == 0 && src.getOutSideResource(ch).getCommonPrefix(dst.getInSideResource(ch)) == null) { - Type srcResourceType = src.getResourceStateType(); - List pathParams = new ArrayList<>(); - generatePullDataTransfer(getter, src.getResourceName(), src.getResourceHierarchy().toResourcePath(pathParams), srcResourceType); - } - } - } - } - } - } - } - - // for source nodes - for (ResourceHierarchy resource: model.getResourceHierarchies()) { - String resourceName = JerseyCodeGenerator.getComponentName(resource); - TypeDeclaration component = componentMap.get(resourceName); - if (JavaCodeGenerator.generatesComponent(resource)) { - if (component != null) { - // state getter method - Type resourceType = JerseyCodeGenerator.getImplStateType(resource); - MethodDeclaration stateGetter = getMethod(component, "getValue"); - if (stateGetter.getBody() == null || stateGetter.getBody().getStatements().size() == 0) { - if (model.isPrimitiveType(resourceType)) { - // primitive type - stateGetter.addStatement("return value;"); - } else { - if (resource.getChildren() != null && resource.getChildren().size() == 1 && resource.getChildren().iterator().next().getNumParameters() > 0) { - // list or map - String implTypeName = resourceType.getImplementationTypeName(); - // copy the current state to be returned as a 'value' - stateGetter.addStatement("return new " + implTypeName + "(value);"); - } else { - if (resource.getChildren() == null || resource.getChildren().size() == 0) { - // a leaf resource - String implTypeName = resourceType.getImplementationTypeName(); - stateGetter.addStatement("return new " + implTypeName + "(value);"); - } else { - Term composer = null; - Term composerSub = new Constant(DataConstraintModel.nil); - composerSub.setType(DataConstraintModel.typeMap); - for (ResourceHierarchy child: resource.getChildren()) { - String childTypeName = JerseyCodeGenerator.getComponentName(child); - String fieldName = JerseyCodeGenerator.toVariableName(childTypeName); - Term childGetter = null; - if (!JerseyCodeGenerator.generatesComponent(child)) { - // the child is not a class - childGetter = new Term(new Symbol("get" + childTypeName, 1, Symbol.Type.METHOD)); - childGetter.addChild(new Constant("this")); - } else { - // the child is a class - childGetter = new Term(new Symbol("getValue", 1, Symbol.Type.METHOD)); - childGetter.addChild(new Field(fieldName, JerseyCodeGenerator.getImplStateType(child))); - } - composer = new Term(DataConstraintModel.insert); - composer.addChild(composerSub); - composer.addChild(new Constant(fieldName, DataConstraintModel.typeString)); // key - composer.addChild(childGetter); // value - composer.setType(DataConstraintModel.typeMap); - composerSub = composer; - } - composer.setType(stateGetter.getReturnType()); - String[] sideEffects = new String[] {null}; - String returnValue = composer.toImplementation(sideEffects); - if (sideEffects[0] != null) { - stateGetter.addStatement(sideEffects[0] + "return " + returnValue+ ";"); - } else { - stateGetter.addStatement("return " + returnValue+ ";"); - } - } - } - } - } - - // (#4) descendant getter method (the implementation must be kept consistent with #3) - if (resource.getChildren().size() > 0) { - for (ResourceHierarchy child: resource.getChildren()) { - ResourceHierarchy parent = resource; - ResourceHierarchy descendant = child; - Set children; - Expression selector; - int params = 0; - if (DataConstraintModel.typeList.isAncestorOf(parent.getResourceStateType())) { - selector = new Field("value"); - params++; - } else if (DataConstraintModel.typeMap.isAncestorOf(parent.getResourceStateType())) { - selector = new Field("value"); - params++; - } else { - String fieldName = JerseyCodeGenerator.getComponentName(descendant); - selector = new Field(JerseyCodeGenerator.toVariableName(fieldName)); - } - do { - String methodName = JerseyCodeGenerator.getComponentName(descendant); - MethodDeclaration descendantGetter = null; - for (MethodDeclaration getter: getGetterMethods(component, methodName)) { - if ((getter.getParameters() == null && params == 0) || (getter.getParameters() != null && getter.getParameters().size() == params)) { - descendantGetter = getter; - break; - } - } - if (descendantGetter != null) { - if (DataConstraintModel.typeList.isAncestorOf(parent.getResourceStateType())) { - Term newSelector = new Term(DataConstraintModel.get); - newSelector.addChild(selector); - newSelector.addChild(new Variable(descendantGetter.getParameters().get(descendantGetter.getParameters().size() - 1).getName())); - newSelector.setType(descendantGetter.getReturnType()); - selector = newSelector; - } else if (DataConstraintModel.typeMap.isAncestorOf(parent.getResourceStateType())) { - Term newSelector = new Term(DataConstraintModel.lookup); - newSelector.addChild(selector); - newSelector.addChild(new Variable(descendantGetter.getParameters().get(descendantGetter.getParameters().size() - 1).getName())); - newSelector.setType(descendantGetter.getReturnType()); - selector = newSelector; - } - if (descendantGetter != null && (descendantGetter.getBody() == null || descendantGetter.getBody().getStatements().size() == 0)) { - String[] sideEffects = new String[] {null}; - String returnValue = selector.toImplementation(sideEffects); - if (sideEffects[0] != null) descendantGetter.addStatement(sideEffects[0]); - descendantGetter.addStatement("return " + returnValue + ";"); - } - } - if (JerseyCodeGenerator.generatesComponent(descendant)) { - // If the descendant generates a component. - break; - } - parent = descendant; - if (DataConstraintModel.typeList.isAncestorOf(parent.getResourceStateType())) { - params++; - } else if (DataConstraintModel.typeMap.isAncestorOf(parent.getResourceStateType())) { - params++; - } - children = descendant.getChildren(); - } while (children != null && children.size() == 1 && (descendant = children.iterator().next()) != null); - } - } - } - } - - // methods for input events - Map> ioChannelsAndMembers = getIOChannelsAndMembers(resource, model); - for (Map.Entry> entry: ioChannelsAndMembers.entrySet()) { - DataTransferChannel ch = entry.getKey(); - Set outs = entry.getValue(); - for (ChannelMember out: outs) { - MethodDeclaration input = null; - if (JerseyCodeGenerator.generatesComponent(resource)) { - // A component is generated for this resource. - input = getInputMethod(component, out, ch.getOutputChannelMembers().size()); - } else { - // No component is generated for this resource. - ResourceHierarchy parent = resource.getParent(); - if (parent != null) { - TypeDeclaration parentType = componentMap.get(JerseyCodeGenerator.getComponentName(parent)); - input = getInputMethod(parentType, out, ch.getOutputChannelMembers().size()); - } - } - if (input != null) { - // In each resource - Set referredSet = referredResources.get(input); - for (ChannelMember rc: ch.getReferenceChannelMembers()) { - // For each reference channel member, get the current state of the reference side resource by pull data transfer. - ResourcePath ref = rc.getResource(); - if (referredSet == null) { - referredSet = new HashSet<>(); - referredResources.put(input, referredSet); - } - if (!out.getResource().equals(ref)) { - String refResourceName = ref.getLeafResourceName(); - Type refResourceType = ref.getResourceStateType(); - if (!referredSet.contains(ref)) { - referredSet.add(ref); - String[] sideEffects = new String[] {""}; - ResourcePath dstRes = out.getResource(); - if (!JerseyCodeGenerator.generatesComponent(dstRes.getResourceHierarchy())) { - dstRes = dstRes.getParent(); - } - if (rc.isOutside() || (ref.getCommonPrefix(dstRes) == null && JerseyCodeGenerator.differentTreesAsDifferentServices)) { - List pathParams = new ArrayList<>(); - for (Expression pathExp: ref.getPathParams()) { - pathParams.add("\" + " + pathExp.toImplementation(sideEffects) + " + \""); - } - generatePullDataTransfer(input, refResourceName, ref.getResourceHierarchy().toResourcePath(pathParams), refResourceType); - } else { - Expression refGetter = JerseyCodeGenerator.pullAccessor.getDirectStateAccessorFor(ref, dstRes); - String refExp = refGetter.toImplementation(sideEffects); - String refTypeName = refResourceType.getInterfaceTypeName(); - input.addFirstStatement(sideEffects[0] + refTypeName + " " + refResourceName + " = " + refExp + ";"); - } - } - } - } - Expression updateExp = ch.deriveUpdateExpressionOf(out, JerseyCodeGenerator.refAccessor).getKey(); - // Replace Json constructor with a constructor of a descendant resource. - ResourceHierarchy outRes = out.getResource().getResourceHierarchy(); - if (outRes.getChildren().size() == 1 && outRes.getChildren().iterator().next().getNumParameters() > 0) { - ResourceHierarchy descendantRes = outRes.getChildren().iterator().next(); - Set children; - do { - if (JerseyCodeGenerator.generatesComponent(descendantRes)) break; - children = descendantRes.getChildren(); - } while (children != null && children.size() == 1 && (descendantRes = children.iterator().next()) != null); - Type descendantStateType = descendantRes.getResourceStateType(); - String descendantComponentName = JerseyCodeGenerator.getComponentName(descendantRes); - TypeDeclaration descendantComponent = componentMap.get(descendantComponentName); - if (DataConstraintModel.typeJson.isAncestorOf(descendantStateType)) { - replaceJsonTermWithConstructorInvocation(updateExp, descendantStateType, descendantComponentName, descendantComponent); - } - } - // Replace the type of the state field. - Type fieldType = JerseyCodeGenerator.getImplStateType(outRes); - if (updateExp instanceof Term) { - ((Term) updateExp).setType(fieldType); - for (Map.Entry varEnt: ((Term) updateExp).getVariables().entrySet()) { - if (varEnt.getValue().getName().equals("value")) { - varEnt.getValue().setType(fieldType); - } - } - } else if (updateExp instanceof Variable) { - ((Variable) updateExp).setType(fieldType); - } - // Add statements to the input method. - String[] sideEffects = new String[] {""}; - String newState = updateExp.toImplementation(sideEffects); - if (JerseyCodeGenerator.generatesComponent(resource)) { - String updateStatement; - 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] + "this.value = " + newState + ";"; - } - if (input.getBody() == null || !input.getBody().getStatements().contains(updateStatement)) { - input.addStatement(updateStatement); - } - } else { - String updateStatement = ""; - if (sideEffects[0] != null) { - updateStatement = sideEffects[0]; - updateStatement = updateStatement.replace(".value", "." + JerseyCodeGenerator.toVariableName(JerseyCodeGenerator.getComponentName(resource))); - if (updateStatement.endsWith("\n")) { - updateStatement = updateStatement.substring(0, updateStatement.length() - 1); - } - } - if (DataConstraintModel.typeList.isAncestorOf(resource.getParent().getResourceStateType())) { - Term selector = new Term(DataConstraintModel.set); - selector.addChild(new Field("value")); - selector.addChild(new Variable(input.getParameters().get(input.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(resource.getParent().getResourceStateType())) { - Term selector = new Term(DataConstraintModel.insert); - selector.addChild(new Field("value")); - selector.addChild(new Variable(input.getParameters().get(input.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())) { - updateStatement += "this." + JerseyCodeGenerator.toVariableName(JerseyCodeGenerator.getComponentName(resource)) + " = " + newState + ";"; - } - if (updateStatement != null && (input.getBody() == null || !input.getBody().getStatements().contains(updateStatement))) { - input.addStatement(updateStatement); - } - } - - if (out.getResource().getParent() != null && out.getResource().getParent().getParent() != null) { - // In the root resource - Expression message = out.getStateTransition().getMessageExpression(); - String inputAccessorName = input.getName(); - if (message instanceof Term) { - inputAccessorName = ((Term) message).getSymbol().getImplName(); - } else if (message instanceof Variable) { - inputAccessorName = ((Variable) message).getName(); - } - MethodDeclaration inputAccessor = getMethod(componentMap.get(JerseyCodeGenerator.getComponentName(resource.getRoot())), inputAccessorName); - if (inputAccessor != null) { - ResourcePath outResPath = new ResourcePath(out.getResource()); - for (int i = 0; i < outResPath.getPathParams().size(); i++) { - Parameter pathParam = new Parameter(inputAccessor.getParameters().get(i).getName()); - outResPath.replacePathParam(i, pathParam, null); - } - // The expression of the receiver (resource) of the input method. - Expression resExp = JerseyCodeGenerator.pullAccessor.getDirectStateAccessorFor(outResPath, outResPath.getRoot()); - String args = ""; - String delimiter = ""; - if (resExp instanceof Term) { - // To access the parent resource if the leaf resource is primitive and cannot declare the input method, or to remove getValue(). - 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); - } - // Values of channel parameters. - for (Selector selector: ch.getAllSelectors()) { - if (selector.getExpression() instanceof Variable) { - Variable selVar = (Variable) selector.getExpression(); - args += delimiter + selVar.getName(); - delimiter = ", "; - } - } - // Values of message parameters. - if (message instanceof Term) { - for (Variable mesVar: message.getVariables().values()) { - args += delimiter + mesVar.getName(); - delimiter = ", "; - } - } - if (resExp != null) { - String resourceAccess = resExp.toImplementation(new String[] {""}); - inputAccessor.addStatement(resourceAccess + "." + input.getName() + "(" + args + ");"); - } else { - inputAccessor.addStatement(input.getName() + "(" + args + ");"); - } - if (input != null && input.getThrows() != null && input.getThrows().getExceptions().contains("JsonProcessingException")) { - inputAccessor.addThrow("JsonProcessingException"); - } - } - } - } - } - } - } - } catch (ParameterizedIdentifierIsFutureWork | ResolvingMultipleDefinitionIsFutureWork - | InvalidMessage | UnificationFailed | ValueUndefined e1) { - e1.printStackTrace(); - } - return codes; - } - - private static void replaceJsonTermWithConstructorInvocation(Expression exp, Type replacedJsonType, String replacingClassName, TypeDeclaration descendantComponent) { - // Replace each json term in exp with the corresponding constructor invocation. - Type descendantType = new Type(replacingClassName, replacingClassName); - Map subTerms = ((Term) exp).getSubTerms(Term.class); - Iterator> termEntItr = subTerms.entrySet().iterator(); - while (termEntItr.hasNext()) { - Entry termEnt = termEntItr.next(); - Term jsonTerm = termEnt.getValue(); - if (jsonTerm.getType() != null) { - if (jsonTerm.getType().equals(replacedJsonType)) { - if (jsonTerm instanceof JsonTerm || jsonTerm.getSymbol().equals(DataConstraintModel.addMember)) { - String constructorInvocation = "new " + replacingClassName + "("; - MethodDeclaration descendantConstructor = getConstructor(descendantComponent); - if (descendantConstructor != null) { - String delimiter = ""; - for (VariableDeclaration var: descendantConstructor.getParameters()) { - // Extract the argument of each constructor parameter from jsonTerm. - JsonAccessor jsonMember = new JsonAccessor(DataConstraintModel.dot); - jsonMember.addChild(jsonTerm); - jsonMember.addChild(new Constant(var.getName(), DataConstraintModel.typeString)); - Expression param = jsonMember.reduce(); // Reduce {"name": "foo", age: 25}.name => "foo" - if (param != null) { - if (param instanceof Term) { - if (((Term) param).getType() == null) { - ((Term) param).setType(var.getType()); - } - } else if (param instanceof Variable) { - if (((Variable) param).getType() == null) { - ((Variable) param).setType(var.getType()); - } - } - constructorInvocation = constructorInvocation + delimiter + param.toImplementation(null); - } else { - constructorInvocation = constructorInvocation + delimiter + var.getName(); - } - delimiter = ", "; - } - } - constructorInvocation += ")"; - ((Term) exp).replaceSubTerm(termEnt.getKey(), new Constant(constructorInvocation)); - subTerms = ((Term) exp).getSubTerms(Term.class); - termEntItr = subTerms.entrySet().iterator(); - } else { - jsonTerm.setType(descendantType); - } - } else { - Type oldType = jsonTerm.getType(); - Type newType = new Type(oldType.getTypeName(), - oldType.getImplementationTypeName().replace(replacedJsonType.getInterfaceTypeName(), replacingClassName), - oldType.getInterfaceTypeName().replace(replacedJsonType.getInterfaceTypeName(), replacingClassName)); - for (Type parent: oldType.getParentTypes()) { - newType.addParentType(parent); - } - jsonTerm.setType(newType); - } - } - } - } - - private static void generatePullDataTransfer(MethodDeclaration methodBody, String fromResourceName, String fromResourcePath, Type fromResourceType) { - String varName = new String(fromResourceName); - String respTypeName = fromResourceType.getInterfaceTypeName(); - String respImplTypeName = fromResourceType.getImplementationTypeName(); - String respConverter = ""; - if (DataConstraintModel.typeList.isAncestorOf(fromResourceType) && fromResourceType != DataConstraintModel.typeList) { - Type compType = TypeInference.getListComponentType(fromResourceType); - if (DataConstraintModel.typeTuple.isAncestorOf(compType)) { - varName += "_json"; - String mapTypeName = convertFromEntryToMapType(compType); - respTypeName = "List<" + mapTypeName + ">"; - respConverter += fromResourceType.getInterfaceTypeName() + " " + fromResourceName + " = new " + fromResourceType.getImplementationTypeName() + "();\n"; - respConverter += "for (" + mapTypeName + " i: " + varName + ") {\n"; - respConverter += "\t" + fromResourceName + ".add(" + getCodeForConversionFromMapToTuple(compType, "i") + ");\n"; - respConverter += "}"; - methodBody.addThrow("JsonProcessingException"); - } else if (DataConstraintModel.typeMap.isAncestorOf(compType)) { - // To do. - } - } else if (DataConstraintModel.typeTuple.isAncestorOf(fromResourceType)) { - varName += "_json"; - respTypeName = convertFromEntryToMapType(fromResourceType); - respConverter += fromResourceType.getInterfaceTypeName() + " " + fromResourceName + " = " + getCodeForConversionFromMapToTuple(fromResourceType, varName) + ";"; - respImplTypeName = "HashMap"; - } else if (DataConstraintModel.typePair.isAncestorOf(fromResourceType)) { - varName += "_json"; - respTypeName = convertFromEntryToMapType(fromResourceType); - respConverter += fromResourceType.getInterfaceTypeName() + " " + fromResourceName + " = " + getCodeForConversionFromMapToPair(fromResourceType, varName) + ";"; - respImplTypeName = "HashMap"; - } else if (DataConstraintModel.typeMap.isAncestorOf(fromResourceType)) { - varName += "_json"; - respTypeName = convertFromEntryToMapType(fromResourceType); - respConverter += fromResourceType.getInterfaceTypeName() + " " + fromResourceName + " = new " + fromResourceType.getImplementationTypeName() + "();\n"; - respConverter += getCodeForConversionFromMapToMap(fromResourceType, varName, fromResourceName); - respImplTypeName = "HashMap"; - } - if (respConverter.length() > 0) { - methodBody.addFirstStatement(respConverter); - } - methodBody.addFirstStatement(respTypeName + " " + varName + " = " + getHttpMethodCallStatementWithResponse(baseURL, fromResourcePath, "get", respImplTypeName)); - } - - private static String convertFromEntryToMapType(Type type) { - String mapTypeName = null; - if (DataConstraintModel.typePair.isAncestorOf(type)) { - Type compType = TypeInference.getPairComponentType(type); - String wrapperType = DataConstraintModel.getWrapperType(compType); - if (wrapperType != null) { - mapTypeName = "Map"; - } else { - mapTypeName = "Map"; - } - } else if (DataConstraintModel.typeMap.isAncestorOf(type)) { - List compTypes = TypeInference.getMapComponentTypes(type); - String wrapperType = DataConstraintModel.getWrapperType(compTypes.get(1)); - if (wrapperType != null) { - mapTypeName = "Map"; - } else { - mapTypeName = "Map"; - } - } else { - mapTypeName = type.getInterfaceTypeName(); - mapTypeName = mapTypeName.replace("Map.Entry", "Map"); - for (int idx = mapTypeName.indexOf("<", 0); idx >= 0; idx = mapTypeName.indexOf("<", idx + 1)) { - int to = mapTypeName.indexOf(",", idx); - if (to > idx) { - mapTypeName = mapTypeName.substring(0, idx + 1) + "String" + mapTypeName.substring(to); // All elements except for the last one have the string type. - } - } - } - return mapTypeName; - } - - private static String getCodeForConversionFromMapToTuple(Type tupleType, String mapVar) { - String decoded = "$x"; - List elementsTypes = TypeInference.getTupleComponentTypes(tupleType); - String elementBase = mapVar; - for (Type elmType: elementsTypes.subList(0, elementsTypes.size() - 1)) { - elementBase += ".entrySet().iterator().next()"; - if (elmType == DataConstraintModel.typeBoolean - || elmType == DataConstraintModel.typeInt - || elmType == DataConstraintModel.typeLong - || elmType == DataConstraintModel.typeFloat - || elmType == DataConstraintModel.typeDouble) { - String elmVal = new JavaSpecific().getStringToValueExp(elmType.getImplementationTypeName(), elementBase + ".getKey()"); - decoded = decoded.replace("$x", "new AbstractMap.SimpleEntry<>(" + elmVal + ", $x)"); - } else if (elmType == DataConstraintModel.typeString) { - decoded = decoded.replace("$x", "new AbstractMap.SimpleEntry<>(" + elementBase + ".getKey(), $x)"); - } else { - // To do. - } - elementBase += ".getValue()"; - } - decoded = decoded.replace("$x", elementBase); - return decoded; - } - - private static String getCodeForConversionFromMapToPair(Type pairType, String mapVar) { - String decoded = "$x"; - decoded = decoded.replace("$x", "new Pair<>(" + mapVar + ".get(\"left\"), $x)"); - decoded = decoded.replace("$x", mapVar + ".get(\"right\")"); - return decoded; - } - - private static String getCodeForConversionFromMapToMap(Type mapType, String mapVal, String mapVar) { - List elementsTypes = TypeInference.getMapComponentTypes(mapType); - Type keyType = elementsTypes.get(0); - Type valType = elementsTypes.get(1); - String keyVal = null; - String decoded = ""; - if (keyType == DataConstraintModel.typeBoolean - || keyType == DataConstraintModel.typeInt - || keyType == DataConstraintModel.typeLong - || keyType == DataConstraintModel.typeFloat - || keyType == DataConstraintModel.typeDouble) { - decoded += "for (String k: " + mapVal + ".keySet()) {\n"; - decoded += "\t" + mapVar + ".put("; - keyVal = new JavaSpecific().getStringToValueExp(keyType.getImplementationTypeName(), "k"); - decoded += keyVal + ", " + mapVal + ".get(" + keyVal + ")" + ");\n"; - decoded += "}"; - } else if (keyType == DataConstraintModel.typeString) { - decoded += mapVar + " = " + mapVal + ";"; - } - return decoded; - } - - private static String getHttpMethodParamsStatement(String callerResourceName, List>> params, boolean isFirstCall) { - String statements = ""; - if (isFirstCall) { - statements += "Form "; - } - statements += "form = new Form();\n"; - for (Map.Entry> param: params) { - Type paramType = param.getKey(); - String paramName = param.getValue().getKey(); - String value = param.getValue().getValue(); - if (DataConstraintModel.typeList.isAncestorOf(paramType)) { - Type compType = TypeInference.getListComponentType(paramType); - String wrapperType = DataConstraintModel.getWrapperType(compType); - if (wrapperType == null) { - statements += "for (" + compType.getInterfaceTypeName() + " i: " + value + ") {\n"; - } else { - statements += "for (" + wrapperType + " i: " + value + ") {\n"; - } - if (DataConstraintModel.typeTuple.isAncestorOf(compType) || DataConstraintModel.typePair.isAncestorOf(paramType) || DataConstraintModel.typeList.isAncestorOf(compType) || DataConstraintModel.typeMap.isAncestorOf(paramType)) { - statements += "\tform.param(\"" + paramName + "\", new ObjectMapper().writeValueAsString(i));\n"; // typeTuple: {"1.0":2.0}, typePair: {"left": 1.0, "right":2.0} - } else { - statements += "\tform.param(\"" + paramName + "\", i.toString());\n"; - } - statements += "}\n"; -// return "Entity entity = Entity.entity(" + paramName + ".toString(), MediaType.APPLICATION_JSON);"; - } else if (DataConstraintModel.typeTuple.isAncestorOf(paramType) || DataConstraintModel.typePair.isAncestorOf(paramType) || DataConstraintModel.typeMap.isAncestorOf(paramType)) { - // typeTuple: {"1.0":2.0}, typePair: {"left": 1.0, "right":2.0} - statements += "form.param(\"" + paramName + "\", new ObjectMapper().writeValueAsString(" + value + "));\n"; - } else { - statements += "form.param(\"" + paramName + "\", " + new JavaSpecific().getValueToStringExp(paramType.getImplementationTypeName(), value) + ");\n"; - } - } - if (isFirstCall) { - statements += "Entity
"; - } - statements += "entity = Entity.entity(form, MediaType.APPLICATION_FORM_URLENCODED);"; - return statements; - } - - private static String getHttpMethodCallStatement(String baseURL, String resourceName, String srcResName, String httpMethod) { - if (srcResName == null) { - return "client.target(\"" + baseURL + "\").path(\"/" + resourceName + "\").request()." + httpMethod + "(entity, String.class);"; - } else { - // For each source resource, a child resource is defined in the destination resource so that its state can be updated separately. - return "client.target(\"" + baseURL + "\").path(\"/" + resourceName + "/" + srcResName + "\").request()." + httpMethod + "(entity, String.class);"; - } - } - - private static String getHttpMethodCallStatementWithResponse(String baseURL, String resourceName, String httpMethod, String respImplName) { - String responseShortTypeName = respImplName; - if (respImplName.contains("<")) { - responseShortTypeName = respImplName.substring(0, respImplName.indexOf("<")); - } - return "client.target(\"" + baseURL + "\").path(\"/" + resourceName + "\").request()." + httpMethod + "(" + responseShortTypeName + ".class);"; - } - - private static MethodDeclaration getConstructor(TypeDeclaration component) { - for (MethodDeclaration m: component.getMethods()) { - if (m.isConstructor()) return m; - } - return null; - } - - private static MethodDeclaration getUpdateMethod(TypeDeclaration component, String dstResName, String srcResName) { - for (MethodDeclaration m: component.getMethods()) { - if (dstResName == null) { - if (m.getName().equals("updateFrom" + srcResName)) return m; - } else { - if (m.getName().equals("update" + dstResName + "From" + srcResName)) return m; - } - } - return null; - } - - private static List getUpdateMethods(TypeDeclaration component, String resName) { - List updates = new ArrayList<>(); - for (MethodDeclaration m: component.getMethods()) { - if (resName == null) { - if (m.getName().startsWith("updateFrom")) { - updates.add(m); - } - } else { - if (m.getName().startsWith("update" + resName + "From")) { - updates.add(m); - } - } - } - return updates; - } - - private static MethodDeclaration getGetterMethod(TypeDeclaration component, String resourceName) { - for (MethodDeclaration m: component.getMethods()) { - if (m.getName().startsWith("get" + resourceName)) return m; - } - return null; - } - - private static List getGetterMethods(TypeDeclaration component, String resourceName) { - List getters = new ArrayList<>(); - for (MethodDeclaration m: component.getMethods()) { - if (m.getName().equals("get" + resourceName)) { - getters.add(m); - } - } - return getters; - } - - private static Map> getIOChannelsAndMembers(ResourceHierarchy resource, DataTransferModel model) { - Map> ioChannelsAndMembers = new HashMap<>(); - for (Channel c: model.getInputChannels()) { - DataTransferChannel ch = (DataTransferChannel) c; - // I/O channel - for (ChannelMember out: ch.getOutputChannelMembers()) { - if (resource.equals(out.getResource().getResourceHierarchy())) { - if (out.getStateTransition().getMessageExpression() instanceof Term || out.getStateTransition().getMessageExpression() instanceof Variable) { - Set channelMembers = ioChannelsAndMembers.get(ch); - if (channelMembers == null) { - channelMembers = new HashSet<>(); - ioChannelsAndMembers.put(ch, channelMembers); - } - channelMembers.add(out); - } - } - } - } - return ioChannelsAndMembers; - } - - private static List getInputMethods(TypeDeclaration component, ResourceNode resource, DataTransferModel model) { - List inputs = new ArrayList<>(); - for (Channel c: model.getInputChannels()) { - DataTransferChannel channel = (DataTransferChannel) c; - // I/O channel - for (ChannelMember out: channel.getOutputChannelMembers()) { - if (resource.getInSideResources().contains(out.getResource())) { - MethodDeclaration input = getInputMethod(component, out, channel.getOutputChannelMembers().size()); - inputs.add(input); - } - } - } - return inputs; - } - - private static MethodDeclaration getInputMethod(TypeDeclaration component, ChannelMember cm, int outNumber) { - String inputMethodName = null; - if (cm.getStateTransition().getMessageExpression() instanceof Term) { - Term message = (Term) cm.getStateTransition().getMessageExpression(); - inputMethodName = message.getSymbol().getImplName(); - } else if (cm.getStateTransition().getMessageExpression() instanceof Variable) { - Variable message = (Variable) cm.getStateTransition().getMessageExpression(); - inputMethodName = message.getName(); - } - if (outNumber > 1) { - inputMethodName += "For" + JerseyCodeGenerator.getComponentName(cm.getResource().getResourceHierarchy()); - } - MethodDeclaration input = getMethod(component, inputMethodName); - return input; - } - - private static MethodDeclaration getMethod(TypeDeclaration component, String methodName) { - for (MethodDeclaration m: component.getMethods()) { - if (m.getName().equals(methodName)) return m; - } - return null; - } -}