| |
---|
| | import java.util.List; |
---|
| | import java.util.Map; |
---|
| | import java.util.Map.Entry; |
---|
| | import java.util.Set; |
---|
| | import java.util.AbstractMap.SimpleEntry; |
---|
| | |
---|
| | import code.ast.Block; |
---|
| | import code.ast.CompilationUnit; |
---|
| | import code.ast.FieldDeclaration; |
---|
| |
---|
| | import models.algebra.Expression; |
---|
| | import models.algebra.Field; |
---|
| | import models.algebra.InvalidMessage; |
---|
| | import models.algebra.ParameterizedIdentifierIsFutureWork; |
---|
| | import models.algebra.Position; |
---|
| | import models.algebra.Term; |
---|
| | import models.algebra.Type; |
---|
| | import models.algebra.UnificationFailed; |
---|
| | import models.algebra.ValueUndefined; |
---|
| | import models.algebra.Variable; |
---|
| | import models.dataConstraintModel.Channel; |
---|
| | import models.dataConstraintModel.ChannelMember; |
---|
| | import models.dataConstraintModel.DataConstraintModel; |
---|
| | import models.dataConstraintModel.JsonAccessor; |
---|
| | import models.dataConstraintModel.ResourceHierarchy; |
---|
| | import models.dataConstraintModel.ResourcePath; |
---|
| | import models.dataConstraintModel.Selector; |
---|
| | import models.dataFlowModel.DataFlowEdge; |
---|
| |
---|
| | public void generateCodeFromFlowGraph(DataTransferModel model, DataFlowGraph flowGraph, ArrayList<ResourceNode> components, |
---|
| | TypeDeclaration mainComponent, MethodDeclaration mainConstructor, ArrayList<CompilationUnit> codes, ILanguageSpecific langSpec) { |
---|
| | Map<ResourceHierarchy, TypeDeclaration> resourceComponents = new HashMap<>(); |
---|
| | Map<ResourceHierarchy, MethodDeclaration> resourceConstructors = new HashMap<>(); |
---|
| | List<Map.Entry<ResourceHierarchy, MethodDeclaration>> getters = new ArrayList<>(); |
---|
| | List<Map.Entry<ResourceHierarchy, MethodDeclaration>> inputs = new ArrayList<>(); |
---|
| | List<Map.Entry<ResourceHierarchy, MethodDeclaration>> updates = new ArrayList<>(); |
---|
| | List<Map.Entry<ResourceHierarchy, FieldDeclaration>> fields = new ArrayList<>(); |
---|
| | List<Map.Entry<ResourceHierarchy, VariableDeclaration>> constructorParams = new ArrayList<>(); |
---|
| | List<Map.Entry<ResourceHierarchy, String>> constructorStatements = new ArrayList<>(); |
---|
| | Map<MethodDeclaration, Map.Entry<Expression, ResourceHierarchy>> updateStatements = new HashMap<>(); |
---|
| | |
---|
| | // For each components. |
---|
| | // For each components (1st pass). |
---|
| | for (Node componentNode: components) { |
---|
| | // Declare this resource. |
---|
| | ResourceNode resourceNode = (ResourceNode) componentNode; |
---|
| | Type resStateType = getImplStateType(resourceNode.getResourceHierarchy(), langSpec); |
---|
| | TypeDeclaration component = null; |
---|
| | if (generatesComponent(resourceNode.getResourceHierarchy())) { |
---|
| | // A component will be generated for this resource. |
---|
| | String resourceName = getComponentName(resourceNode.getResourceHierarchy(), langSpec); |
---|
| |
---|
| | } else { |
---|
| | resourceConstructors.put(resourceNode.getResourceHierarchy(), constructor); |
---|
| | } |
---|
| | } |
---|
| | } |
---|
| | } |
---|
| | |
---|
| | // For each components (2nd pass). |
---|
| | for (Node componentNode: components) { |
---|
| | // Declare this resource. |
---|
| | ResourceNode resourceNode = (ResourceNode) componentNode; |
---|
| | Type resStateType = getImplStateType(resourceNode.getResourceHierarchy(), langSpec); |
---|
| | TypeDeclaration component = null; |
---|
| | TypeDeclaration parentComponent = null; |
---|
| | if (generatesComponent(resourceNode.getResourceHierarchy())) { |
---|
| | String resourceName = getComponentName(resourceNode.getResourceHierarchy(), langSpec); |
---|
| | component = resourceComponents.get(resourceNode.getResourceHierarchy()); |
---|
| | |
---|
| | // Declare the field in this resource to store the state. |
---|
| | if (((StoreAttribute) resourceNode.getAttribute()).isStored()) { |
---|
| | declareStateField(resourceNode, resourceName, component, resStateType, constructorParams, langSpec); |
---|
| |
---|
| | |
---|
| | // Declare the getter methods in this resource to obtain the children resources. |
---|
| | declareChildGetterMethod(resourceNode, component, langSpec); |
---|
| | } |
---|
| | if (resourceNode.getResourceHierarchy().getParent() != null) { |
---|
| | parentComponent = resourceComponents.get(resourceNode.getResourceHierarchy().getParent()); |
---|
| | } |
---|
| | |
---|
| | // Declare cache fields and update methods in this resource. |
---|
| | Map.Entry<List<MethodDeclaration>, Map.Entry<List<FieldDeclaration>, List<String>>> updatesAndCacheFieldsAndInitStatements = declareCacheFieldsAndUpdateMethods(resourceNode, component, langSpec); |
---|
| | Map.Entry<List<String>, Map<MethodDeclaration, Map.Entry<Expression, ResourceHierarchy>>> initStatementsAndUpdateUpdates = declareCacheFieldsAndUpdateMethods(resourceNode, component, parentComponent, langSpec); |
---|
| | if (component == null) { |
---|
| | // updates were not added to any component because no component had been generated. |
---|
| | for (MethodDeclaration update: updatesAndCacheFieldsAndInitStatements.getKey()) { |
---|
| | updates.add(new AbstractMap.SimpleEntry<>(resourceNode.getResourceHierarchy().getParent(), update)); |
---|
| | } |
---|
| | // Cache fields were not added to any component because no component had been generated. |
---|
| | for (FieldDeclaration field: updatesAndCacheFieldsAndInitStatements.getValue().getKey()) { |
---|
| | fields.add(new AbstractMap.SimpleEntry<>(resourceNode.getResourceHierarchy().getParent(), field)); |
---|
| | } |
---|
| | // Constructor statements were not added to any component because no component had been generated. |
---|
| | for (String statement: updatesAndCacheFieldsAndInitStatements.getValue().getValue()) { |
---|
| | for (String statement: initStatementsAndUpdateUpdates.getKey()) { |
---|
| | constructorStatements.add(new AbstractMap.SimpleEntry<>(resourceNode.getResourceHierarchy().getParent(), statement)); |
---|
| | } |
---|
| | } |
---|
| | for (Map.Entry<MethodDeclaration, Map.Entry<Expression, ResourceHierarchy>> entry: initStatementsAndUpdateUpdates.getValue().entrySet()) { |
---|
| | updateStatements.put(entry.getKey(), entry.getValue()); |
---|
| | } |
---|
| | |
---|
| | // Declare the state field and reference fields in the parent component. |
---|
| | if (component == null) { |
---|
| | declareFieldsInParentComponent(resourceNode, fields, constructorParams, langSpec); |
---|
| | declareFieldsInParentComponent(resourceNode, parentComponent, constructorParams, langSpec); |
---|
| | } |
---|
| | |
---|
| | // Declare the getter method in this resource to obtain the state. |
---|
| | MethodDeclaration stateGetter = declareStateGetterMethod(resourceNode, component, resStateType, langSpec); |
---|
| | if (component == null) { |
---|
| | // stateGetter was not added to any component because no component had been generated. |
---|
| | getters.add(new AbstractMap.SimpleEntry<>(resourceNode.getResourceHierarchy().getParent(), stateGetter)); |
---|
| | } |
---|
| | MethodDeclaration stateGetter = declareStateGetterMethod(resourceNode, component, parentComponent, resStateType, langSpec); |
---|
| | |
---|
| | // Declare the accessor method in the main component to call the getter method. |
---|
| | declareAccessorInMainComponent(mainComponent, resourceNode, stateGetter, langSpec); |
---|
| | |
---|
| | // Declare input methods in this component and the main component. |
---|
| | Map.Entry<List<MethodDeclaration>, List<String>> inputMethodsAndInitStatements = declareInputMethodsInThisAndMainComponents(resourceNode, component, mainComponent, model, langSpec); |
---|
| | Map.Entry<List<String>, Map<MethodDeclaration, Map.Entry<Expression, ResourceHierarchy>>> initStatementsAndInputUpdates = declareInputMethodsInThisAndMainComponents(resourceNode, component, parentComponent, mainComponent, model, langSpec); |
---|
| | if (component == null) { |
---|
| | // inputMethods were not added to any component because no component had been generated. |
---|
| | for (MethodDeclaration in: inputMethodsAndInitStatements.getKey()) { |
---|
| | inputs.add(new AbstractMap.SimpleEntry<>(resourceNode.getResourceHierarchy().getParent(), in)); |
---|
| | } |
---|
| | // Constructor statements were not added to any component because no component had been generated. |
---|
| | for (String statement: inputMethodsAndInitStatements.getValue()) { |
---|
| | for (String statement: initStatementsAndInputUpdates.getKey()) { |
---|
| | constructorStatements.add(new AbstractMap.SimpleEntry<>(resourceNode.getResourceHierarchy().getParent(), statement)); |
---|
| | } |
---|
| | } |
---|
| | } |
---|
| | |
---|
| | // Add leaf getter methods to the parent components. |
---|
| | for (Map.Entry<ResourceHierarchy, MethodDeclaration> entry: getters) { |
---|
| | resourceComponents.get(entry.getKey()).addMethod(entry.getValue()); |
---|
| | } |
---|
| | |
---|
| | // Add leaf input methods to the parent components. |
---|
| | for (Map.Entry<ResourceHierarchy, MethodDeclaration> entry: inputs) { |
---|
| | resourceComponents.get(entry.getKey()).addMethod(entry.getValue()); |
---|
| | } |
---|
| | |
---|
| | // Add leaf update methods to the parent components. |
---|
| | for (Map.Entry<ResourceHierarchy, MethodDeclaration> entry: updates) { |
---|
| | resourceComponents.get(entry.getKey()).addMethod(entry.getValue()); |
---|
| | } |
---|
| | |
---|
| | // Add leaf reference fields to the parent components. |
---|
| | for (Map.Entry<ResourceHierarchy, FieldDeclaration> entry: fields) { |
---|
| | resourceComponents.get(entry.getKey()).addField(entry.getValue()); |
---|
| | for (Map.Entry<MethodDeclaration, Map.Entry<Expression, ResourceHierarchy>> entry: initStatementsAndInputUpdates.getValue().entrySet()) { |
---|
| | updateStatements.put(entry.getKey(), entry.getValue()); |
---|
| | } |
---|
| | } |
---|
| | |
---|
| | // Add constructor parameters to the ancestor components. |
---|
| | for (ResourceNode root: flowGraph.getRootResourceNodes()) { |
---|
| |
---|
| | |
---|
| | // Add constructor statements. |
---|
| | for (Map.Entry<ResourceHierarchy, String> entry: constructorStatements) { |
---|
| | resourceConstructors.get(entry.getKey()).addStatement(entry.getValue()); |
---|
| | } |
---|
| | |
---|
| | // Add update statements. |
---|
| | for (MethodDeclaration method: updateStatements.keySet()) { |
---|
| | Expression updateExp = updateStatements.get(method).getKey(); |
---|
| | ResourceHierarchy childRes = updateStatements.get(method).getValue(); |
---|
| | TypeDeclaration childComponent = resourceComponents.get(childRes); |
---|
| | addUpdateStatementWithConstructorInvocationToMethod(method, updateExp, childRes, childComponent, langSpec); |
---|
| | } |
---|
| | } |
---|
| | |
---|
| | private static List<VariableDeclaration> addConstructorParameters(ResourceHierarchy resource, Map<ResourceHierarchy, TypeDeclaration> resourceComponents, |
---|
| |
---|
| | } |
---|
| | } |
---|
| | if (resource.getNumParameters() > 0) params.clear(); |
---|
| | return params; |
---|
| | } |
---|
| | |
---|
| | private void addUpdateStatementWithConstructorInvocationToMethod(MethodDeclaration method, Expression exp, ResourceHierarchy childRes, TypeDeclaration childComponent, ILanguageSpecific langSpec) { |
---|
| | Type replacedJsonType = childRes.getResourceStateType(); |
---|
| | String replacingClassName = getComponentName(childRes, langSpec); |
---|
| | Map<Position, Term> subTerms = ((Term) exp).getSubTerms(Term.class); |
---|
| | for (Entry<Position, Term> termEnt: subTerms.entrySet()) { |
---|
| | Term jsonTerm = termEnt.getValue(); |
---|
| | if (jsonTerm.getType() == replacedJsonType) { |
---|
| | MethodDeclaration childConstructor = getConstructor(childComponent); |
---|
| | List<String> params = new ArrayList<>(); |
---|
| | for (VariableDeclaration var: childConstructor.getParameters()) { |
---|
| | JsonAccessor jsonMember = new JsonAccessor(DataConstraintModel.dot); |
---|
| | jsonMember.addChild(jsonTerm); |
---|
| | jsonMember.addChild(new Constant("\"" + var.getName() + "\"")); |
---|
| | params.add(jsonMember.reduce().toImplementation(new String[] {""})); |
---|
| | } |
---|
| | ((Term) exp).replaceSubTerm(termEnt.getKey(), new Constant(langSpec.getConstructorInvocation(replacingClassName, params))); |
---|
| | } |
---|
| | } |
---|
| | String[] sideEffects = new String[] {""}; |
---|
| | String newState = exp.toImplementation(sideEffects); |
---|
| | String updateStatement; |
---|
| | if (exp instanceof Term && ((Term) exp).getSymbol().isImplWithSideEffect()) { |
---|
| | updateStatement = sideEffects[0]; |
---|
| | } else { |
---|
| | updateStatement = sideEffects[0] + langSpec.getFieldAccessor(fieldOfResourceState) + langSpec.getAssignment() + newState + langSpec.getStatementDelimiter(); |
---|
| | } |
---|
| | method.addFirstStatement(updateStatement); |
---|
| | } |
---|
| | |
---|
| | private MethodDeclaration declareConstructorAndFieldsToReferToResources(ResourceNode resourceNode, TypeDeclaration component, List<ResourcePath> depends, ILanguageSpecific langSpec) { |
---|
| | // Declare a constructor in each component. |
---|
| |
---|
| | } |
---|
| | } |
---|
| | } |
---|
| | |
---|
| | private void declareFieldsInParentComponent(ResourceNode resourceNode, List<Map.Entry<ResourceHierarchy, FieldDeclaration>> fields, List<Map.Entry<ResourceHierarchy, VariableDeclaration>> constructorParams, ILanguageSpecific langSpec) { |
---|
| | private void declareFieldsInParentComponent(ResourceNode resourceNode, TypeDeclaration parentComponent, List<Map.Entry<ResourceHierarchy, VariableDeclaration>> constructorParams, ILanguageSpecific langSpec) { |
---|
| | // Declare reference fields for push/pull data transfer. |
---|
| | boolean noPullTransfer = true; |
---|
| | for (Edge resToCh : resourceNode.getOutEdges()) { |
---|
| | DataFlowEdge re = (DataFlowEdge) resToCh; |
---|
| |
---|
| | dstRes = dstRes.getParent(); |
---|
| | } |
---|
| | dstResName = getComponentName(dstRes.getResourceHierarchy(), langSpec); |
---|
| | FieldDeclaration refFieldForPush = langSpec.newFieldDeclaration(new Type(dstResName, dstResName), langSpec.toVariableName(dstResName)); |
---|
| | fields.add(new AbstractMap.SimpleEntry<>(resourceNode.getParent().getResourceHierarchy(), refFieldForPush)); |
---|
| | parentComponent.addField(refFieldForPush); |
---|
| | if (dstRes.getParent() != null) { |
---|
| | // Reference to root resource. |
---|
| | String dstRootResName = getComponentName(dstRes.getRoot().getResourceHierarchy(), langSpec); |
---|
| | FieldDeclaration refRootFieldForPush = langSpec.newFieldDeclaration(new Type(dstRootResName, dstRootResName), langSpec.toVariableName(dstRootResName)); |
---|
| | fields.add(new AbstractMap.SimpleEntry<>(resourceNode.getParent().getResourceHierarchy(), refRootFieldForPush)); |
---|
| | parentComponent.addField(refRootFieldForPush); |
---|
| | } |
---|
| | } |
---|
| | } |
---|
| | } |
---|
| |
---|
| | srcRes = srcRes.getParent(); |
---|
| | } |
---|
| | srcResName = getComponentName(srcRes.getResourceHierarchy(), langSpec); |
---|
| | FieldDeclaration refFieldForPull = langSpec.newFieldDeclaration(new Type(srcResName, srcResName), langSpec.toVariableName(srcResName)); |
---|
| | fields.add(new AbstractMap.SimpleEntry<>(resourceNode.getParent().getResourceHierarchy(), refFieldForPull)); |
---|
| | parentComponent.addField(refFieldForPull); |
---|
| | if (srcRes.getParent() != null) { |
---|
| | // Reference to root resource. |
---|
| | String srcRootResName = getComponentName(srcRes.getRoot().getResourceHierarchy(), langSpec); |
---|
| | FieldDeclaration refRootFieldForPull = langSpec.newFieldDeclaration(new Type(srcRootResName, srcRootResName), langSpec.toVariableName(srcRootResName)); |
---|
| | fields.add(new AbstractMap.SimpleEntry<>(resourceNode.getParent().getResourceHierarchy(), refRootFieldForPull)); |
---|
| | parentComponent.addField(refRootFieldForPull); |
---|
| | } |
---|
| | noPullTransfer = false; |
---|
| | } |
---|
| | } |
---|
| |
---|
| | ResourceHierarchy res = resourceNode.getOutSideResource().getResourceHierarchy(); |
---|
| | if (((StoreAttribute) resourceNode.getAttribute()).isStored() && noPullTransfer && res.getNumParameters() == 0) { |
---|
| | String resName = getComponentName(res, langSpec); |
---|
| | FieldDeclaration stateField = langSpec.newFieldDeclaration(res.getResourceStateType(), langSpec.toVariableName(resName)); |
---|
| | fields.add(new AbstractMap.SimpleEntry<>(resourceNode.getParent().getResourceHierarchy(), stateField)); |
---|
| | parentComponent.addField(stateField); |
---|
| | constructorParams.add(new AbstractMap.SimpleEntry<>(resourceNode.getParent().getResourceHierarchy(), langSpec.newVariableDeclaration(res.getResourceStateType(), langSpec.toVariableName(resName)))); |
---|
| | } |
---|
| | } |
---|
| | |
---|
| | private MethodDeclaration declareStateGetterMethod(ResourceNode resourceNode, TypeDeclaration component, Type resStateType, ILanguageSpecific langSpec) { |
---|
| | private MethodDeclaration declareStateGetterMethod(ResourceNode resourceNode, TypeDeclaration component, TypeDeclaration parentComponent, Type resStateType, ILanguageSpecific langSpec) { |
---|
| | // Declare the getter method of the resource state. |
---|
| | MethodDeclaration stateGetter = null; |
---|
| | if (component != null) { |
---|
| | // A component is created for this resource. |
---|
| |
---|
| | stateGetter = new MethodDeclaration(getterPrefix + resCompName, resStateType); |
---|
| | } else { |
---|
| | stateGetter = new MethodDeclaration(getterPrefix + resCompName, false, resStateType, getterParams); |
---|
| | } |
---|
| | if (parentComponent != null) { |
---|
| | parentComponent.addMethod(stateGetter); |
---|
| | } |
---|
| | } |
---|
| | |
---|
| | if (((StoreAttribute) resourceNode.getAttribute()).isStored()) { |
---|
| | if (component != null) { |
---|
| |
---|
| | } |
---|
| | } |
---|
| | } |
---|
| | |
---|
| | private Map.Entry<List<MethodDeclaration>, Map.Entry<List<FieldDeclaration>, List<String>>> declareCacheFieldsAndUpdateMethods(ResourceNode resourceNode, TypeDeclaration component, ILanguageSpecific langSpec) { |
---|
| | private Map.Entry<List<String>, Map<MethodDeclaration, Map.Entry<Expression, ResourceHierarchy>>> declareCacheFieldsAndUpdateMethods(ResourceNode resourceNode, TypeDeclaration component, TypeDeclaration parentComponent, ILanguageSpecific langSpec) { |
---|
| | // Declare cash fields and update methods in the component. |
---|
| | String resComponentName = langSpec.toComponentName(resourceNode.getResourceName()); |
---|
| | List<MethodDeclaration> updateMethods = new ArrayList<>(); |
---|
| | List<FieldDeclaration> cacheFields = new ArrayList<>(); |
---|
| | List<String> constructorStatements = new ArrayList<>(); |
---|
| | Map<MethodDeclaration, Map.Entry<Expression, ResourceHierarchy>> updateStatements = new HashMap<>(); |
---|
| | for (Edge chToRes: resourceNode.getInEdges()) { |
---|
| | for (Edge resToCh: chToRes.getSource().getInEdges()) { |
---|
| | DataTransferChannel ch = ((ChannelNode) resToCh.getDestination()).getChannel(); |
---|
| | DataFlowEdge re = (DataFlowEdge) resToCh; |
---|
| |
---|
| | } |
---|
| | MethodDeclaration update = langSpec.newMethodDeclaration(updateMethodName + srcResComponentName, false, null, vars); |
---|
| | if (component != null) { |
---|
| | component.addMethod(update); |
---|
| | } else { |
---|
| | updateMethods.add(update); |
---|
| | } else if (parentComponent != null) { |
---|
| | parentComponent.addMethod(update); |
---|
| | } |
---|
| | |
---|
| | // Add a statement to update the state field |
---|
| | if (((StoreAttribute) resourceNode.getAttribute()).isStored()) { |
---|
| | try { |
---|
| | for (ChannelMember out: ch.getOutputChannelMembers()) { |
---|
| | if (resourceNode.getInSideResources().contains(out.getResource())) { |
---|
| | Expression updateExp = ch.deriveUpdateExpressionOf(out, getPushAccessor()); |
---|
| | // Replace Json constructor with a constructor of the child resource. |
---|
| | ResourceHierarchy outRes = out.getResource().getResourceHierarchy(); |
---|
| | if (outRes.getChildren().size() == 1 && outRes.getChildren().iterator().next().getNumParameters() > 0) { |
---|
| | ResourceHierarchy childRes = outRes.getChildren().iterator().next(); |
---|
| | Type childStateType = childRes.getResourceStateType(); |
---|
| | if (DataConstraintModel.typeJson.isAncestorOf(childStateType)) { |
---|
| | updateStatements.put(update, new AbstractMap.SimpleEntry<>(updateExp, childRes)); |
---|
| | break; |
---|
| | } |
---|
| | } |
---|
| | // Add statements to the input method. |
---|
| | String[] sideEffects = new String[] {""}; |
---|
| | String curState = updateExp.toImplementation(sideEffects); |
---|
| | String updateStatement; |
---|
| | if (updateExp instanceof Term && ((Term) updateExp).getSymbol().isImplWithSideEffect()) { |
---|
| |
---|
| | srcRes.getResourceName(), |
---|
| | langSpec.getFieldInitializer(srcRes.getResourceStateType(), srcRes.getResourceHierarchy().getInitialValue())); |
---|
| | if (component != null) { |
---|
| | component.addField(cacheField); |
---|
| | } else { |
---|
| | cacheFields.add(cacheField); |
---|
| | } else if (parentComponent != null){ |
---|
| | parentComponent.addField(cacheField); |
---|
| | } |
---|
| | |
---|
| | } |
---|
| | // Update the cache field. |
---|
| |
---|
| | // Update constructor. |
---|
| | if (component != null) { |
---|
| | MethodDeclaration constructor = getConstructor(component); |
---|
| | constructor.addStatement(updateReference); // Initialize the reference field. |
---|
| | } else { |
---|
| | } else if (parentComponent != null){ |
---|
| | constructorStatements.add(updateReference); |
---|
| | } |
---|
| | } |
---|
| | } |
---|
| |
---|
| | // Update constructor. |
---|
| | if (component != null) { |
---|
| | MethodDeclaration constructor = getConstructor(component); |
---|
| | constructor.addStatement(updateReference); // Initialize the reference field. |
---|
| | } else { |
---|
| | } else if (parentComponent != null) { |
---|
| | constructorStatements.add(updateReference); |
---|
| | } |
---|
| | } |
---|
| | } |
---|
| |
---|
| | } |
---|
| | } |
---|
| | } |
---|
| | } |
---|
| | return new AbstractMap.SimpleEntry<>(updateMethods, new AbstractMap.SimpleEntry<>(cacheFields, constructorStatements)); |
---|
| | return new AbstractMap.SimpleEntry<>(constructorStatements, updateStatements); |
---|
| | } |
---|
| | |
---|
| | private Map.Entry<List<MethodDeclaration>, List<String>> declareInputMethodsInThisAndMainComponents(ResourceNode resourceNode, TypeDeclaration component, |
---|
| | TypeDeclaration mainComponent, DataTransferModel model, ILanguageSpecific langSpec) { |
---|
| | private Map.Entry<List<String>, Map<MethodDeclaration, Map.Entry<Expression, ResourceHierarchy>>> declareInputMethodsInThisAndMainComponents(ResourceNode resourceNode, TypeDeclaration component, |
---|
| | TypeDeclaration parentComponent, TypeDeclaration mainComponent, DataTransferModel model, ILanguageSpecific langSpec) { |
---|
| | // Declare input methods. |
---|
| | String resName = resourceNode.getResourceName(); |
---|
| | String resComponentName = langSpec.toComponentName(resName); |
---|
| | List<MethodDeclaration> inputMethods = new ArrayList<>(); |
---|
| | List<String> constructorStatements = new ArrayList<>(); |
---|
| | Map<MethodDeclaration, Map.Entry<Expression, ResourceHierarchy>> inputStatements = new HashMap<>(); |
---|
| | for (Channel ch : model.getIOChannels()) { |
---|
| | for (ChannelMember out : ((DataTransferChannel) ch).getOutputChannelMembers()) { |
---|
| | if (resourceNode.getInSideResources().contains(out.getResource())) { |
---|
| | Expression message = out.getStateTransition().getMessageExpression(); |
---|
| |
---|
| | input = langSpec.newMethodDeclaration(((Term) message).getSymbol().getImplName(), false, null, resInputParams); |
---|
| | if (component != null) { |
---|
| | // A component is created for this resource. |
---|
| | component.addMethod(input); |
---|
| | } else { |
---|
| | } else if (parentComponent != null) { |
---|
| | // No component is created for this resource. |
---|
| | inputMethods.add(input); |
---|
| | parentComponent.addMethod(input); |
---|
| | } |
---|
| | |
---|
| | // Declare the accessor in the main component to call the input method. |
---|
| | String str = ((Term) message).getSymbol().getImplName(); |
---|
| |
---|
| | } |
---|
| | if (component != null) { |
---|
| | // A component is created for this resource. |
---|
| | component.addMethod(input); |
---|
| | } else { |
---|
| | } else if (parentComponent != null) { |
---|
| | // No component is created for this resource. |
---|
| | inputMethods.add(input); |
---|
| | parentComponent.addMethod(input); |
---|
| | } |
---|
| | |
---|
| | // Declare the accessor in the main component to call the input method. |
---|
| | String str = ((Variable) message).getName(); |
---|
| |
---|
| | |
---|
| | if (input != null) { |
---|
| | // Add a statement to update the state field to the input method. |
---|
| | try { |
---|
| | String[] sideEffects = new String[] {""}; |
---|
| | Expression updateExp; |
---|
| | updateExp = ((DataTransferChannel) ch).deriveUpdateExpressionOf(out, getPullAccessor()); |
---|
| | String newState = updateExp.toImplementation(sideEffects); |
---|
| | ResourceHierarchy resource = resourceNode.getResourceHierarchy(); |
---|
| | if (generatesComponent(resource)) { |
---|
| | String updateStatement; |
---|
| | if (updateExp instanceof Term && ((Term) updateExp).getSymbol().isImplWithSideEffect()) { |
---|
| | updateStatement = sideEffects[0]; |
---|
| | Expression updateExp = ((DataTransferChannel) ch).deriveUpdateExpressionOf(out, getPullAccessor()); |
---|
| | // Replace Json constructor with a constructor of the child resource. |
---|
| | ResourceHierarchy outRes = out.getResource().getResourceHierarchy(); |
---|
| | if (outRes.getChildren().size() == 1 && outRes.getChildren().iterator().next().getNumParameters() > 0) { |
---|
| | ResourceHierarchy childRes = outRes.getChildren().iterator().next(); |
---|
| | Type childStateType = childRes.getResourceStateType(); |
---|
| | if (DataConstraintModel.typeJson.isAncestorOf(childStateType)) { |
---|
| | inputStatements.put(input, new AbstractMap.SimpleEntry<>(updateExp, childRes)); |
---|
| | updateExp = null; |
---|
| | } |
---|
| | } |
---|
| | // Add statements to the input method. |
---|
| | if (updateExp != null) { |
---|
| | String[] sideEffects = new String[] {""}; |
---|
| | String newState = updateExp.toImplementation(sideEffects); |
---|
| | ResourceHierarchy resource = resourceNode.getResourceHierarchy(); |
---|
| | if (generatesComponent(resource)) { |
---|
| | String updateStatement; |
---|
| | if (updateExp instanceof Term && ((Term) updateExp).getSymbol().isImplWithSideEffect()) { |
---|
| | updateStatement = sideEffects[0]; |
---|
| | } else { |
---|
| | updateStatement = sideEffects[0] + langSpec.getFieldAccessor(fieldOfResourceState) + langSpec.getAssignment() + newState + langSpec.getStatementDelimiter(); |
---|
| | } |
---|
| | input.addFirstStatement(updateStatement); |
---|
| | } else { |
---|
| | updateStatement = sideEffects[0] + langSpec.getFieldAccessor(fieldOfResourceState) + langSpec.getAssignment() + newState + langSpec.getStatementDelimiter(); |
---|
| | } |
---|
| | input.addFirstStatement(updateStatement); |
---|
| | } else { |
---|
| | String updateStatement = null; |
---|
| | if (updateExp instanceof Term && ((Term) updateExp).getSymbol().isImplWithSideEffect()) { |
---|
| | // ToDo. |
---|
| | updateStatement = sideEffects[0]; |
---|
| | } else { |
---|
| | if (DataConstraintModel.typeList.isAncestorOf(resourceNode.getParent().getResourceStateType())) { |
---|
| | Term selector = new Term(DataConstraintModel.set); |
---|
| | selector.addChild(new Constant(langSpec.getFieldAccessor(fieldOfResourceState))); |
---|
| | selector.addChild(new Variable(input.getParameters().get(input.getParameters().size() - 2).getName())); |
---|
| | selector.addChild(new Constant(newState)); |
---|
| | String[] sideEffects2 = new String[] {""}; |
---|
| | String newList = selector.toImplementation(sideEffects2); |
---|
| | updateStatement = sideEffects[0] + sideEffects2[0]; |
---|
| | } else if (DataConstraintModel.typeMap.isAncestorOf(resourceNode.getParent().getResourceStateType())) { |
---|
| | Term selector = new Term(DataConstraintModel.insert); |
---|
| | selector.addChild(new Constant(langSpec.getFieldAccessor(fieldOfResourceState))); |
---|
| | selector.addChild(new Variable(input.getParameters().get(input.getParameters().size() - 2).getName())); |
---|
| | selector.addChild(new Constant(newState)); |
---|
| | String[] sideEffects2 = new String[] {""}; |
---|
| | String newMap = selector.toImplementation(sideEffects2); |
---|
| | updateStatement = sideEffects[0] + sideEffects2[0]; |
---|
| | String updateStatement = null; |
---|
| | if (updateExp instanceof Term && ((Term) updateExp).getSymbol().isImplWithSideEffect()) { |
---|
| | // ToDo. |
---|
| | updateStatement = sideEffects[0]; |
---|
| | } else { |
---|
| | String resourceName = langSpec.toVariableName(getComponentName(resource, langSpec)); |
---|
| | updateStatement = sideEffects[0] + langSpec.getFieldAccessor(resourceName) + langSpec.getAssignment() + newState + langSpec.getStatementDelimiter(); |
---|
| | } |
---|
| | if (updateStatement != null) { |
---|
| | input.addFirstStatement(updateStatement); |
---|
| | if (DataConstraintModel.typeList.isAncestorOf(resourceNode.getParent().getResourceStateType())) { |
---|
| | Term selector = new Term(DataConstraintModel.set); |
---|
| | selector.addChild(new Constant(langSpec.getFieldAccessor(fieldOfResourceState))); |
---|
| | selector.addChild(new Variable(input.getParameters().get(input.getParameters().size() - 2).getName())); |
---|
| | selector.addChild(new Constant(newState)); |
---|
| | String[] sideEffects2 = new String[] {""}; |
---|
| | String newList = selector.toImplementation(sideEffects2); |
---|
| | updateStatement = sideEffects[0] + sideEffects2[0]; |
---|
| | } else if (DataConstraintModel.typeMap.isAncestorOf(resourceNode.getParent().getResourceStateType())) { |
---|
| | Term selector = new Term(DataConstraintModel.insert); |
---|
| | selector.addChild(new Constant(langSpec.getFieldAccessor(fieldOfResourceState))); |
---|
| | selector.addChild(new Variable(input.getParameters().get(input.getParameters().size() - 2).getName())); |
---|
| | selector.addChild(new Constant(newState)); |
---|
| | String[] sideEffects2 = new String[] {""}; |
---|
| | String newMap = selector.toImplementation(sideEffects2); |
---|
| | updateStatement = sideEffects[0] + sideEffects2[0]; |
---|
| | } else { |
---|
| | String resourceName = langSpec.toVariableName(getComponentName(resource, langSpec)); |
---|
| | updateStatement = sideEffects[0] + langSpec.getFieldAccessor(resourceName) + langSpec.getAssignment() + newState + langSpec.getStatementDelimiter(); |
---|
| | } |
---|
| | if (updateStatement != null) { |
---|
| | input.addFirstStatement(updateStatement); |
---|
| | } |
---|
| | } |
---|
| | } |
---|
| | } |
---|
| | } catch (ParameterizedIdentifierIsFutureWork | ResolvingMultipleDefinitionIsFutureWork |
---|
| |
---|
| | } |
---|
| | } |
---|
| | } |
---|
| | } |
---|
| | return new AbstractMap.SimpleEntry<>(inputMethods, constructorStatements); |
---|
| | return new AbstractMap.SimpleEntry<>(constructorStatements, inputStatements); |
---|
| | } |
---|
| | } |
---|
| | |
---|
| | |