diff --git a/AlgebraicDataflowArchitectureModel/src/generators/CodeGenerationContext.java b/AlgebraicDataflowArchitectureModel/src/generators/CodeGenerationContext.java new file mode 100644 index 0000000..157806d --- /dev/null +++ b/AlgebraicDataflowArchitectureModel/src/generators/CodeGenerationContext.java @@ -0,0 +1,144 @@ +package generators; + +import java.util.HashMap; +import java.util.Map; +import java.util.Set; + +import code.ast.TypeDeclaration; +import models.algebra.Type; +import models.dataConstraintModel.DataConstraintModel; +import models.dataConstraintModel.ListType; +import models.dataConstraintModel.MapType; +import models.dataConstraintModel.ResourceHierarchy; +import models.dataFlowModel.DataTransferChannel; + +public class CodeGenerationContext { + protected HashMap> componentNames = new HashMap<>(); + protected Map resourceHierarchyToComponent; + protected Map componentNameToType; + protected Map>> updateMethods; + protected ILanguageSpecific langSpec = null; + protected IPlatformSpecific platformSpec = null; + + public CodeGenerationContext(ILanguageSpecific langSpec, IPlatformSpecific platformSpec) { + this.resourceHierarchyToComponent = new HashMap<>(); + this.componentNameToType = new HashMap<>(); + this.updateMethods = new HashMap<>(); + this.langSpec = langSpec; + this.platformSpec = platformSpec; + } + + public String getComponentName(ResourceHierarchy res, ILanguageSpecific langSpec) { + String name = res.getResourceName(); + if (res.getNumParameters() > 0) { + if (name.length() > 3 && name.endsWith("ies")) { + name = name.substring(0, name.length() - 3) + "y"; + } else if (name.length() > 1 && name.endsWith("s")) { + name = name.substring(0, name.length() - 1); + } else { + name += "Element"; + } + } + String componentName = langSpec.toComponentName(name); + if (!generatesComponent(res)) return componentName; + // To avoid generating multiple components with the same name. + HashMap resToName = componentNames.get(componentName); + if (resToName == null) { + resToName = new HashMap<>(); + resToName.put(res, componentName); + componentNames.put(componentName, resToName); + return componentName; + } + if (resToName.get(res) == null) { + componentName += resToName.size(); + resToName.put(res, componentName); + return componentName; + } + return resToName.get(res); + } + + public Type getOrCreateComponentType(ResourceHierarchy res) { + return getOrCreateComponentType(getComponentName(res, langSpec)); + } + + public Type getOrCreateComponentType(String componentName) { + Type componentType = componentNameToType.get(componentName); + if (componentType != null) return componentType; + componentType = new Type(componentName, new code.ast.SimpleType(componentName)); + componentNameToType.put(componentName, componentType); + return componentType; + } + + public Type getImplStateType(ResourceHierarchy res, ILanguageSpecific langSpec) { + Set children = res.getChildren(); + if (children == null || children.size() == 0) { + // leaf resource. + return res.getResourceStateType(); + } else { + ResourceHierarchy child = children.iterator().next(); + if (children.size() == 1 && child.getNumParameters() > 0) { + // map or list. + if (DataConstraintModel.typeList.isAncestorOf(res.getResourceStateType()) || res.getResourceStateType() instanceof ListType) { + // list. + if (generatesComponent(child)) { + return langSpec.newListType(getOrCreateComponentType(child)); + } else { + return langSpec.newListType(getImplStateType(child, langSpec)); + } + } else if (DataConstraintModel.typeMap.isAncestorOf(res.getResourceStateType()) || res.getResourceStateType() instanceof MapType) { + // map. + if (generatesComponent(child)) { + return langSpec.newMapType(DataConstraintModel.typeString, getOrCreateComponentType(child).getInterfaceTypeName()); + } else { + return langSpec.newMapType(DataConstraintModel.typeString, getImplStateType(child, langSpec).getInterfaceTypeName()); + } + } + return null; + } else { + // class + return res.getResourceStateType(); + } + } + } + + public boolean generatesComponent(ResourceHierarchy res) { + if (res.getParent() == null) return true; + if (res.getChildren() == null || res.getChildren().size() == 0) return false; + if (res.getNumParameters() > 0 && res.getChildren().size() == 1 && res.getChildren().iterator().next().getNumParameters() > 0) return false; + if (res.getChildren().size() == 1 && res.getChildren().iterator().next().getNumParameters() > 0 + && (res.getChildren().iterator().next().getChildren() == null || res.getChildren().iterator().next().getChildren().size() == 0)) return false; + return true; +// return res.getParent() == null || !(res.getChildren() == null || res.getChildren().size() == 0); + } + + public void putComponent(ResourceHierarchy res, TypeDeclaration component) { + resourceHierarchyToComponent.put(res, component); + } + + public TypeDeclaration getComponent(ResourceHierarchy res) { + return resourceHierarchyToComponent.get(res); + } + + + public String getOrPutUpdateMethodName(ResourceHierarchy srcRes, DataTransferChannel ch, ResourceHierarchy dstRes) { + Map> dstResUpdatesMethods = updateMethods.getOrDefault(dstRes, new HashMap<>()); + updateMethods.put(dstRes, dstResUpdatesMethods); + Map dstResFromSrcResUpdatesMethods = dstResUpdatesMethods.getOrDefault(srcRes, new HashMap<>()); + dstResUpdatesMethods.put(srcRes, dstResFromSrcResUpdatesMethods); + String updateMethodName = dstResFromSrcResUpdatesMethods.get(ch); + if (updateMethodName == null) { + String srcResComponentName = getComponentName(srcRes, langSpec); + String dstResComponentName = getComponentName(dstRes, langSpec); + if (generatesComponent(dstRes)) { + updateMethodName = CodeGenerator.updateMethodPrefix + CodeGenerator.from + srcResComponentName; + } else if (dstRes.getParent() != null) { + updateMethodName = CodeGenerator.updateMethodPrefix + dstResComponentName + CodeGenerator.from + srcResComponentName; + } + if (dstResFromSrcResUpdatesMethods.size() > 0) { + updateMethodName += dstResFromSrcResUpdatesMethods.size() + 1; // To avoid declaring the method multiply. + } + dstResFromSrcResUpdatesMethods.put(ch, updateMethodName); + } + return updateMethodName; + } +}