diff --git a/AlgebraicDataflowArchitectureModel/src/generators/CodeGenerator.java b/AlgebraicDataflowArchitectureModel/src/generators/CodeGenerator.java index 015baa7..f4a867b 100644 --- a/AlgebraicDataflowArchitectureModel/src/generators/CodeGenerator.java +++ b/AlgebraicDataflowArchitectureModel/src/generators/CodeGenerator.java @@ -50,8 +50,9 @@ */ public abstract class CodeGenerator { public static final String fieldOfResourceState = "value"; + public static final String methoNameOfResourceState = "Value"; public static final String getterPrefix = "get"; - public static final String getterOfResourceState = "getValue"; + public static final String getterOfResourceState = getterPrefix + methoNameOfResourceState; // "getValue" public static final String updateMethodPrefix = "update"; public static final String from = "From"; public static final String _for = "For"; @@ -408,7 +409,7 @@ } } - protected void declareAccessorInMainComponent(TypeDeclaration mainComponent, ResourceNode accessRes, MethodDeclaration stateGetter, ILanguageSpecific langSpec) { + protected void declareAccessorInMainComponent(TypeDeclaration mainComponent, ResourceNode accessRes, MethodDeclaration stateGetter, IPlatformSpecific platformSpec, ILanguageSpecific langSpec) { List mainGetterParams = new ArrayList<>(); int v = 1; for (Expression param: accessRes.getPrimaryResourcePath().getPathParams()) { @@ -428,7 +429,7 @@ accessor = langSpec.newMethodDeclaration(getterPrefix + getComponentName(accessRes.getResourceHierarchy(), langSpec), false, getImplStateType(accessRes.getResourceHierarchy(), langSpec), mainGetterParams); } Block block = new Block(); - Expression getState = getPullAccessor().getDirectStateAccessorFor(accessRes.getPrimaryResourcePath(), null); + Expression getState = getPullAccessor(platformSpec).getDirectStateAccessorFor(accessRes.getPrimaryResourcePath(), null); block.addStatement(langSpec.getReturnStatement(getState.toImplementation(new String[] {null})) + langSpec.getStatementDelimiter()); // if (stateGetter.getParameters() == null || stateGetter.getParameters().size() == 0) { // block.addStatement(langSpec.getReturnStatement(langSpec.getMethodInvocation(accessRes.getResourceName(), stateGetter.getName())) + langSpec.getStatementDelimiter()); @@ -513,244 +514,440 @@ return null; } - protected IResourceStateAccessor getPushAccessor() { - return 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(fieldOfResourceState, + protected IResourceStateAccessor getPushAccessor(IPlatformSpecific platformSpec) { + if (platformSpec.isMonolithic()) { + return 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(fieldOfResourceState, + targetRes.getResourceStateType() != null ? targetRes.getResourceStateType() + : DataConstraintModel.typeInt); + } + // use the cached value as the current state + return new Field(langSpec.toVariableName(getComponentName(targetRes.getResourceHierarchy(), langSpec)), targetRes.getResourceStateType() != null ? targetRes.getResourceStateType() : DataConstraintModel.typeInt); } - // use the cached value as the current state - return new Field(langSpec.toVariableName(getComponentName(targetRes.getResourceHierarchy(), langSpec)), - targetRes.getResourceStateType() != null ? targetRes.getResourceStateType() - : DataConstraintModel.typeInt); - } - - @Override - public Expression getNextStateAccessorFor(ChannelMember target, ChannelMember from) { - ResourcePath targetRes= target.getResource(); - return new Parameter(langSpec.toVariableName(getComponentName(targetRes.getResourceHierarchy(), langSpec)), - targetRes.getResourceStateType() != null ? targetRes.getResourceStateType() - : DataConstraintModel.typeInt); - } - - @Override - public Expression getDirectStateAccessorFor(ResourcePath targetRes, ResourcePath fromRes) { - if (fromRes != null && targetRes.equals(fromRes)) { - return new Field(fieldOfResourceState, + + @Override + public Expression getNextStateAccessorFor(ChannelMember target, ChannelMember from) { + ResourcePath targetRes= target.getResource(); + return new Parameter(langSpec.toVariableName(getComponentName(targetRes.getResourceHierarchy(), langSpec)), targetRes.getResourceStateType() != null ? targetRes.getResourceStateType() : DataConstraintModel.typeInt); } - // for reference channel member - return new Parameter(langSpec.toVariableName(getComponentName(targetRes.getResourceHierarchy(), langSpec)), - targetRes.getResourceStateType() != null ? targetRes.getResourceStateType() - : DataConstraintModel.typeInt); - } - }; + + @Override + public Expression getDirectStateAccessorFor(ResourcePath targetRes, ResourcePath fromRes) { + if (fromRes != null && targetRes.equals(fromRes)) { + return new Field(fieldOfResourceState, + targetRes.getResourceStateType() != null ? targetRes.getResourceStateType() + : DataConstraintModel.typeInt); + } + // for reference channel member + return new Parameter(langSpec.toVariableName(getComponentName(targetRes.getResourceHierarchy(), langSpec)), + targetRes.getResourceStateType() != null ? targetRes.getResourceStateType() + : DataConstraintModel.typeInt); + } + }; + } else { + return 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(fieldOfResourceState, + targetRes.getResourceStateType() != null ? targetRes.getResourceStateType() + : DataConstraintModel.typeInt); + } + // use the cached value as the current state + return new Field(langSpec.toVariableName(getComponentName(targetRes.getResourceHierarchy(), langSpec)), + targetRes.getResourceStateType() != null ? targetRes.getResourceStateType() + : DataConstraintModel.typeInt); + } + + @Override + public Expression getNextStateAccessorFor(ChannelMember target, ChannelMember from) { + ResourcePath targetRes = target.getResource(); + return new Parameter(langSpec.toVariableName(getComponentName(targetRes.getResourceHierarchy(), langSpec)), + targetRes.getResourceStateType() != null ? targetRes.getResourceStateType() + : DataConstraintModel.typeInt); + } + + @Override + public Expression getDirectStateAccessorFor(ResourcePath targetRes, ResourcePath fromRes) { + if (fromRes != null && targetRes.equals(fromRes)) { + return new Field(fieldOfResourceState, + targetRes.getResourceStateType() != null ? targetRes.getResourceStateType() + : DataConstraintModel.typeInt); + } + return null; + } + }; + } } - protected IResourceStateAccessor getPullAccessor() { - return 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(), langSpec); - if (generatesComponent(targetRes.getResourceHierarchy())) { - getter = new Term(new Symbol(getterOfResourceState, 1, Symbol.Type.METHOD)); - getter.addChild(new Field(langSpec.toVariableName(targetComponentName), targetRes.getResourceStateType())); + protected IResourceStateAccessor getPullAccessor(IPlatformSpecific platformSpec) { + if (platformSpec.isMonolithic()) { + return 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(), langSpec); + if (generatesComponent(targetRes.getResourceHierarchy())) { + getter = new Term(new Symbol(getterOfResourceState, 1, Symbol.Type.METHOD)); + getter.addChild(new Field(langSpec.toVariableName(targetComponentName), targetRes.getResourceStateType())); + } else { + String parentName = langSpec.toVariableName(getComponentName(targetRes.getResourceHierarchy().getParent(), langSpec)); + Type parentType = targetRes.getResourceHierarchy().getParent().getResourceStateType(); + getter = new Term(new Symbol(getterPrefix + targetComponentName, 1, Symbol.Type.METHOD)); + getter.addChild(new Field(parentName, parentType)); + } + return getter; } else { - String parentName = langSpec.toVariableName(getComponentName(targetRes.getResourceHierarchy().getParent(), langSpec)); - Type parentType = targetRes.getResourceHierarchy().getParent().getResourceStateType(); - getter = new Term(new Symbol(getterPrefix + targetComponentName, 1, Symbol.Type.METHOD)); - getter.addChild(new Field(parentName, parentType)); + 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); + } + Term getter = null; + String targetComponentName = getComponentName(targetRes.getResourceHierarchy(), langSpec); + if (generatesComponent(targetRes.getResourceHierarchy())) { + getter = new Term(new Symbol(getterOfResourceState, 1, Symbol.Type.METHOD)); + getter.addChild(new Field(langSpec.toVariableName(targetComponentName), targetRes.getResourceStateType())); + } else { + String parentName = langSpec.toVariableName(getComponentName(targetRes.getResourceHierarchy().getParent(), langSpec)); + Type parentType = targetRes.getResourceHierarchy().getParent().getResourceStateType(); + getter = new Term(new Symbol(getterPrefix + 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(fieldOfResourceState, + 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(getterOfResourceState, 1, Symbol.Type.METHOD)); + getter.addChild(new Field(langSpec.toVariableName(getComponentName(targetRes.getResourceHierarchy(), langSpec)), targetRes.getResourceStateType())); + return getter; + } else { + return new Field(langSpec.toVariableName(getComponentName(targetRes.getResourceHierarchy(), langSpec)), 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(), langSpec); + if (getter == null && generatesComponent(curPath.getResourceHierarchy())) { + // root resource + String fieldName = langSpec.toVariableName(typeName); + getter = new Field(fieldName, new Type(typeName, typeName)); + } else { + 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) { + 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(getterPrefix + 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(getterPrefix + 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(getterOfResourceState, 1, Symbol.Type.METHOD)); + newGetter.addChild(getter); + getter = newGetter; } return getter; - } else { - return getDirectStateAccessorFor(targetRes, null); } - } + }; + } else { + return 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(langSpec.toVariableName(getComponentName(targetRes.getResourceHierarchy(), langSpec)), + targetRes.getResourceStateType() != null ? targetRes.getResourceStateType() + : DataConstraintModel.typeInt); + } - @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); + @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); + } } - Term getter = null; - String targetComponentName = getComponentName(targetRes.getResourceHierarchy(), langSpec); - if (generatesComponent(targetRes.getResourceHierarchy())) { - getter = new Term(new Symbol(getterOfResourceState, 1, Symbol.Type.METHOD)); - getter.addChild(new Field(langSpec.toVariableName(targetComponentName), targetRes.getResourceStateType())); - } else { - String parentName = langSpec.toVariableName(getComponentName(targetRes.getResourceHierarchy().getParent(), langSpec)); - Type parentType = targetRes.getResourceHierarchy().getParent().getResourceStateType(); - getter = new Term(new Symbol(getterPrefix + targetComponentName, 1, Symbol.Type.METHOD)); - getter.addChild(new Field(parentName, parentType)); - } - return getter; - } else { - return getDirectStateAccessorFor(targetRes, null); + return new Parameter(langSpec.toVariableName(getComponentName(targetRes.getResourceHierarchy(), langSpec)), + targetRes.getResourceStateType() != null ? targetRes.getResourceStateType() + : DataConstraintModel.typeInt); } - } - - @Override - public Expression getDirectStateAccessorFor(ResourcePath targetRes, ResourcePath fromRes) { - if (fromRes != null) { + + @Override + public Expression getDirectStateAccessorFor(ResourcePath targetRes, ResourcePath fromRes) { + if (fromRes != null && !fromRes.getResourceHierarchy().isAncestorOf(targetRes.getResourceHierarchy())) { + if (targetRes.equals(fromRes)) { + return new Field(fieldOfResourceState, + targetRes.getResourceStateType() != null ? targetRes.getResourceStateType() + : DataConstraintModel.typeInt); + } + // for reference channel member + return new Parameter(langSpec.toVariableName(getComponentName(targetRes.getResourceHierarchy(), langSpec)), + 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(), langSpec); + if (getter == null && fromRes == null) { + // root resource + String fieldName = langSpec.toVariableName(typeName); + getter = new Field(fieldName, new Type(typeName, typeName)); + } else { + 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) { + 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(getterPrefix + 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(getterPrefix + 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(getterOfResourceState, 1, Symbol.Type.METHOD)); + newGetter.addChild(getter); + getter = newGetter; + } + return getter; + } + } + }; + } + } + + protected IResourceStateAccessor getRefAccessor(IPlatformSpecific platformSpec) { + if (platformSpec.isMonolithic()) { + return 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(fieldOfResourceState, + targetRes.getResourceStateType() != null ? targetRes.getResourceStateType() + : DataConstraintModel.typeInt); + } + // use the cached value as the current state + return new Parameter(langSpec.toVariableName(getComponentName(targetRes.getResourceHierarchy(), langSpec)), + targetRes.getResourceStateType() != null ? targetRes.getResourceStateType() + : DataConstraintModel.typeInt); + } + + @Override + public Expression getNextStateAccessorFor(ChannelMember target, ChannelMember from) { + ResourcePath targetRes= target.getResource(); + return new Parameter(langSpec.toVariableName(getComponentName(targetRes.getResourceHierarchy(), langSpec)), + targetRes.getResourceStateType() != null ? targetRes.getResourceStateType() + : DataConstraintModel.typeInt); + } + + @Override + public Expression getDirectStateAccessorFor(ResourcePath targetRes, ResourcePath fromRes) { + if (fromRes != null && targetRes.equals(fromRes)) { + return new Field(fieldOfResourceState, + targetRes.getResourceStateType() != null ? targetRes.getResourceStateType() + : DataConstraintModel.typeInt); + } + // for reference channel member + return new Parameter(langSpec.toVariableName(getComponentName(targetRes.getResourceHierarchy(), langSpec)), + targetRes.getResourceStateType() != null ? targetRes.getResourceStateType() + : DataConstraintModel.typeInt); + } + }; + } else { + return 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(fieldOfResourceState, 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(getterOfResourceState, 1, Symbol.Type.METHOD)); - getter.addChild(new Field(langSpec.toVariableName(getComponentName(targetRes.getResourceHierarchy(), langSpec)), targetRes.getResourceStateType())); - return getter; - } else { - return new Field(langSpec.toVariableName(getComponentName(targetRes.getResourceHierarchy(), langSpec)), 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(), langSpec); - if (getter == null && generatesComponent(curPath.getResourceHierarchy())) { - // root resource - String fieldName = langSpec.toVariableName(typeName); - getter = new Field(fieldName, new Type(typeName, typeName)); - } else { - 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) { - 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(getterPrefix + 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(getterOfResourceState, 1, Symbol.Type.METHOD)); - newGetter.addChild(getter); - getter = newGetter; - } - return getter; - } - }; - } - - protected IResourceStateAccessor getRefAccessor() { - return 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(fieldOfResourceState, + return new Parameter(langSpec.toVariableName(getComponentName(targetRes.getResourceHierarchy(), langSpec)), targetRes.getResourceStateType() != null ? targetRes.getResourceStateType() : DataConstraintModel.typeInt); } - // use the cached value as the current state - return new Parameter(langSpec.toVariableName(getComponentName(targetRes.getResourceHierarchy(), langSpec)), - targetRes.getResourceStateType() != null ? targetRes.getResourceStateType() - : DataConstraintModel.typeInt); - } - @Override - public Expression getNextStateAccessorFor(ChannelMember target, ChannelMember from) { - ResourcePath targetRes= target.getResource(); - return new Parameter(langSpec.toVariableName(getComponentName(targetRes.getResourceHierarchy(), langSpec)), - targetRes.getResourceStateType() != null ? targetRes.getResourceStateType() - : DataConstraintModel.typeInt); - } - - @Override - public Expression getDirectStateAccessorFor(ResourcePath targetRes, ResourcePath fromRes) { - if (fromRes != null && targetRes.equals(fromRes)) { - return new Field(fieldOfResourceState, + @Override + public Expression getNextStateAccessorFor(ChannelMember target, ChannelMember from) { + ResourcePath targetRes = target.getResource(); + return new Parameter(langSpec.toVariableName(getComponentName(targetRes.getResourceHierarchy(), langSpec)), targetRes.getResourceStateType() != null ? targetRes.getResourceStateType() : DataConstraintModel.typeInt); } - // for reference channel member - return new Parameter(langSpec.toVariableName(getComponentName(targetRes.getResourceHierarchy(), langSpec)), - targetRes.getResourceStateType() != null ? targetRes.getResourceStateType() - : DataConstraintModel.typeInt); - } - }; + + @Override + public Expression getDirectStateAccessorFor(ResourcePath targetRes, ResourcePath fromRes) { + if (fromRes != null && targetRes.equals(fromRes)) { + return new Field(fieldOfResourceState, + targetRes.getResourceStateType() != null ? targetRes.getResourceStateType() + : DataConstraintModel.typeInt); + } + return null; + } + }; + } } } diff --git a/AlgebraicDataflowArchitectureModel/src/generators/CodeGeneratorFromDataFlowGraph.java b/AlgebraicDataflowArchitectureModel/src/generators/CodeGeneratorFromDataFlowGraph.java index 59930d9..16d2bff 100644 --- a/AlgebraicDataflowArchitectureModel/src/generators/CodeGeneratorFromDataFlowGraph.java +++ b/AlgebraicDataflowArchitectureModel/src/generators/CodeGeneratorFromDataFlowGraph.java @@ -65,6 +65,7 @@ List> constructorStatements = new ArrayList<>(); Map>> updateStatements = new HashMap<>(); Map> descendantGetters = new HashMap<>(); + Map getterAccessors = new HashMap<>(); TypeDeclaration mainComponent = null; MethodDeclaration mainConstructor = null; @@ -136,7 +137,7 @@ // Declare the accessor method in the main component to call the getter method. if (platformSpec.hasMain()) { - declareAccessorInMainComponent(mainComponent, resourceNode, stateGetter, langSpec); + declareAccessorInMainComponent(mainComponent, resourceNode, stateGetter, platformSpec, langSpec); } } if (component != null) { @@ -161,7 +162,7 @@ } // Declare cache fields and update methods in this resource. - Map.Entry, Map>>> initStatementsAndUpdateUpdates = declareCacheFieldsAndUpdateMethods(resourceNode, component, parentComponent, langSpec); + Map.Entry, Map>>> initStatementsAndUpdateUpdates = declareCacheFieldsAndUpdateMethods(resourceNode, component, parentComponent, platformSpec, langSpec); if (component == null) { // Constructor statements were not added to any component because no component had been generated. for (String statement: initStatementsAndUpdateUpdates.getKey()) { @@ -177,14 +178,19 @@ // (#2) Declare the getter method to obtain the resource state in an ancestor resource. (complementary to #1) if (component == null) { - MethodDeclaration stateGetter = declareStateGetterMethodInAncestor(resourceNode, resourceComponents, resStateType, langSpec); + MethodDeclaration stateGetter = declareStateGetterMethodInAncestor(resourceNode, resourceComponents, resStateType, platformSpec, langSpec); if (stateGetter != null && platformSpec.hasMain()) { // Declare the accessor method in the main component to call the getter method. - declareAccessorInMainComponent(mainComponent, resourceNode, stateGetter, langSpec); + declareAccessorInMainComponent(mainComponent, resourceNode, stateGetter, platformSpec, langSpec); } } + if (!platformSpec.isMonolithic()) { + // Declare the getter accessor in the root resource. + declareGetterAccessorInTheRootResource(resourceNode, getterAccessors, platformSpec, langSpec); + } + // Declare input methods in this component and the main component. Map.Entry, Map>>> initStatementsAndInputUpdates = declareInputMethodsInThisAndMainComponents(resourceNode, component, parentComponent, mainComponent, model, platformSpec, langSpec); if (component == null) { @@ -514,12 +520,17 @@ DataTransferChannel ch = chNode.getChannel(); // Check if the destination resource is outside of the channel scope. boolean outsideOutputResource = false; + ChannelMember out = null; for (ChannelMember cm: ch.getOutputChannelMembers()) { - if (((ResourceNode) chToRes.getDestination()).getInSideResources().contains(cm.getResource()) && cm.isOutside()) { - outsideOutputResource = true; // Regarded as push transfer. - break; + if (((ResourceNode) chToRes.getDestination()).getInSideResources().contains(cm.getResource())) { + out = cm; + if (cm.isOutside()) { + outsideOutputResource = true; // Regarded as push transfer. + break; + } } } + ResourcePath dstResPath = 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. @@ -535,33 +546,44 @@ String dstResName = getComponentName(dstRes, langSpec); FieldDeclaration refFieldForPush = langSpec.newFieldDeclaration(new Type(dstResName, dstResName), langSpec.toVariableName(dstResName)); VariableDeclaration refVarForPush = langSpec.newVariableDeclaration(new Type(dstResName, dstResName), langSpec.toVariableName(dstResName)); - if (component != null) { - // A component is created for this resource. - if (resourceNode.getResourceHierarchy() != dstRes) { - component.addField(refFieldForPush); - if (!outsideOutputResource) { - Map nameToParam = constructorParams.get(resourceNode.getResourceHierarchy()); - if (nameToParam == null) { - nameToParam = new HashMap<>(); - constructorParams.put(resourceNode.getResourceHierarchy(), nameToParam); - } - if (nameToParam.get(dstResName) == null) { - nameToParam.put(dstResName, refVarForPush); - } - } + if (!platformSpec.isMonolithic() + && (outsideOutputResource || (resourceNode.getOutSideResource(ch).getCommonPrefix(dstResPath) == null && platformSpec.isDifferentTreesAsDifferentServices()))) { + // Inter-service (for REST API) + if (!bDeclareClientField) { + // Declare a client field to connect to the destination resource of push transfer. + platformSpec.addClientFieldDeclaration(parentComponent); + bDeclareClientField = true; } } else { - // No component is created for this resource. - if (resourceNode.getParent().getResourceHierarchy() != dstRes) { - parentComponent.addField(refFieldForPush); - if (!outsideOutputResource) { - Map nameToParam = constructorParams.get(resourceNode.getParent().getResourceHierarchy()); - if (nameToParam == null) { - nameToParam = new HashMap<>(); - constructorParams.put(resourceNode.getParent().getResourceHierarchy(), nameToParam); + // Monolithic or Inner-service (for REST API) + if (component != null) { + // A component is created for this resource. + if (resourceNode.getResourceHierarchy() != dstRes) { + component.addField(refFieldForPush); + if (!outsideOutputResource) { + Map nameToParam = constructorParams.get(resourceNode.getResourceHierarchy()); + if (nameToParam == null) { + nameToParam = new HashMap<>(); + constructorParams.put(resourceNode.getResourceHierarchy(), nameToParam); + } + if (nameToParam.get(dstResName) == null) { + nameToParam.put(dstResName, refVarForPush); + } } - if (nameToParam.get(dstResName) == null) { - nameToParam.put(dstResName, refVarForPush); + } + } else { + // No component is created for this resource. + if (resourceNode.getParent().getResourceHierarchy() != dstRes) { + parentComponent.addField(refFieldForPush); + if (!outsideOutputResource) { + Map nameToParam = constructorParams.get(resourceNode.getParent().getResourceHierarchy()); + if (nameToParam == null) { + nameToParam = new HashMap<>(); + constructorParams.put(resourceNode.getParent().getResourceHierarchy(), nameToParam); + } + if (nameToParam.get(dstResName) == null) { + nameToParam.put(dstResName, refVarForPush); + } } } } @@ -617,13 +639,6 @@ } } } - if (!platformSpec.isMonolithic()) { - if (!bDeclareClientField) { - // Declare a client field to connect to the destination resource of push transfer. - platformSpec.addClientFieldDeclaration(parentComponent); - bDeclareClientField = true; - } - } } } } @@ -804,7 +819,8 @@ } - private MethodDeclaration declareStateGetterMethod(ResourceNode resourceNode, TypeDeclaration component, Type resStateType, IPlatformSpecific platformSpec, ILanguageSpecific langSpec) { + private MethodDeclaration declareStateGetterMethod(ResourceNode resourceNode, TypeDeclaration component, Type resStateType, + IPlatformSpecific platformSpec, ILanguageSpecific langSpec) { // Declare the getter method of the resource state. MethodDeclaration stateGetter = langSpec.newMethodDeclaration(getterOfResourceState, resStateType); if (!platformSpec.isMonolithic() && resourceNode.getResourceHierarchy().getParent() == null) { @@ -818,13 +834,14 @@ fillStateGetterMethod(stateGetter, resourceNode.getResourceHierarchy(), resStateType, langSpec); } else { // invocations to other getter methods when at least one incoming data-flow edges is PULL-style. - addOtherGetterInvocationsToStateGatter(stateGetter, resourceNode, langSpec); + addOtherGetterInvocationsToStateGatter(stateGetter, resourceNode, platformSpec, langSpec); } return stateGetter; } - private MethodDeclaration declareStateGetterMethodInAncestor(ResourceNode resourceNode, Map resourceComponents, Type resStateType, ILanguageSpecific langSpec) { + private MethodDeclaration declareStateGetterMethodInAncestor(ResourceNode resourceNode, Map resourceComponents, Type resStateType, + IPlatformSpecific platformSpec, ILanguageSpecific langSpec) { // Search an ancestor in which the getter method is declared. ResourceNode ancestorNode = resourceNode; ResourceNode childNode = null; @@ -871,7 +888,7 @@ if (((StoreAttribute) resourceNode.getAttribute()).isStored() && !hasDescendantIn) { fillDescendantGetterMethod(stateGetter, resourceNode.getResourceHierarchy(), childNode.getResourceHierarchy(), ancestorNode.getResourceHierarchy(), ancestorComponent, langSpec); } else { - addOtherGetterInvocationsToStateGatter(stateGetter, resourceNode, langSpec); + addOtherGetterInvocationsToStateGatter(stateGetter, resourceNode, platformSpec, langSpec); } return stateGetter; @@ -893,7 +910,7 @@ } private void addOtherGetterInvocationsToStateGatter(MethodDeclaration stateGetter, ResourceNode resourceNode, - ILanguageSpecific langSpec) { + IPlatformSpecific platformSpec, ILanguageSpecific langSpec) { try { // Data transfer on the same channel hierarchy. boolean isContainedPush = false; @@ -914,10 +931,10 @@ if (((PushPullAttribute) dIn.getAttribute()).getSelectedOption() == PushPullValue.PUSH) { // PUSH transfer isContainedPush = true; - inputResourceToStateAccessor.put(in, getPushAccessor()); + inputResourceToStateAccessor.put(in, getPushAccessor(platformSpec)); } else { // PULL transfer - inputResourceToStateAccessor.put(in, getPullAccessor()); + inputResourceToStateAccessor.put(in, getPullAccessor(platformSpec)); ch = ((ChannelNode) resToCh.getDestination()).getChannel(); // pull containing input side channel is at most one. } } @@ -935,7 +952,7 @@ // for reference channel members. for (ChannelMember c: ch.getReferenceChannelMembers()) { - inputResourceToStateAccessor.put(c, getPullAccessor()); // by pull data transfer + inputResourceToStateAccessor.put(c, getPullAccessor(platformSpec)); // by pull data transfer } // Construct the base message. @@ -1078,7 +1095,7 @@ // generate a return statement. String[] sideEffects = new String[] {""}; - String curState = ch.deriveUpdateExpressionOf(out, messageTerm, getPullAccessor()).toImplementation(sideEffects); + String curState = ch.deriveUpdateExpressionOf(out, messageTerm, getPullAccessor(platformSpec)).toImplementation(sideEffects); stateGetter.addStatement(sideEffects[0] + langSpec.getReturnStatement(curState) + langSpec.getStatementDelimiter()); } catch (ParameterizedIdentifierIsFutureWork | ResolvingMultipleDefinitionIsFutureWork | InvalidMessage | UnificationFailed | ValueUndefined e) { @@ -1134,7 +1151,8 @@ } } - private Map.Entry, Map>>> declareCacheFieldsAndUpdateMethods(ResourceNode resourceNode, TypeDeclaration component, TypeDeclaration parentComponent, ILanguageSpecific langSpec) { + private Map.Entry, Map>>> declareCacheFieldsAndUpdateMethods(ResourceNode resourceNode, TypeDeclaration component, TypeDeclaration parentComponent, + IPlatformSpecific platformSpec, ILanguageSpecific langSpec) { // Declare cash fields and update methods in the component. String resComponentName = getComponentName(resourceNode.getResourceHierarchy(), langSpec); List constructorStatements = new ArrayList<>(); @@ -1250,17 +1268,17 @@ if (resourceNode.getInSideResources().contains(out.getResource())) { Expression updateExp = null; if (ch.getReferenceChannelMembers().size() == 0) { - updateExp = ch.deriveUpdateExpressionOf(out, getPushAccessor()).getKey(); + updateExp = ch.deriveUpdateExpressionOf(out, getPushAccessor(platformSpec)).getKey(); } else { // if there exists one or more reference channel member. HashMap inputResourceToStateAccessor = new HashMap<>(); for (ChannelMember in: ch.getInputChannelMembers()) { - inputResourceToStateAccessor.put(in, getPushAccessor()); + inputResourceToStateAccessor.put(in, getPushAccessor(platformSpec)); } for (ChannelMember c: ch.getReferenceChannelMembers()) { - inputResourceToStateAccessor.put(c, getRefAccessor()); + inputResourceToStateAccessor.put(c, getRefAccessor(platformSpec)); } - updateExp = ch.deriveUpdateExpressionOf(out, getPushAccessor(), inputResourceToStateAccessor).getKey(); + updateExp = ch.deriveUpdateExpressionOf(out, getPushAccessor(platformSpec), inputResourceToStateAccessor).getKey(); } // Replace Json constructor with a constructor of the child resource. ResourceHierarchy outRes = out.getResource().getResourceHierarchy(); @@ -1408,7 +1426,7 @@ for (ChannelMember out: ch.getOutputChannelMembers()) { if (resourceNode.getInSideResources().contains(out.getResource())) { try { - resourcePaths = ch.fillOutsideResourcePaths(out, getPullAccessor()); + resourcePaths = ch.fillOutsideResourcePaths(out, getPullAccessor(platformSpec)); } catch (ParameterizedIdentifierIsFutureWork | ResolvingMultipleDefinitionIsFutureWork | InvalidMessage | UnificationFailed | ValueUndefined e) { e.printStackTrace(); @@ -1423,7 +1441,7 @@ // An outside input resource path depends on srcRes. ResourcePath outsidePath = resourcePaths.get(outsideMember).getKey(); String outsideResName = langSpec.toVariableName(getComponentName(outsidePath.getResourceHierarchy(), langSpec)); - Expression outsideExp = getPullAccessor().getDirectStateAccessorFor(outsidePath, null); + Expression outsideExp = getPullAccessor(platformSpec).getDirectStateAccessorFor(outsidePath, null); if (generatesComponent(outsidePath.getResourceHierarchy())) { outsideExp = ((Term) outsideExp).getChild(0); } @@ -1547,7 +1565,7 @@ insideResPath = insideResPath.getParent(); } insideResPath = insideResPath.getParent(); - String parent = getPullAccessor().getDirectStateAccessorFor(insideResPath, resourceNode.getPrimaryResourcePath()).toImplementation(new String[] {}); + String parent = getPullAccessor(platformSpec).getDirectStateAccessorFor(insideResPath, resourceNode.getPrimaryResourcePath()).toImplementation(new String[] {}); if (insideResPath != null) { if (selType.equals(DataConstraintModel.typeInt)) { // make a for loop (for a list) for broadcasting. @@ -1582,7 +1600,7 @@ if (!generatesComponent(srcRes.getResourceHierarchy())) { srcRes = srcRes.getParent(); } - Expression refGetter = getPullAccessor().getDirectStateAccessorFor(ref, srcRes); + Expression refGetter = getPullAccessor(platformSpec).getDirectStateAccessorFor(ref, srcRes); String[] sideEffects = new String[] {""}; String refExp = refGetter.toImplementation(sideEffects); String refTypeName = ref.getResourceStateType().getInterfaceTypeName(); @@ -1593,7 +1611,7 @@ } // Update fields to refer to outside resources. try { - Map>> resourcePaths = ch2.fillOutsideResourcePaths(out, getPullAccessor()); + Map>> resourcePaths = ch2.fillOutsideResourcePaths(out, getPullAccessor(platformSpec)); if (resourcePaths != null && resourcePaths.size() > 0) { for (ChannelMember outsideMember: resourcePaths.keySet()) { ResourcePath outsidePath = resourcePaths.get(outsideMember).getKey(); @@ -1601,7 +1619,7 @@ outsidePath = outsidePath.getParent(); } String outsideResName = langSpec.toVariableName(getComponentName(outsidePath.getResourceHierarchy(), langSpec)); - Expression outsideExp = getPullAccessor().getDirectStateAccessorFor(outsidePath, null); + Expression outsideExp = getPullAccessor(platformSpec).getDirectStateAccessorFor(outsidePath, null); if (generatesComponent(outsidePath.getResourceHierarchy())) { outsideExp = ((Term) outsideExp).getChild(0); } @@ -1690,7 +1708,7 @@ if (srcRes2.getParent().equals(dstRes2.getParent())) { Map>> resourcePaths = null; try { - resourcePaths = ch2.fillOutsideResourcePaths(out, getPullAccessor()); + resourcePaths = ch2.fillOutsideResourcePaths(out, getPullAccessor(platformSpec)); if (resourcePaths != null && resourcePaths.size() > 0) { for (ChannelMember outsideMember: outsideInputMembers2) { for (ChannelMember dependedMember: resourcePaths.get(outsideMember).getValue()) { @@ -1701,7 +1719,7 @@ outsidePath = outsidePath.getParent(); } String outsideResName = langSpec.toVariableName(getComponentName(outsidePath.getResourceHierarchy(), langSpec)); - Expression outsideExp = getPullAccessor().getDirectStateAccessorFor(outsidePath, null); + Expression outsideExp = getPullAccessor(platformSpec).getDirectStateAccessorFor(outsidePath, null); if (generatesComponent(outsidePath.getResourceHierarchy())) { outsideExp = ((Term) outsideExp).getChild(0); } @@ -1956,14 +1974,14 @@ ResourcePath ref = rc.getResource(); if (!out.getResource().equals(ref)) { String refVarName = ref.getLeafResourceName(); - Expression refGetter = getPullAccessor().getDirectStateAccessorFor(ref, null); + Expression refGetter = getPullAccessor(platformSpec).getDirectStateAccessorFor(ref, null); String[] sideEffects = new String[] {""}; String refExp = refGetter.toImplementation(sideEffects); String refTypeName = ref.getResourceStateType().getInterfaceTypeName(); inputAccessor.addFirstStatement(sideEffects[0] + refTypeName + " " + refVarName + " = " + refExp + ";"); } } - Expression resExp = getPullAccessor().getDirectStateAccessorFor(out.getResource(), null); + Expression resExp = getPullAccessor(platformSpec).getDirectStateAccessorFor(out.getResource(), null); List args = new ArrayList<>(); if (resExp instanceof Term) { // to access the parent @@ -2008,7 +2026,7 @@ if (input != null) { // Add a statement to update the state field to the input method. try { - Expression updateExp = ((DataTransferChannel) ch).deriveUpdateExpressionOf(out, getRefAccessor()).getKey(); + Expression updateExp = ((DataTransferChannel) ch).deriveUpdateExpressionOf(out, getRefAccessor(platformSpec)).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) { @@ -2175,7 +2193,7 @@ insideResPath = insideResPath.getParent(); } insideResPath = insideResPath.getParent(); - String parent = getPullAccessor().getDirectStateAccessorFor(insideResPath, resourceNode.getPrimaryResourcePath()).toImplementation(new String[] {}); + String parent = getPullAccessor(platformSpec).getDirectStateAccessorFor(insideResPath, resourceNode.getPrimaryResourcePath()).toImplementation(new String[] {}); if (insideResPath != null) { if (selType.equals(DataConstraintModel.typeInt)) { // make a for loop (for a list) for broadcasting. @@ -2210,7 +2228,7 @@ if (!generatesComponent(srcRes.getResourceHierarchy())) { srcRes = srcRes.getParent(); } - Expression refGetter = getPullAccessor().getDirectStateAccessorFor(ref, srcRes); + Expression refGetter = getPullAccessor(platformSpec).getDirectStateAccessorFor(ref, srcRes); String[] sideEffects = new String[] {""}; String refExp = refGetter.toImplementation(sideEffects); String refTypeName = ref.getResourceStateType().getInterfaceTypeName(); @@ -2221,7 +2239,7 @@ } // Update fields to refer to outside resources. try { - Map>> resourcePaths = ch2.fillOutsideResourcePaths(out2, getPullAccessor()); + Map>> resourcePaths = ch2.fillOutsideResourcePaths(out2, getPullAccessor(platformSpec)); if (resourcePaths != null && resourcePaths.size() > 0) { for (ChannelMember outsideMember: resourcePaths.keySet()) { ResourcePath outsidePath = resourcePaths.get(outsideMember).getKey(); @@ -2229,7 +2247,7 @@ outsidePath = outsidePath.getParent(); } String outsideResName = langSpec.toVariableName(getComponentName(outsidePath.getResourceHierarchy(), langSpec)); - Expression outsideExp = getPullAccessor().getDirectStateAccessorFor(outsidePath, null); + Expression outsideExp = getPullAccessor(platformSpec).getDirectStateAccessorFor(outsidePath, null); if (generatesComponent(outsidePath.getResourceHierarchy())) { outsideExp = ((Term) outsideExp).getChild(0); } @@ -2313,7 +2331,7 @@ if (srcRes2.getParent().equals(dstRes2.getParent())) { Map>> resourcePaths = null; try { - resourcePaths = directDstCh.fillOutsideResourcePaths(out2, getPullAccessor()); + resourcePaths = directDstCh.fillOutsideResourcePaths(out2, getPullAccessor(platformSpec)); if (resourcePaths != null && resourcePaths.size() > 0) { for (ChannelMember outsideMember: outsideInputMembers2) { for (ChannelMember dependedMember: resourcePaths.get(outsideMember).getValue()) { @@ -2324,7 +2342,7 @@ outsidePath = outsidePath.getParent(); } String outsideResName = langSpec.toVariableName(getComponentName(outsidePath.getResourceHierarchy(), langSpec)); - Expression outsideExp = getPullAccessor().getDirectStateAccessorFor(outsidePath, null); + Expression outsideExp = getPullAccessor(platformSpec).getDirectStateAccessorFor(outsidePath, null); if (generatesComponent(outsidePath.getResourceHierarchy())) { outsideExp = ((Term) outsideExp).getChild(0); } @@ -2359,4 +2377,62 @@ } return new AbstractMap.SimpleEntry<>(constructorStatements, inputStatements); } + + private void declareGetterAccessorInTheRootResource(ResourceNode resourceNode, + Map getterAccessors, IPlatformSpecific platformSpec, ILanguageSpecific langSpec) { + if (resourceNode.getResourceHierarchy().getParent() != null) { + // For a non-root resource + MethodDeclaration getterAccessor = null; + List mainGetterParams = new ArrayList<>(); + String resourcePath = getGetterResourcePathAndPathParams(resourceNode.getPrimaryResourcePath(), mainGetterParams, platformSpec, langSpec); + if (resourcePath.indexOf('/') > 0) { + resourcePath = resourcePath.substring(resourcePath.indexOf('/')); + } else { + resourcePath = ""; + } + if (mainGetterParams.size() > 0) { + getterAccessor = langSpec.newMethodDeclaration(getterPrefix + getComponentName(resourceNode.getResourceHierarchy(), langSpec) + methoNameOfResourceState, + false, + getImplStateType(resourceNode.getResourceHierarchy(), langSpec), + mainGetterParams); + } else { + getterAccessor = langSpec.newMethodDeclaration(getterPrefix + getComponentName(resourceNode.getResourceHierarchy(), langSpec) + methoNameOfResourceState, + getImplStateType(resourceNode.getResourceHierarchy(), langSpec)); + } + getterAccessor.setBody(new Block()); + ResourcePath resPath = resourceNode.getPrimaryResourcePath(); + Expression getState = getPullAccessor(platformSpec).getDirectStateAccessorFor(resPath, resPath.getRoot()); + getterAccessor.getBody().addStatement(langSpec.getReturnStatement(getState.toImplementation(new String[] {null})) + langSpec.getStatementDelimiter()); + platformSpec.addGetAnnotations(getterAccessor); + if (resourcePath.length() > 0) { + platformSpec.addPathAnnotation(getterAccessor, resourcePath); + } + getterAccessors.put(resourceNode.getResourceHierarchy(), getterAccessor); + } + } + + private String getGetterResourcePathAndPathParams(ResourcePath resPath, List pathParams, IPlatformSpecific platformSpec, ILanguageSpecific langSpec) { + int v = 1; + List params = new ArrayList<>(); + for (Expression pathParam: resPath.getPathParams()) { + if (pathParam instanceof Variable) { + Variable var = (Variable) pathParam; + String paramName = var.getName(); + params.add("{" + paramName + "}"); + VariableDeclaration param = langSpec.newVariableDeclaration(var.getType(), paramName); + platformSpec.addParamAnnotation(param, paramName); + pathParams.add(param); + } else if (pathParam instanceof Term) { + Term var = (Term) pathParam; + String paramName = "v" + v; + params.add("{" + paramName + "}"); + VariableDeclaration param = langSpec.newVariableDeclaration(var.getType(), paramName); + platformSpec.addParamAnnotation(param, paramName); + pathParams.add(param); + } + v++; + } + return resPath.getResourceHierarchy().toResourcePath(params); + } + } diff --git a/AlgebraicDataflowArchitectureModel/src/generators/IPlatformSpecific.java b/AlgebraicDataflowArchitectureModel/src/generators/IPlatformSpecific.java index 5de330b..a3f35c1 100644 --- a/AlgebraicDataflowArchitectureModel/src/generators/IPlatformSpecific.java +++ b/AlgebraicDataflowArchitectureModel/src/generators/IPlatformSpecific.java @@ -8,13 +8,17 @@ import code.ast.ImportDeclaration; import code.ast.MethodDeclaration; import code.ast.TypeDeclaration; +import code.ast.VariableDeclaration; public interface IPlatformSpecific { boolean hasMain(); boolean isMonolithic(); + boolean isDifferentTreesAsDifferentServices(); boolean hasComponentAnnotation(); void addComponentAnnotations(TypeDeclaration component, String resourceName); void addGetAnnotations(MethodDeclaration getMethod); + void addPathAnnotation(MethodDeclaration method, String resourcePath); + void addParamAnnotation(VariableDeclaration var, String paramName); void addClientFieldDeclaration(TypeDeclaration component); boolean hasPlatformSpecificImports(); void addPlatformSpecificImports(CompilationUnit cu); diff --git a/AlgebraicDataflowArchitectureModel/src/generators/RestApiSpecific.java b/AlgebraicDataflowArchitectureModel/src/generators/RestApiSpecific.java index 5582fc9..379b7d1 100644 --- a/AlgebraicDataflowArchitectureModel/src/generators/RestApiSpecific.java +++ b/AlgebraicDataflowArchitectureModel/src/generators/RestApiSpecific.java @@ -9,6 +9,7 @@ import code.ast.ImportDeclaration; import code.ast.MethodDeclaration; import code.ast.TypeDeclaration; +import code.ast.VariableDeclaration; import models.algebra.Type; public class RestApiSpecific implements IPlatformSpecific { @@ -25,6 +26,11 @@ } @Override + public boolean isDifferentTreesAsDifferentServices() { + return true; + } + + @Override public boolean hasComponentAnnotation() { return true; } @@ -42,6 +48,16 @@ } @Override + public void addPathAnnotation(MethodDeclaration method, String resourcePath) { + method.addAnnotation(new Annotation("Path", "\"" + resourcePath + "\"")); + } + + @Override + public void addParamAnnotation(VariableDeclaration var, String paramName) { + var.addAnnotation(new Annotation("PathParam", "\"" + paramName + "\"")); + } + + @Override public void addClientFieldDeclaration(TypeDeclaration component) { FieldDeclaration clientField = new FieldDeclaration(typeClient, "client", "ClientBuilder.newClient()"); component.addField(clientField); @@ -61,5 +77,4 @@ cu.addImport(new ImportDeclaration("com.fasterxml.jackson.databind.ObjectMapper")); cu.addImport(new ImportDeclaration("com.fasterxml.jackson.core.JsonProcessingException")); } - } diff --git a/AlgebraicDataflowArchitectureModel/src/generators/StandaloneSpecific.java b/AlgebraicDataflowArchitectureModel/src/generators/StandaloneSpecific.java index 4afd2c8..8ecbdc4 100644 --- a/AlgebraicDataflowArchitectureModel/src/generators/StandaloneSpecific.java +++ b/AlgebraicDataflowArchitectureModel/src/generators/StandaloneSpecific.java @@ -7,6 +7,7 @@ import code.ast.ImportDeclaration; import code.ast.MethodDeclaration; import code.ast.TypeDeclaration; +import code.ast.VariableDeclaration; public class StandaloneSpecific implements IPlatformSpecific { @@ -21,6 +22,11 @@ } @Override + public boolean isDifferentTreesAsDifferentServices() { + return false; // meaningless + } + + @Override public boolean hasComponentAnnotation() { return false; } @@ -34,6 +40,14 @@ } @Override + public void addPathAnnotation(MethodDeclaration method, String resourcePath) { + } + + @Override + public void addParamAnnotation(VariableDeclaration var, String paramName) { + } + + @Override public void addClientFieldDeclaration(TypeDeclaration component) { }