diff --git a/AlgebraicDataflowArchitectureModel/models/Citrus.model b/AlgebraicDataflowArchitectureModel/models/Citrus.model index 3730a7d..700e4dd 100644 --- a/AlgebraicDataflowArchitectureModel/models/Citrus.model +++ b/AlgebraicDataflowArchitectureModel/models/Citrus.model @@ -3,7 +3,7 @@ } channel CreateBook(aid:Str) { - out accounts.{aid}.books(bookList:List, createBook(title:Str)) = append(bookList, {"title": title, "todos":nil, "favorited": nil}) + out accounts.{aid}.books(bookList:List, createBook(title:Str)) = append(bookList, {"title": title, "todos": nil, "favorited": nil}) } channel DeleteAccount { @@ -11,7 +11,7 @@ } channel ChangeAccountName { - out accounts(accDB:Map, changeAccountId(aid:Str, newAid:Str)) = insert(delete(accDB, aid), newAid, lookup(accDB, aid)) + out accounts(accDB:Map, changeAccountId(aid:Str, newAid:Str)) = if(aid == newAid, accDB, delete(insert(accDB, newAid, lookup(accDB, aid)), aid)) } channel ChangeBookName(aid:Str, bid:Int) { @@ -23,7 +23,7 @@ } channel CreateToDo(aid:Str, bid:Int) { - out accounts.{aid}.books.{bid}.todos(toDoDB:Map, createtodo(title:Str, year:Str, month:Str, day:Str)) = insert(toDoDB, year, + out accounts.{aid}.books.{bid}.todos(toDoDB:Map, createtodo(year:Str, month:Str, day:Str, title:Str)) = insert(toDoDB, year, insert(lookup(toDoDB, year), month, insert(lookup(lookup(toDoDB, year), month), day, append(lookup(lookup(lookup(toDoDB, year), month), day), {"title": title, "check": false})))) @@ -37,8 +37,15 @@ out accounts.{aid}.books.{bid}.todos.{year}.{month}.{day}.{tid}.check(check:Bool, changeCheck(newCheck)) = newCheck } -channel DeleteToDo(aid:Str, bid:Int, year:Str, month:Str, day:Str, tid:Int) { - out accounts.{aid}.books.{bid}.todos.{year}.{month}.{day}(todoList:List, deleteToDo(tid:int)) = if(tid < length(todoList), remove(todoList, tid), todoList) +channel DeleteToDo(aid:Str, bid:Int) { + out accounts.{aid}.books.{bid}.todos(toDoDB:Map, deleteToDo(year:Str, month:Str, day:Str, tid:int)) = insert(toDoDB, + year, + insert(lookup(toDoDB, year), + month, + insert(lookup(lookup(toDoDB, year), month), + day, + remove(lookup(lookup(lookup(toDoDB, year), month), day), + tid)))) } channel AddFavorited(aid:Str, bid:Int) { diff --git a/AlgebraicDataflowArchitectureModel/src/generators/CodeGenerator.java b/AlgebraicDataflowArchitectureModel/src/generators/CodeGenerator.java index fe86c0c..7792b4f 100644 --- a/AlgebraicDataflowArchitectureModel/src/generators/CodeGenerator.java +++ b/AlgebraicDataflowArchitectureModel/src/generators/CodeGenerator.java @@ -98,14 +98,14 @@ if (generatesComponent(child)) { return langSpec.newListType(getComponentName(child, langSpec)); } else { - return langSpec.newListType(getImplStateType(child, langSpec).getImplementationTypeName()); + return langSpec.newListType(getImplStateType(child, langSpec).getInterfaceTypeName()); } } else if (DataConstraintModel.typeMap.isAncestorOf(res.getResourceStateType())) { // map. if (generatesComponent(child)) { return langSpec.newMapType(DataConstraintModel.typeString, getComponentName(child, langSpec)); } else { - return langSpec.newMapType(DataConstraintModel.typeString, getImplStateType(child, langSpec).getImplementationTypeName()); + return langSpec.newMapType(DataConstraintModel.typeString, getImplStateType(child, langSpec).getInterfaceTypeName()); } } return null; @@ -117,9 +117,11 @@ } public static boolean generatesComponent(ResourceHierarchy res) { - return res.getParent() == null || !(res.getChildren() == null || res.getChildren().size() == 0); -// Type resType = res.getResourceStateType(); -// return DataConstraintModel.typeJson.isAncestorOf(resType) || DataConstraintModel.typeList.isAncestorOf(resType) || DataConstraintModel.typeMap.isAncestorOf(resType); + 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; + return true; +// return res.getParent() == null || !(res.getChildren() == null || res.getChildren().size() == 0); } /** @@ -367,29 +369,37 @@ } } - protected void fillChildGetterMethod(MethodDeclaration childGetter, ResourceHierarchy child, Type parentResourceType, ILanguageSpecific langSpec) { - if (DataConstraintModel.typeList.isAncestorOf(parentResourceType)) { - Term selector = new Term(DataConstraintModel.get); - selector.addChild(new Variable(langSpec.getFieldAccessor(fieldOfResourceState))); - selector.addChild(new Variable(childGetter.getParameters().get(childGetter.getParameters().size() - 1).getName())); - selector.setType(childGetter.getReturnType()); - String[] sideEffects = new String[] {null}; - String returnValue = selector.toImplementation(sideEffects); - if (sideEffects[0] != null) childGetter.addStatement(sideEffects[0]); - childGetter.addStatement(langSpec.getReturnStatement(returnValue) + langSpec.getStatementDelimiter()); - } else if (DataConstraintModel.typeMap.isAncestorOf(parentResourceType)) { - Term selector = new Term(DataConstraintModel.lookup); - selector.addChild(new Variable(langSpec.getFieldAccessor(fieldOfResourceState))); - selector.addChild(new Variable(childGetter.getParameters().get(childGetter.getParameters().size() - 1).getName())); - selector.setType(childGetter.getReturnType()); - String[] sideEffects = new String[] {null}; - String returnValue = selector.toImplementation(sideEffects); - if (sideEffects[0] != null) childGetter.addStatement(sideEffects[0]); - childGetter.addStatement(langSpec.getReturnStatement(returnValue) + langSpec.getStatementDelimiter()); + protected void fillDescendantGetterMethod(MethodDeclaration descendantGetter, ResourceHierarchy descendant, ResourceHierarchy ancestor, TypeDeclaration ancestorComponent, ILanguageSpecific langSpec) { + Expression selector; + if (DataConstraintModel.typeList.isAncestorOf(ancestor.getResourceStateType())) { + selector = new Variable(langSpec.getFieldAccessor(fieldOfResourceState)); + } else if (DataConstraintModel.typeMap.isAncestorOf(ancestor.getResourceStateType())) { + selector = new Variable(langSpec.getFieldAccessor(fieldOfResourceState)); } else { - String fieldName = langSpec.toVariableName(getComponentName(child, langSpec)); - childGetter.addStatement(langSpec.getReturnStatement(langSpec.getFieldAccessor(fieldName)) + langSpec.getStatementDelimiter()); - } + String fieldName = langSpec.toVariableName(getComponentName(descendant, langSpec)); + selector = new Variable(langSpec.getFieldAccessor(fieldName)); + } + if (descendantGetter.getParameters() != null) { + for (VariableDeclaration param: descendantGetter.getParameters()) { + if (DataConstraintModel.typeInt.isAncestorOf(param.getType())) { + Term newSelector = new Term(DataConstraintModel.get); + newSelector.addChild(selector); + newSelector.addChild(new Variable(param.getName())); + selector = newSelector; + } else if (DataConstraintModel.typeString.isAncestorOf(param.getType())) { + Term newSelector = new Term(DataConstraintModel.lookup); + newSelector.addChild(selector); + newSelector.addChild(new Variable(param.getName())); + 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(langSpec.getReturnStatement(returnValue) + langSpec.getStatementDelimiter()); + } } protected void declareAccessorInMainComponent(TypeDeclaration mainComponent, ResourceNode accessRes, MethodDeclaration stateGetter, ILanguageSpecific langSpec) { @@ -453,6 +463,16 @@ return null; } + protected static List getGetterMethods(TypeDeclaration component, String resourceName) { + List getters = new ArrayList<>(); + for (MethodDeclaration m: component.getMethods()) { + if (m.getName().startsWith(getterPrefix + resourceName)) { + getters.add(m); + } + } + return getters; + } + protected MethodDeclaration getUpdateMethod(Edge inEdge, TypeDeclaration component, Map>> dataFlowInform, ILanguageSpecific langSpec) { List passedResoueces = dataFlowInform.get(inEdge).get(PushPullValue.PUSH); @@ -602,6 +622,7 @@ // iterate from the root resource Term getter = null; int v = 1; + int arity = 2; while (!pathStack.empty()) { curPath = pathStack.pop(); String typeName = getComponentName(curPath.getResourceHierarchy(), langSpec); @@ -610,23 +631,65 @@ String fieldName = langSpec.toVariableName(typeName); getter = new Field(fieldName, new Type(typeName, typeName)); } else { - Term newGetter = new Term(new Symbol(getterPrefix + typeName, -1, Symbol.Type.METHOD)); - newGetter.addChild(getter); - if (curPath.getResourceHierarchy().getNumParameters() > 0) { - Variable var = null; - Expression param = curPath.getLastParam(); - if (param instanceof Variable) { - var = (Variable) param; - } else if (param instanceof Term) { - var = new Variable("v" + v, ((Term) param).getType()); + if (generatesComponent(curPath.getResourceHierarchy())) { + if (arity == 2) { + Term newGetter = new Term(new Symbol(getterPrefix + typeName, -1, Symbol.Type.METHOD)); + newGetter.addChild(getter); + if (curPath.getResourceHierarchy().getNumParameters() > 0) { + Variable var = null; + Expression param = curPath.getLastParam(); + if (param instanceof Variable) { + var = (Variable) param; + } else if (param instanceof Term) { + var = new Variable("v" + v, ((Term) param).getType()); + } + if (var != null) { + newGetter.addChild(var); + newGetter.getSymbol().setArity(2); + } + v++; + } + getter = newGetter; + } else { + if (curPath.getResourceHierarchy().getNumParameters() > 0) { + Variable var = null; + Expression param = curPath.getLastParam(); + if (param instanceof Variable) { + var = (Variable) param; + } else if (param instanceof Term) { + var = new Variable("v" + v, ((Term) param).getType()); + } + if (var != null) { + getter.getSymbol().setArity(arity); + getter.addChild(var); + } + v++; + } } - if (var != null) { - newGetter.addChild(var); - newGetter.getSymbol().setArity(2); + arity = 2; + } else { + // to get a descendant resource directly. + if (arity == 2) { + Term newGetter = new Term(new Symbol(getterPrefix + typeName, -1, Symbol.Type.METHOD)); + newGetter.addChild(getter); + getter = newGetter; } - v++; + if (curPath.getResourceHierarchy().getNumParameters() > 0) { + Variable var = null; + Expression param = curPath.getLastParam(); + if (param instanceof Variable) { + var = (Variable) param; + } else if (param instanceof Term) { + var = new Variable("v" + v, ((Term) param).getType()); + } + if (var != null) { + getter.getSymbol().setArity(arity); + getter.addChild(var); + arity++; + } + v++; + } } - getter = newGetter; } } diff --git a/AlgebraicDataflowArchitectureModel/src/generators/CodeGeneratorFromDataFlowGraph.java b/AlgebraicDataflowArchitectureModel/src/generators/CodeGeneratorFromDataFlowGraph.java index 00cc669..beba922 100644 --- a/AlgebraicDataflowArchitectureModel/src/generators/CodeGeneratorFromDataFlowGraph.java +++ b/AlgebraicDataflowArchitectureModel/src/generators/CodeGeneratorFromDataFlowGraph.java @@ -9,6 +9,7 @@ import java.util.Map; import java.util.Map.Entry; import java.util.Set; +import java.util.Stack; import java.util.AbstractMap.SimpleEntry; import code.ast.Block; @@ -59,7 +60,7 @@ List> constructorParams = new ArrayList<>(); List> constructorStatements = new ArrayList<>(); Map> updateStatements = new HashMap<>(); - Map> childGetters = new HashMap<>(); + Map> descendantGetters = new HashMap<>(); // For each components (1st pass). for (Node componentNode: components) { @@ -108,8 +109,8 @@ declareAccessorInMainComponent(mainComponent, resourceNode, stateGetter, langSpec); } if (component != null) { - // Declare the getter methods in this resource to obtain the children resources. - declareChildGetterMethod(resourceNode, component, childGetters, langSpec); + // Declare the getter methods in this resource to obtain the descendant resources. + declareDescendantGetterMethods(resourceNode, component, descendantGetters, langSpec); } } } @@ -143,9 +144,9 @@ // Declare the fields to refer to other resources in the parent/this component, and the state field in the parent component. declareFieldsToReferToOtherResourcesAndStateFieldInParentComponent(resourceNode, component, parentComponent, constructorParams, langSpec); - // Declare the getter method in this resource to obtain the state. + // Declare the getter method to obtain the resource state in an ancestor resource. if (component == null) { - MethodDeclaration stateGetter = declareStateGetterMethodInParent(resourceNode, parentComponent, resStateType, langSpec); + MethodDeclaration stateGetter = declareStateGetterMethodInAncestor(resourceNode, resourceComponents, resStateType, langSpec); if (stateGetter != null) { // Declare the accessor method in the main component to call the getter method. @@ -267,7 +268,7 @@ } } // Replace the type of the state field. - Type fieldType = JavaCodeGenerator.getImplStateType(childRes.getParent()); + Type fieldType = getImplStateType(childRes.getParent(), langSpec); if (exp instanceof Term) { ((Term) exp).setType(fieldType); for (Map.Entry varEnt: ((Term) exp).getVariables().entrySet()) { @@ -634,38 +635,48 @@ return stateGetter; } - private MethodDeclaration declareStateGetterMethodInParent(ResourceNode resourceNode, TypeDeclaration parentComponent, Type resStateType, ILanguageSpecific langSpec) { - // Check duplication. - String getterName = getterPrefix + getComponentName(resourceNode.getResourceHierarchy(), langSpec); - for (MethodDeclaration method: parentComponent.getMethods()) { - if (method.getName().equals(getterName)) return null; - } - - // Declare the getter method of the resource state. + private MethodDeclaration declareStateGetterMethodInAncestor(ResourceNode resourceNode, Map resourceComponents, Type resStateType, ILanguageSpecific langSpec) { + // Search an ancestor in which the getter method is declared. + ResourceNode ancestorNode = resourceNode; + Stack ancestors = new Stack<>(); + do { + ancestors.push(ancestorNode); + ancestorNode = ancestorNode.getParent(); + } while (!generatesComponent(ancestorNode.getResourceHierarchy())); + TypeDeclaration ancestorComponent = resourceComponents.get(ancestorNode.getResourceHierarchy()); List getterParams = new ArrayList<>(); int v = 1; - for (Selector param: resourceNode.getSelectors()) { - if (param.getExpression() instanceof Variable) { - Variable var = (Variable) param.getExpression(); - getterParams.add(new VariableDeclaration(var.getType(), var.getName())); - } else if (param.getExpression() instanceof Term) { - Term var = (Term) param.getExpression(); - getterParams.add(new VariableDeclaration(var.getType(), "v" + v)); + while (ancestors.size() > 0) { + ResourceNode curAncestor = ancestors.pop(); + Expression param = curAncestor.getPrimaryResourcePath().getLastParam(); + if (param instanceof Variable) { + Variable var = (Variable) param; + getterParams.add(langSpec.newVariableDeclaration(var.getType(), var.getName())); + } else if (param instanceof Term) { + Term var = (Term) param; + getterParams.add(langSpec.newVariableDeclaration(var.getType(), "v" + v)); } v++; } + // Check duplication. + String getterName = getterPrefix + getComponentName(resourceNode.getResourceHierarchy(), langSpec); + for (MethodDeclaration method: ancestorComponent.getMethods()) { + if (method.getName().equals(getterName) && method.getParameters().size() == getterParams.size()) return null; + } + + // Declare the getter method of the resource state. MethodDeclaration stateGetter = null; if (getterParams.size() == 0) { - stateGetter = new MethodDeclaration(getterName, resStateType); + stateGetter = langSpec.newMethodDeclaration(getterName, resStateType); } else { - stateGetter = new MethodDeclaration(getterName, false, resStateType, getterParams); + stateGetter = langSpec.newMethodDeclaration(getterName, false, resStateType, getterParams); } - if (parentComponent != null) { - parentComponent.addMethod(stateGetter); + if (ancestorComponent != null) { + ancestorComponent.addMethod(stateGetter); } if (((StoreAttribute) resourceNode.getAttribute()).isStored()) { - fillChildGetterMethod(stateGetter, resourceNode.getResourceHierarchy(), resourceNode.getResourceHierarchy().getParent().getResourceStateType(), langSpec); + fillDescendantGetterMethod(stateGetter, resourceNode.getResourceHierarchy(), ancestorNode.getResourceHierarchy(), ancestorComponent, langSpec); } else { addOtherGetterInvocationsToStateGatter(stateGetter, resourceNode, langSpec); } @@ -728,44 +739,51 @@ } } - private void declareChildGetterMethod(ResourceNode resourceNode, TypeDeclaration component, Map> childGetters, ILanguageSpecific langSpec) { - // Declare the getter methods in this resource to obtain the children resources. - Set children = childGetters.get(resourceNode.getResourceHierarchy()); - if (children == null) { - children = new HashSet<>(); - childGetters.put(resourceNode.getResourceHierarchy(), children); + private void declareDescendantGetterMethods(ResourceNode resourceNode, TypeDeclaration component, Map> descendantGetters, ILanguageSpecific langSpec) { + // Declare the getter methods in this resource to obtain descendant resources. + Set descendants = descendantGetters.get(resourceNode.getResourceHierarchy()); + if (descendants == null) { + descendants = new HashSet<>(); + descendantGetters.put(resourceNode.getResourceHierarchy(), descendants); } for (ResourceNode child: resourceNode.getChildren()) { - if (generatesComponent(child.getResourceHierarchy())) { - // A component for the child is generated. - if (!children.contains(child.getResourceHierarchy())) { - children.add(child.getResourceHierarchy()); - List params = new ArrayList<>(); - int v = 1; - Expression param = child.getPrimaryResourcePath().getLastParam(); - if (param != null) { - if (param instanceof Variable) { - Variable var = (Variable) param; - params.add(langSpec.newVariableDeclaration(var.getType(), var.getName())); - } else if (param instanceof Term) { - Term var = (Term) param; - params.add(langSpec.newVariableDeclaration(var.getType(), "v" + v)); - } - v++; + // 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(langSpec.newVariableDeclaration(var.getType(), var.getName())); + } else if (param instanceof Term) { + Term var = (Term) param; + params.add(langSpec.newVariableDeclaration(var.getType(), "v" + v)); } - String childCompName = getComponentName(child.getResourceHierarchy(), langSpec); - Type childType = new Type(childCompName, childCompName); - MethodDeclaration childGetter = null; - if (params.size() == 0) { - childGetter = langSpec.newMethodDeclaration(getterPrefix + childCompName, childType); - } else { - childGetter = langSpec.newMethodDeclaration(getterPrefix + childCompName, false, childType, params); - } - - fillChildGetterMethod(childGetter, child.getResourceHierarchy(), resourceNode.getResourceStateType(), langSpec); - component.addMethod(childGetter); + 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(), langSpec); + Type descendantType = new Type(descendantCompName, descendantCompName); + MethodDeclaration descendantGetter = null; + if (params.size() == 0) { + descendantGetter = langSpec.newMethodDeclaration(getterPrefix + descendantCompName, descendantType); + } else { + descendantGetter = langSpec.newMethodDeclaration(getterPrefix + descendantCompName, false, descendantType, params); + } + + fillDescendantGetterMethod(descendantGetter, descendant.getResourceHierarchy(), resourceNode.getResourceHierarchy(), component, langSpec); + component.addMethod(descendantGetter); + } + break; + } + childNodes = descendant.getChildren(); + } while (childNodes != null && childNodes.size() == 1 && (descendant = childNodes.iterator().next()) != null); } } @@ -1439,7 +1457,7 @@ ResourcePath ref = rc.getResource(); if (!out.getResource().equals(ref)) { String refVarName = ref.getLeafResourceName(); - Expression refGetter = JavaCodeGenerator.pullAccessor.getDirectStateAccessorFor(ref, null); + Expression refGetter = getPullAccessor().getDirectStateAccessorFor(ref, null); String[] sideEffects = new String[] {""}; String refExp = refGetter.toImplementation(sideEffects); String refTypeName = ref.getResourceStateType().getInterfaceTypeName(); diff --git a/AlgebraicDataflowArchitectureModel/src/generators/JavaCodeGenerator.java b/AlgebraicDataflowArchitectureModel/src/generators/JavaCodeGenerator.java index 8f17c1a..b646911 100644 --- a/AlgebraicDataflowArchitectureModel/src/generators/JavaCodeGenerator.java +++ b/AlgebraicDataflowArchitectureModel/src/generators/JavaCodeGenerator.java @@ -101,14 +101,14 @@ if (generatesComponent(child)) { return new Type("List", "ArrayList<>", "List<" + getComponentName(child) + ">", DataConstraintModel.typeList); } else { - return new Type("List", "ArrayList<>", "List<" + getImplStateType(child).getImplementationTypeName() + ">", DataConstraintModel.typeList); + 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 new Type("Map", "HashMap<>", "Map", DataConstraintModel.typeMap); } } return null; @@ -120,9 +120,11 @@ } public static boolean generatesComponent(ResourceHierarchy res) { - return res.getParent() == null || !(res.getChildren() == null || res.getChildren().size() == 0); -// Type resType = res.getResourceStateType(); -// return DataConstraintModel.typeJson.isAncestorOf(resType) || DataConstraintModel.typeList.isAncestorOf(resType) || DataConstraintModel.typeMap.isAncestorOf(resType); + 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; + return true; +// return res.getParent() == null || !(res.getChildren() == null || res.getChildren().size() == 0); } static public ArrayList doGenerate(DataFlowGraph graph, DataTransferModel model) { @@ -133,7 +135,7 @@ Map> updates = new HashMap<>(); Map> inputs = new HashMap<>(); List> fields = new ArrayList<>(); - Map> childGetters = new HashMap<>(); + Map> descendantGetters = new HashMap<>(); List> constructorParams = new ArrayList<>(); Map> dependedRootComponentGraph = getDependedRootComponentGraph(model); @@ -275,41 +277,48 @@ declareAccessorMethodInMainComponent(resourceNode, mainComponent); } if (component != null) { - // Declare the getter methods to obtain the children resources. - Set children = childGetters.get(resourceNode.getResourceHierarchy()); - if (children == null) { - children = new HashSet<>(); - childGetters.put(resourceNode.getResourceHierarchy(), children); + // Declare the getter methods in this resource to obtain descendant resources. + Set descendants = descendantGetters.get(resourceNode.getResourceHierarchy()); + if (descendants == null) { + descendants = new HashSet<>(); + descendantGetters.put(resourceNode.getResourceHierarchy(), descendants); } for (ResourceNode child: resourceNode.getChildren()) { - if (generatesComponent(child.getResourceHierarchy())) { - // A component for the child is generated. - if (!children.contains(child.getResourceHierarchy())) { - children.add(child.getResourceHierarchy()); - List params = new ArrayList<>(); - int v = 1; - Expression param = child.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++; + // 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)); } - String childCompName = getComponentName(child.getResourceHierarchy()); - Type childType = new Type(childCompName, childCompName); - MethodDeclaration childGetter = null; - if (params.size() == 0) { - childGetter = new MethodDeclaration("get" + childCompName, childType); - } else { - childGetter = new MethodDeclaration("get" + childCompName, false, childType, params); - } - component.addMethod(childGetter); + 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); } } } @@ -354,30 +363,40 @@ } } - // Declare the getter method to obtain the resource state in the parent component. + // Declare the getter method to obtain the resource state in an ancestor component. 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) { - if (entry.getKey() == resourceNode.getParent().getResourceHierarchy() && entry.getValue().getName().equals(getterName)) { + ResourceHierarchy r = entry.getKey(); + MethodDeclaration m = entry.getValue(); + if (r == ancestorNode.getResourceHierarchy() && m.getName().equals(getterName) && m.getParameters().size() == getterParams.size()) { bExists = true; break; } } if (!bExists) { - List getterParams = new ArrayList<>(); - int v = 1; - for (Selector param: resourceNode.getSelectors()) { - if (param.getExpression() instanceof Variable) { - Variable var = (Variable) param.getExpression(); - getterParams.add(new VariableDeclaration(var.getType(), var.getName())); - } else if (param.getExpression() instanceof Term) { - Term var = (Term) param.getExpression(); - getterParams.add(new VariableDeclaration(var.getType(), "v" + v)); - } - v++; - } Type resType = getImplStateType(resourceNode.getResourceHierarchy()); MethodDeclaration stateGetter = null; if (getterParams.size() == 0) { @@ -385,7 +404,7 @@ } else { stateGetter = new MethodDeclaration(getterName, false, resType, getterParams); } - getters.add(new AbstractMap.SimpleEntry<>(resourceNode.getParent().getResourceHierarchy(), stateGetter)); + getters.add(new AbstractMap.SimpleEntry<>(ancestorNode.getResourceHierarchy(), stateGetter)); // Declare the accessor method in the main type to call the getter method. declareAccessorMethodInMainComponent(resourceNode, mainComponent); @@ -1253,6 +1272,7 @@ // iterate from the root resource Term getter = null; int v = 1; + int arity = 2; while (!pathStack.empty()) { curPath = pathStack.pop(); String typeName = getComponentName(curPath.getResourceHierarchy()); @@ -1261,23 +1281,65 @@ String fieldName = toVariableName(typeName); getter = new Field(fieldName, new Type(typeName, typeName)); } else { - Term newGetter = new Term(new Symbol("get" + typeName, -1, Symbol.Type.METHOD)); - newGetter.addChild(getter); - if (curPath.getResourceHierarchy().getNumParameters() > 0) { - Variable var = null; - Expression param = curPath.getLastParam(); - if (param instanceof Variable) { - var = (Variable) param; - } else if (param instanceof Term) { - var = new Variable("v" + v, ((Term) param).getType()); + 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) { + Variable var = null; + Expression param = curPath.getLastParam(); + if (param instanceof Variable) { + var = (Variable) param; + } else if (param instanceof Term) { + var = new Variable("v" + v, ((Term) param).getType()); + } + if (var != null) { + newGetter.addChild(var); + newGetter.getSymbol().setArity(2); + } + v++; + } + getter = newGetter; + } else { + if (curPath.getResourceHierarchy().getNumParameters() > 0) { + Variable var = null; + Expression param = curPath.getLastParam(); + if (param instanceof Variable) { + var = (Variable) param; + } else if (param instanceof Term) { + var = new Variable("v" + v, ((Term) param).getType()); + } + if (var != null) { + getter.getSymbol().setArity(arity); + getter.addChild(var); + } + v++; + } } - if (var != null) { - newGetter.addChild(var); - newGetter.getSymbol().setArity(2); + arity = 2; + } else { + // to get a descendant resource directly. + if (arity == 2) { + Term newGetter = new Term(new Symbol("get" + typeName, -1, Symbol.Type.METHOD)); + newGetter.addChild(getter); + getter = newGetter; } - v++; + if (curPath.getResourceHierarchy().getNumParameters() > 0) { + Variable var = null; + Expression param = curPath.getLastParam(); + if (param instanceof Variable) { + var = (Variable) param; + } else if (param instanceof Term) { + var = new Variable("v" + v, ((Term) param).getType()); + } + if (var != null) { + getter.getSymbol().setArity(arity); + getter.addChild(var); + arity++; + } + v++; + } } - getter = newGetter; } } if (generatesComponent(targetRes.getResourceHierarchy())) { diff --git a/AlgebraicDataflowArchitectureModel/src/generators/JavaMethodBodyGenerator.java b/AlgebraicDataflowArchitectureModel/src/generators/JavaMethodBodyGenerator.java index cbe262c..df180a0 100644 --- a/AlgebraicDataflowArchitectureModel/src/generators/JavaMethodBodyGenerator.java +++ b/AlgebraicDataflowArchitectureModel/src/generators/JavaMethodBodyGenerator.java @@ -575,10 +575,10 @@ } } } + // for source nodes TypeDeclaration mainComponent = componentMap.get(JavaCodeGenerator.mainTypeName); for (ResourceHierarchy resource: model.getResourceHierarchies()) { -// ResourceNode resource = (ResourceNode) n; String resourceName = JavaCodeGenerator.getComponentName(resource); TypeDeclaration component = componentMap.get(resourceName); if (component != null) { @@ -637,36 +637,62 @@ } } - // child getter method + // descendant getter method if (resource.getChildren().size() > 0) { for (ResourceHierarchy child: resource.getChildren()) { - String methodName = "get" + JavaCodeGenerator.getComponentName(child); - MethodDeclaration childGetter = getMethod(component, methodName); - if (childGetter != null && (childGetter.getBody() == null || childGetter.getBody().getStatements().size() == 0)) { - if (DataConstraintModel.typeList.isAncestorOf(resource.getResourceStateType())) { - Term selector = new Term(DataConstraintModel.get); - selector.addChild(new Field("value")); - selector.addChild(new Variable(childGetter.getParameters().get(childGetter.getParameters().size() - 1).getName())); - selector.setType(childGetter.getReturnType()); - String[] sideEffects = new String[] {null}; - String returnValue = selector.toImplementation(sideEffects); - if (sideEffects[0] != null) childGetter.addStatement(sideEffects[0]); - childGetter.addStatement("return " + returnValue + ";"); - } else if (DataConstraintModel.typeMap.isAncestorOf(resource.getResourceStateType())) { - Term selector = new Term(DataConstraintModel.lookup); - selector.addChild(new Field("value")); - selector.addChild(new Variable(childGetter.getParameters().get(childGetter.getParameters().size() - 1).getName())); - selector.setType(childGetter.getReturnType()); - String[] sideEffects = new String[] {null}; - String returnValue = selector.toImplementation(sideEffects); - if (sideEffects[0] != null) childGetter.addStatement(sideEffects[0]); - childGetter.addStatement("return " + returnValue+ ";"); - } else { - String fieldName = JavaCodeGenerator.getComponentName(child); - String returnValue = JavaCodeGenerator.toVariableName(fieldName); - childGetter.addStatement("return this." + returnValue + ";"); - } + 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; + } + } + 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; + params++; + } 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; + params++; + } + 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; + children = descendant.getChildren(); + } while (children != null && children.size() == 1 && (descendant = children.iterator().next()) != null); } } } @@ -930,6 +956,16 @@ return null; } + private static List getGetterMethods(TypeDeclaration component, String resourceName) { + List getters = new ArrayList<>(); + for (MethodDeclaration m: component.getMethods()) { + if (m.getName().startsWith("get" + resourceName)) { + getters.add(m); + } + } + return getters; + } + private static Map> getIOChannelsAndMembers(ResourceHierarchy resource, DataTransferModel model) { Map> ioChannelsAndMembers = new HashMap<>(); for (Channel c: model.getInputChannels()) { diff --git a/AlgebraicDataflowArchitectureModel/src/generators/JerseyCodeGenerator.java b/AlgebraicDataflowArchitectureModel/src/generators/JerseyCodeGenerator.java index 5ced72d..0dc0551 100644 --- a/AlgebraicDataflowArchitectureModel/src/generators/JerseyCodeGenerator.java +++ b/AlgebraicDataflowArchitectureModel/src/generators/JerseyCodeGenerator.java @@ -102,14 +102,14 @@ if (generatesComponent(child)) { return new Type("List", "ArrayList<>", "List<" + getComponentName(child) + ">", DataConstraintModel.typeList); } else { - return new Type("List", "ArrayList<>", "List<" + getImplStateType(child).getImplementationTypeName() + ">", DataConstraintModel.typeList); + 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 new Type("Map", "HashMap<>", "Map", DataConstraintModel.typeMap); } } return null; @@ -121,9 +121,11 @@ } public static boolean generatesComponent(ResourceHierarchy res) { - return res.getParent() == null || !(res.getChildren() == null || res.getChildren().size() == 0); -// Type resType = res.getResourceStateType(); -// return DataConstraintModel.typeJson.isAncestorOf(resType) || DataConstraintModel.typeList.isAncestorOf(resType) || DataConstraintModel.typeMap.isAncestorOf(resType); + 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; + return true; +// return res.getParent() == null || !(res.getChildren() == null || res.getChildren().size() == 0); } static public ArrayList doGenerate(DataFlowGraph graph, DataTransferModel model) { @@ -136,7 +138,7 @@ Map> updates = new HashMap<>(); Map> inputs = new HashMap<>(); List> fields = new ArrayList<>(); - Map> childGetters = new HashMap<>(); + Map> descendantGetters = new HashMap<>(); Map getterAccessors = new HashMap<>(); Map inputAccessors = new HashMap<>(); Map> constructorParams = new HashMap<>(); @@ -221,41 +223,48 @@ component.addMethod(stateGetter); } if (component != null) { - // Declare the getter methods to obtain the children resources. - Set children = childGetters.get(resourceNode.getResourceHierarchy()); - if (children == null) { - children = new HashSet<>(); - childGetters.put(resourceNode.getResourceHierarchy(), children); + // Declare the getter methods in this resource to obtain descendant resources. + Set descendants = descendantGetters.get(resourceNode.getResourceHierarchy()); + if (descendants == null) { + descendants = new HashSet<>(); + descendantGetters.put(resourceNode.getResourceHierarchy(), descendants); } for (ResourceNode child: resourceNode.getChildren()) { - if (generatesComponent(child.getResourceHierarchy())) { - // The child generates a component. - if (!children.contains(child.getResourceHierarchy())) { - children.add(child.getResourceHierarchy()); - List pathParams = new ArrayList<>(); - int v = 1; - Expression pathParam = child.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++; + // 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)); } - String childCompName = getComponentName(child.getResourceHierarchy()); - Type childType = new Type(childCompName, childCompName); - MethodDeclaration childGetter = null; - if (pathParams.size() == 0) { - childGetter = new MethodDeclaration("get" + childCompName, childType); - } else { - childGetter = new MethodDeclaration("get" + childCompName, false, childType, pathParams); - } - component.addMethod(childGetter); + 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); } } @@ -380,30 +389,40 @@ } } - // Declare the getter method to obtain the resource state in the parent component. + // Declare the getter method to obtain the resource state in an ancestor component. 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) { - if (entry.getKey() == resourceNode.getParent().getResourceHierarchy() && entry.getValue().getName().equals(getterName)) { + ResourceHierarchy r = entry.getKey(); + MethodDeclaration m = entry.getValue(); + if (r == ancestorNode.getResourceHierarchy() && m.getName().equals(getterName) && m.getParameters().size() == pathParams.size()) { bExists = true; break; } } if (!bExists) { - List pathParams = new ArrayList<>(); - int v = 1; - for (Selector pathParam: resourceNode.getSelectors()) { - if (pathParam.getExpression() instanceof Variable) { - Variable var = (Variable) pathParam.getExpression(); - pathParams.add(new VariableDeclaration(var.getType(), var.getName())); - } else if (pathParam.getExpression() instanceof Term) { - Term var = (Term) pathParam.getExpression(); - pathParams.add(new VariableDeclaration(var.getType(), "v" + v)); - } - v++; - } Type resType = getImplStateType(resourceNode.getResourceHierarchy()); MethodDeclaration stateGetter = null; if (pathParams.size() == 0) { @@ -411,7 +430,7 @@ } else { stateGetter = new MethodDeclaration(getterName, false, resType, pathParams); } - getters.add(new AbstractMap.SimpleEntry<>(resourceNode.getParent().getResourceHierarchy(), stateGetter)); + getters.add(new AbstractMap.SimpleEntry<>(ancestorNode.getResourceHierarchy(), stateGetter)); } } @@ -1288,6 +1307,7 @@ // iterate from the `from' resource Term getter = null; int v = 1; + int arity = 2; while (!pathStack.empty()) { curPath = pathStack.pop(); String typeName = getComponentName(curPath.getResourceHierarchy()); @@ -1296,23 +1316,65 @@ String fieldName = toVariableName(typeName); getter = new Field(fieldName, new Type(typeName, typeName)); } else { - Term newGetter = new Term(new Symbol("get" + typeName, -1, Symbol.Type.METHOD)); - newGetter.addChild(getter); - if (curPath.getResourceHierarchy().getNumParameters() > 0) { - Variable var = null; - Expression param = curPath.getLastParam(); - if (param instanceof Variable) { - var = (Variable) param; - } else if (param instanceof Term) { - var = new Variable("v" + v, ((Term) param).getType()); + 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) { + Variable var = null; + Expression param = curPath.getLastParam(); + if (param instanceof Variable) { + var = (Variable) param; + } else if (param instanceof Term) { + var = new Variable("v" + v, ((Term) param).getType()); + } + if (var != null) { + newGetter.addChild(var); + newGetter.getSymbol().setArity(2); + } + v++; + } + getter = newGetter; + } else { + if (curPath.getResourceHierarchy().getNumParameters() > 0) { + Variable var = null; + Expression param = curPath.getLastParam(); + if (param instanceof Variable) { + var = (Variable) param; + } else if (param instanceof Term) { + var = new Variable("v" + v, ((Term) param).getType()); + } + if (var != null) { + getter.getSymbol().setArity(arity); + getter.addChild(var); + } + v++; + } } - if (var != null) { - newGetter.addChild(var); - newGetter.getSymbol().setArity(2); + arity = 2; + } else { + // to get a descendant resource directly. + if (arity == 2) { + Term newGetter = new Term(new Symbol("get" + typeName, -1, Symbol.Type.METHOD)); + newGetter.addChild(getter); + getter = newGetter; } - v++; + if (curPath.getResourceHierarchy().getNumParameters() > 0) { + Variable var = null; + Expression param = curPath.getLastParam(); + if (param instanceof Variable) { + var = (Variable) param; + } else if (param instanceof Term) { + var = new Variable("v" + v, ((Term) param).getType()); + } + if (var != null) { + getter.getSymbol().setArity(arity); + getter.addChild(var); + arity++; + } + v++; + } } - getter = newGetter; } } diff --git a/AlgebraicDataflowArchitectureModel/src/generators/JerseyMethodBodyGenerator.java b/AlgebraicDataflowArchitectureModel/src/generators/JerseyMethodBodyGenerator.java index a77cca1..d476588 100644 --- a/AlgebraicDataflowArchitectureModel/src/generators/JerseyMethodBodyGenerator.java +++ b/AlgebraicDataflowArchitectureModel/src/generators/JerseyMethodBodyGenerator.java @@ -700,6 +700,7 @@ } } } + // for source nodes for (ResourceHierarchy resource: model.getResourceHierarchies()) { String resourceName = JerseyCodeGenerator.getComponentName(resource); @@ -760,36 +761,62 @@ } } - // child getter method + // descendant getter method if (resource.getChildren().size() > 0) { for (ResourceHierarchy child: resource.getChildren()) { - String methodName = "get" + JerseyCodeGenerator.getComponentName(child); - MethodDeclaration childGetter = getMethod(component, methodName); - if (childGetter != null && (childGetter.getBody() == null || childGetter.getBody().getStatements().size() == 0)) { - if (DataConstraintModel.typeList.isAncestorOf(resource.getResourceStateType())) { - Term selector = new Term(DataConstraintModel.get); - selector.addChild(new Field("value")); - selector.addChild(new Variable(childGetter.getParameters().get(childGetter.getParameters().size() - 1).getName())); - selector.setType(childGetter.getReturnType()); - String[] sideEffects = new String[] {null}; - String returnValue = selector.toImplementation(sideEffects); - if (sideEffects[0] != null) childGetter.addStatement(sideEffects[0]); - childGetter.addStatement("return " + returnValue + ";"); - } else if (DataConstraintModel.typeMap.isAncestorOf(resource.getResourceStateType())) { - Term selector = new Term(DataConstraintModel.lookup); - selector.addChild(new Field("value")); - selector.addChild(new Variable(childGetter.getParameters().get(childGetter.getParameters().size() - 1).getName())); - selector.setType(childGetter.getReturnType()); - String[] sideEffects = new String[] {null}; - String returnValue = selector.toImplementation(sideEffects); - if (sideEffects[0] != null) childGetter.addStatement(sideEffects[0]); - childGetter.addStatement("return " + returnValue+ ";"); - } else { - String fieldName = JerseyCodeGenerator.getComponentName(child); - String returnValue = JerseyCodeGenerator.toVariableName(fieldName); - childGetter.addStatement("return this." + returnValue + ";"); - } + 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; + } + } + 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; + params++; + } 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; + params++; + } + 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; + children = descendant.getChildren(); + } while (children != null && children.size() == 1 && (descendant = children.iterator().next()) != null); } } } @@ -1209,13 +1236,6 @@ return null; } - 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 getUpdateMethods(TypeDeclaration component, String resName) { List updates = new ArrayList<>(); for (MethodDeclaration m: component.getMethods()) { @@ -1232,6 +1252,23 @@ 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().startsWith("get" + resourceName)) { + getters.add(m); + } + } + return getters; + } + private static Map> getIOChannelsAndMembers(ResourceHierarchy resource, DataTransferModel model) { Map> ioChannelsAndMembers = new HashMap<>(); for (Channel c: model.getInputChannels()) { diff --git a/AlgebraicDataflowArchitectureModel/src/models/dataFlowModel/ResourceNode.java b/AlgebraicDataflowArchitectureModel/src/models/dataFlowModel/ResourceNode.java index 6c2073c..d382534 100644 --- a/AlgebraicDataflowArchitectureModel/src/models/dataFlowModel/ResourceNode.java +++ b/AlgebraicDataflowArchitectureModel/src/models/dataFlowModel/ResourceNode.java @@ -160,6 +160,10 @@ return selectors; } + public Selector getLastSelector() { + return selectors.get(resourceHierarchy.getTotalNumParameters() - 1); + } + public List getAllSelectors() { List selectors = new ArrayList<>(); if (parent != null) {