/* * ****************************************************************************** * MontiCore Language Workbench * Copyright (c) 2015, MontiCore, All rights reserved. * * This project is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 3.0 of the License, or (at your option) any later version. * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this project. If not, see <http://www.gnu.org/licenses/>. * ****************************************************************************** */ package de.monticore.codegen.cd2java.ast_emf; import static de.monticore.codegen.GeneratorHelper.getPlainName; import java.util.ArrayList; import java.util.Arrays; import java.util.Collection; import java.util.LinkedHashMap; import java.util.LinkedHashSet; import java.util.List; import java.util.Map; import java.util.Optional; import java.util.Set; import java.util.stream.Collectors; import java.util.stream.Stream; import com.google.common.base.Preconditions; import com.google.common.collect.Lists; import com.google.common.collect.Maps; import de.monticore.codegen.GeneratorHelper; import de.monticore.codegen.cd2java.ast.AstAdditionalAttributes; import de.monticore.codegen.cd2java.ast.AstGeneratorHelper; import de.monticore.codegen.cd2java.ast.CdDecorator; import de.monticore.codegen.cd2java.visitor.VisitorGeneratorHelper; import de.monticore.codegen.mc2cd.TransformationHelper; import de.monticore.codegen.mc2cd.transl.ConstantsTranslation; import de.monticore.generating.templateengine.GlobalExtensionManagement; import de.monticore.generating.templateengine.HookPoint; import de.monticore.generating.templateengine.StringHookPoint; import de.monticore.generating.templateengine.TemplateHookPoint; import de.monticore.io.paths.IterablePath; import de.monticore.symboltable.GlobalScope; import de.monticore.types.TypesHelper; import de.monticore.types.TypesPrinter; import de.monticore.types.types._ast.ASTImportStatement; import de.monticore.types.types._ast.ASTSimpleReferenceType; import de.monticore.umlcd4a.cd4analysis._ast.ASTCDAttribute; import de.monticore.umlcd4a.cd4analysis._ast.ASTCDClass; import de.monticore.umlcd4a.cd4analysis._ast.ASTCDCompilationUnit; import de.monticore.umlcd4a.cd4analysis._ast.ASTCDDefinition; import de.monticore.umlcd4a.cd4analysis._ast.ASTCDEnum; import de.monticore.umlcd4a.cd4analysis._ast.ASTCDEnumConstant; import de.monticore.umlcd4a.cd4analysis._ast.ASTCDInterface; import de.monticore.umlcd4a.cd4analysis._ast.ASTCDMethod; import de.monticore.umlcd4a.cd4analysis._ast.ASTCDType; import de.monticore.umlcd4a.cd4analysis._ast.CD4AnalysisNodeFactory; import de.monticore.umlcd4a.cd4analysis._visitor.CD4AnalysisInheritanceVisitor; import de.monticore.umlcd4a.symboltable.CDFieldSymbol; import de.monticore.umlcd4a.symboltable.CDSymbol; import de.monticore.umlcd4a.symboltable.CDTypeSymbol; import de.se_rwth.commons.Names; import de.se_rwth.commons.StringTransformations; import de.se_rwth.commons.logging.Log; import groovyjarjarantlr.ANTLRException; import transformation.ast.ASTCDRawTransformation; /** * Decorates class diagrams by adding of new classes and methods using in emf * compatible ast files * * @author (last commit) $Author$ * @version $Revision$, $Date$ */ public class CdEmfDecorator extends CdDecorator { public static final String EFACTORY = "Factory"; public static final String EFACTORY_IMPL = "FactoryImpl"; public static final String EPACKAGE = "Package"; public static final String EPACKAGE_IMPL = "PackageImpl"; public static final String HTTP = "http://"; private Map<ASTCDType, List<EmfAttribute>> emfAttributes = new LinkedHashMap<>(); public CdEmfDecorator( GlobalExtensionManagement glex, GlobalScope symbolTable, IterablePath targetPath) { super(glex, symbolTable, targetPath); } public void decorate(ASTCDCompilationUnit cdCompilationUnit) { AstEmfGeneratorHelper astHelper = new AstEmfGeneratorHelper(cdCompilationUnit, symbolTable); // Run over classdiagramm and collects external emf types ETypeCollector emfCollector = new ETypeCollector(astHelper); emfCollector.handle(cdCompilationUnit.getCDDefinition()); ASTCDDefinition cdDefinition = cdCompilationUnit.getCDDefinition(); List<ASTCDClass> nativeClasses = Lists.newArrayList(cdDefinition.getCDClasses()); List<ASTCDType> nativeTypes = astHelper.getNativeTypes(cdDefinition); List<ASTCDClass> astNotAbstractClasses = cdDefinition.getCDClasses().stream() .filter(e -> e.getModifier().isPresent()) .filter(e -> !e.getModifier().get().isAbstract()) .collect(Collectors.toList()); // Run over classdiagramm and converts cd types to mc-java types new Cd2JavaTypeConverter(astHelper).handle(cdDefinition); createEmfAttributes(astHelper, emfCollector, nativeTypes); // Interface for all ast nodes of the language decorateBaseInterface(cdDefinition); // Decorate with builder pattern addBuilders(cdDefinition, astHelper); addNodeFactoryClass(cdCompilationUnit, astNotAbstractClasses, astHelper); // Check if handwritten ast types exist transformCdTypeNamesForHWTypes(cdCompilationUnit); cdDefinition.getCDClasses().stream() .forEach(c -> addSuperInterfaces(c)); // Decorate with additional methods and attributes for (ASTCDClass clazz : nativeClasses) { addConstructors(clazz, astHelper); addAdditionalMethods(clazz, astHelper); // addAdditionalAttributes(clazz, astHelper); addGetter(clazz, astHelper); addSetter(clazz, astHelper); addSymbolGetter(clazz, astHelper); glex.replaceTemplate("ast.AstImports", clazz, new TemplateHookPoint("ast_emf.AstEImports")); } for (ASTCDInterface interf : cdDefinition.getCDInterfaces()) { addGetter(interf); } // Add ASTConstant class addConstantsClass(cdDefinition, astHelper); // Additional imports cdCompilationUnit.getImportStatements().add( ASTImportStatement .getBuilder() .importList( Lists.newArrayList(VisitorGeneratorHelper.getQualifiedVisitorType(astHelper .getPackageName(), cdDefinition.getName()))) .build()); addEmfCode(cdCompilationUnit, nativeClasses, nativeTypes, astHelper, emfCollector.getExternalTypes()); } /** * TODO: Write me! * * @param astHelper * @param astNotListClasses */ void createEmfAttributes(AstEmfGeneratorHelper astHelper, ETypeCollector emfCollector, List<ASTCDType> astTypes) { emfAttributes.clear(); astTypes.stream().filter(t -> t instanceof ASTCDClass) .forEach(t -> ((ASTCDClass) t).getCDAttributes().stream() .filter(a -> !(getAdditionaAttributeNames().anyMatch(ad -> ad.equals(a.getName())))) .forEach(a -> createEmfAttribute(t, a, astHelper, emfCollector))); astTypes.stream().filter(t -> t instanceof ASTCDInterface) .forEach(t -> ((ASTCDInterface) t).getCDAttributes().stream() .filter(a -> !(getAdditionaAttributeNames().anyMatch(ad -> ad.equals(a.getName())))) .forEach(a -> createEmfAttribute(t, a, astHelper, emfCollector))); emfAttributes.keySet() .forEach(t -> AstEmfGeneratorHelper.sortEmfAttributes(emfAttributes.get(t))); } Stream<String> getAdditionaAttributeNames() { return Arrays.asList(AstAdditionalAttributes.values()).stream().map(a -> a.toString()); } /** * TODO: Write me! * * @param astClasses * @param map. */ void addEmfCode(ASTCDCompilationUnit cdCompilationUnit, List<ASTCDClass> astClasses, List<ASTCDType> types, AstEmfGeneratorHelper astHelper, Map<String, String> map) { // addEFactoryInterface(cdCompilationUnit, types, astHelper); // addEFactoryImplementation(cdCompilationUnit, astClasses, astHelper); addEPackageInterface(cdCompilationUnit, types, map.values(), astHelper); addEPackageImplementation(cdCompilationUnit, types, map, astHelper); addLiteralsEnum(cdCompilationUnit, astHelper); // Decorate with additional EMF methods and attributes for (ASTCDClass clazz : astClasses) { addEGetter(clazz, astHelper); addESetter(clazz, astHelper); addEUnset(clazz, astHelper); addEIsSet(clazz, astHelper); addStructuralFeatureMethods(clazz, astHelper); // addValuesForEListAttributes(clazz, astHelper); addToString(clazz, astHelper); addEStaticClass(clazz, astHelper); } } void addEFactoryInterface(ASTCDCompilationUnit cdCompilationUnit, List<ASTCDType> astClasses, AstEmfGeneratorHelper astHelper) { ASTCDDefinition cdDef = cdCompilationUnit.getCDDefinition(); ASTCDInterface factory = CD4AnalysisNodeFactory.createASTCDInterface(); String factoryName = cdDef.getName() + EFACTORY; // Check if a handwritten node factory exists if (TransformationHelper.existsHandwrittenClass(targetPath, TransformationHelper.getAstPackageName(cdCompilationUnit) + factoryName)) { factoryName += TransformationHelper.GENERATED_CLASS_SUFFIX; } factory.setName(factoryName); cdDef.getCDInterfaces().add(factory); for (ASTCDType clazz : astClasses) { if (!clazz.getModifier().isPresent() || clazz.getModifier().get().isAbstract()) { return; } String className = GeneratorHelper.getPlainName(clazz); String toParse = "public static " + className + " create" + className + "() ;"; HookPoint methodBody = new TemplateHookPoint("ast.factorymethods.Create", clazz, className); replaceMethodBodyTemplate(factory, toParse, methodBody); } List<String> classNames = astClasses.stream().map(e -> getPlainName(e)) .collect(Collectors.toList()); glex.replaceTemplate("ast.AstInterfaceContent", factory, new TemplateHookPoint( "ast_emf.EFactory", factory, cdDef.getName(), HTTP + cdDef.getName() + "/1.0", classNames)); } void addEFactoryImplementation(ASTCDCompilationUnit cdCompilationUnit, List<ASTCDClass> astClasses, AstEmfGeneratorHelper astHelper) { ASTCDDefinition cdDef = cdCompilationUnit.getCDDefinition(); ASTCDClass factoryClass = CD4AnalysisNodeFactory.createASTCDClass(); String factoryClassName = cdDef.getName() + EFACTORY_IMPL; // Check if a handwritten node factory exists if (TransformationHelper.existsHandwrittenClass(targetPath, TransformationHelper.getAstPackageName(cdCompilationUnit) + factoryClassName)) { factoryClassName += TransformationHelper.GENERATED_CLASS_SUFFIX; } factoryClass.setName(factoryClassName); List<String> classNames = astClasses.stream() .filter(e -> e.getModifier().isPresent()) .filter(e -> !e.getModifier().get().isAbstract()) .map(e -> getPlainName(e)) .collect(Collectors.toList()); cdDef.getCDClasses().add(factoryClass); glex.replaceTemplate(CLASS_CONTENT_TEMPLATE, factoryClass, new TemplateHookPoint( "ast_emf.EFactoryImpl", factoryClass, cdDef.getName(), HTTP + cdDef.getName() + "/1.0", classNames)); } void addEPackageInterface(ASTCDCompilationUnit cdCompilationUnit, List<ASTCDType> astTypes, Collection<String> externaltypes, AstEmfGeneratorHelper astHelper) { ASTCDDefinition cdDef = cdCompilationUnit.getCDDefinition(); ASTCDInterface packageInterface = CD4AnalysisNodeFactory.createASTCDInterface(); String interfaceName = cdDef.getName() + EPACKAGE; // Check if a handwritten node factory exists if (TransformationHelper.existsHandwrittenClass(targetPath, TransformationHelper.getAstPackageName(cdCompilationUnit) + interfaceName)) { interfaceName += TransformationHelper.GENERATED_CLASS_SUFFIX; } packageInterface.setName(interfaceName); cdDef.getCDInterfaces().add(packageInterface); for (ASTCDType type : astTypes) { List<CDTypeSymbol> superTypes = astHelper.getAllSuperTypesEmfOrder(type); int count = 0; for (CDTypeSymbol interf : superTypes) { List<CDFieldSymbol> attributes = GeneratorHelper.getVisibleFields(interf).stream() .filter(e -> !astHelper.isAttributeOfSuperType(e, interf)) .collect(Collectors.toList()); for (int i = count; i < count + attributes.size(); i++) { String toParseAttr = "int " + getPlainName(type) + "_" + StringTransformations.capitalize(attributes.get(i - count).getName()) + " = " + i + ";"; cdTransformation.addCdAttributeUsingDefinition(packageInterface, toParseAttr); } count += attributes.size(); } List<EmfAttribute> attributes = getEmfAttributes(type).stream() .filter(e -> !astHelper.isAttributeOfSuperType(e.getCdAttribute(), type)) .collect(Collectors.toList()); for (int i = count; i < count + attributes.size(); i++) { EmfAttribute emfAttribute = attributes.get(i - count); String toParseAttr = "int " + emfAttribute.getFullName() + " = " + i + ";"; cdTransformation.addCdAttributeUsingDefinition(packageInterface, toParseAttr); String toParse = emfAttribute.getEmfType() + " get" + emfAttribute.getFullName() + "();"; cdTransformation.addCdMethodUsingDefinition(packageInterface, toParse); } } int i = astTypes.size() + 1; for (String typeName : externaltypes) { String toParseAttr = "int " + typeName + " = " + i + ";"; cdTransformation.addCdAttributeUsingDefinition(packageInterface, toParseAttr); String toParse = "EDataType get" + typeName + "();"; cdTransformation.addCdMethodUsingDefinition(packageInterface, toParse); i++; } List<String> classNames = astTypes.stream().map(e -> getPlainName(e)) .collect(Collectors.toList()); glex.replaceTemplate("ast.AstInterfaceContent", packageInterface, new TemplateHookPoint( "ast_emf.EPackage", packageInterface, cdDef.getName(), HTTP + cdDef.getName() + "/1.0", classNames)); } void addEPackageImplementation(ASTCDCompilationUnit cdCompilationUnit, List<ASTCDType> astClasses, Map<String, String> externaltypes, AstEmfGeneratorHelper astHelper) { ASTCDDefinition cdDef = cdCompilationUnit.getCDDefinition(); ASTCDClass packageImpl = CD4AnalysisNodeFactory.createASTCDClass(); String className = cdDef.getName() + EPACKAGE_IMPL; // Check if a handwritten node factory exists if (TransformationHelper.existsHandwrittenClass(targetPath, TransformationHelper.getAstPackageName(cdCompilationUnit) + className)) { className += TransformationHelper.GENERATED_CLASS_SUFFIX; } packageImpl.setName(className); List<String> classNames = astClasses.stream().map(e -> getPlainName(e)) .collect(Collectors.toList()); for (String clazz : classNames) { String toParse = "protected static " + className + " factory" + clazz + " = null;"; cdTransformation.addCdAttributeUsingDefinition(packageImpl, toParse); } for (ASTCDType type : emfAttributes.keySet()) { List<EmfAttribute> allEmfAttrbutes = getNotInheritedEmfAttributes(type, astHelper); for (int i = 0; i < allEmfAttrbutes.size(); i++) { EmfAttribute emfAttribute = allEmfAttrbutes.get(i); String toParse = "public " + emfAttribute.getEmfType() + " get" + emfAttribute.getFullName() + "();"; HookPoint getMethodBody = new StringHookPoint("return (" + emfAttribute.getEmfType() + ")" + StringTransformations .uncapitalize(getPlainName(emfAttribute.getCdType()).substring(3)) + "EClass.getEStructuralFeatures().get(" + i + ");"); replaceMethodBodyTemplate(packageImpl, toParse, getMethodBody); } } for (String typeName : externaltypes.values()) { String toParse = "public EDataType get" + typeName + "();"; HookPoint getMethodBody = new StringHookPoint( "return " + StringTransformations.uncapitalize(typeName) + "EDataType;"); replaceMethodBodyTemplate(packageImpl, toParse, getMethodBody); } List<EmfAttribute> allEmfAttrbutes = getAllNotInheritedEmfAttributes(astHelper); String toParse = "public void createPackageContents();"; HookPoint getMethodBody = new TemplateHookPoint( "ast_emf.epackagemethods.CreatePackageContents", cdDef.getName(), astClasses, allEmfAttrbutes, externaltypes.values()); replaceMethodBodyTemplate(packageImpl, toParse, getMethodBody); List<String> superCDs = astHelper.getAllSuperCds(astHelper.getCdSymbol()).stream() .map(CDSymbol::getFullName).collect(Collectors.toList()); toParse = "public void initializePackageContents();"; getMethodBody = new TemplateHookPoint( "ast_emf.epackagemethods.InitializePackageContents", cdDef.getName(), superCDs, astClasses, allEmfAttrbutes, externaltypes, GeneratorHelper.getValuesOfConstantEnum(astHelper.getCdDefinition())); replaceMethodBodyTemplate(packageImpl, toParse, getMethodBody); cdDef.getCDClasses().add(packageImpl); glex.replaceTemplate(CLASS_CONTENT_TEMPLATE, packageImpl, new TemplateHookPoint( "ast_emf.EPackageImpl", packageImpl, cdDef.getName(), classNames, externaltypes.values())); } void addSetter(ASTCDClass clazz, AstEmfGeneratorHelper astHelper) { for (EmfAttribute attribute : getEmfAttributes(clazz)) { ASTCDAttribute cdAttribute = attribute.getCdAttribute(); String typeName = TypesHelper.printSimpleRefType(cdAttribute.getType()); if (!AstGeneratorHelper.generateSetter(clazz, cdAttribute, typeName)) { continue; } String methodName = GeneratorHelper.getPlainSetter(cdAttribute); String attributeName = cdAttribute.getName(); boolean isOptional = GeneratorHelper.isOptional(cdAttribute); String toParse = "public void " + methodName + "(" + typeName + " " + attributeName + ") ;"; HookPoint methodBody = new TemplateHookPoint("ast_emf.additionalmethods.Set", astHelper.getCdName(), attribute, attributeName); ASTCDMethod setMethod = replaceMethodBodyTemplate(clazz, toParse, methodBody); if (isOptional) { glex.replaceTemplate(ERROR_IFNULL_TEMPLATE, setMethod, new StringHookPoint("")); } if (isOptional) { toParse = "public boolean " + attributeName + "IsPresent() ;"; methodBody = new StringHookPoint(" return " + attributeName + ".isPresent(); \n"); replaceMethodBodyTemplate(clazz, toParse, methodBody); } } } /** * Adds getter for all attributes of ast classes * * @param clazz * @param astHelper * @throws ANTLRException */ void addEGetter(ASTCDClass clazz, AstEmfGeneratorHelper astHelper) { String toParse = "public Object eGet(int featureID, boolean resolve, boolean coreType);"; HookPoint getMethodBody = new TemplateHookPoint("ast_emf.additionalmethods.EGet", clazz, astHelper.getCdName(), astHelper.getAllVisibleFields(clazz)); replaceMethodBodyTemplate(clazz, toParse, getMethodBody); } /** * Adds setter for all attributes of ast classes * * @param clazz * @param astHelper * @throws ANTLRException */ void addESetter(ASTCDClass clazz, AstEmfGeneratorHelper astHelper) { String toParse = "public void eSet(int featureID, Object newValue);"; HookPoint getMethodBody = new TemplateHookPoint("ast_emf.additionalmethods.ESet", clazz, astHelper.getCdName(), astHelper.getAllVisibleFields(clazz)); Optional<ASTCDMethod> astMethod = cdTransformation.addCdMethodUsingDefinition(clazz, toParse); Preconditions.checkArgument(astMethod.isPresent()); glex.replaceTemplate(EMPTY_BODY_TEMPLATE, astMethod.get(), getMethodBody); glex.replaceTemplate(ERROR_IFNULL_TEMPLATE, astMethod.get(), new StringHookPoint("")); } /** * TODO: Write me! * * @param clazz * @param astHelper */ @Override protected void addAdditionalAttributes(ASTCDClass clazz, AstGeneratorHelper astHelper) { // Add Symbol attribute Optional<ASTCDAttribute> attribute = cdTransformation.addCdAttributeUsingDefinition(clazz, AstAdditionalAttributes.symbol.getDeclaration()); addSetterForAdditionalAttribute(clazz, attribute.get(), "Symbol", AstAdditionalAttributes.symbol.toString(), true); // Add Scope attribute attribute = cdTransformation.addCdAttributeUsingDefinition(clazz, AstAdditionalAttributes.enclosingScope.getDeclaration()); addSetterForAdditionalAttribute(clazz, attribute.get(), "Scope", AstAdditionalAttributes.enclosingScope.toString(), true); } private void addSetterForAdditionalAttribute(ASTCDClass clazz, ASTCDAttribute attribute, String typeName, String attributeName, boolean isOptional) { String toParse = "public void set" + StringTransformations.capitalize(attributeName) + "(" + typeName + " " + attributeName + ") ;"; HookPoint methodBody = new TemplateHookPoint("ast.additionalmethods.Set", clazz, attribute, attributeName); ASTCDMethod setMethod = replaceMethodBodyTemplate(clazz, toParse, methodBody); if (isOptional) { glex.replaceTemplate(ERROR_IFNULL_TEMPLATE, setMethod, new StringHookPoint("")); } if (isOptional) { toParse = "public boolean " + attributeName + "IsPresent() ;"; methodBody = new StringHookPoint(" return " + attributeName + ".isPresent(); \n"); replaceMethodBodyTemplate(clazz, toParse, methodBody); } } /** * Adds setter for all attributes of ast classes * * @param clazz * @param astHelper * @throws ANTLRException */ void addEUnset(ASTCDClass clazz, AstEmfGeneratorHelper astHelper) { String toParse = "public void eUnset(int featureID);"; HookPoint getMethodBody = new TemplateHookPoint("ast_emf.additionalmethods.EUnset", clazz, astHelper.getCdName(), astHelper.getAllVisibleFields(clazz)); replaceMethodBodyTemplate(clazz, toParse, getMethodBody); } /** * Adds setter for all attributes of ast classes * * @param clazz * @param astHelper * @throws ANTLRException */ void addEIsSet(ASTCDClass clazz, AstEmfGeneratorHelper astHelper) { String toParse = "public boolean eIsSet(int featureID);"; HookPoint getMethodBody = new TemplateHookPoint("ast_emf.additionalmethods.EIsSet", clazz, astHelper.getCdName(), astHelper.getAllVisibleFields(clazz)); replaceMethodBodyTemplate(clazz, toParse, getMethodBody); } /** * Adds overriding for the eBaseStructuralFeatureID method i this class has an * interfaces * * @param clazz * @param astHelper */ void addStructuralFeatureMethods(ASTCDClass clazz, AstEmfGeneratorHelper astHelper) { String methodName = "eBaseStructuralFeatureID"; String toParse = "public int " + methodName + "(int featureID, Class<?> baseClass);"; HookPoint getMethodBody = new TemplateHookPoint("ast_emf.additionalmethods.EStructuralFeature", clazz, methodName, astHelper.getAllSuperInterfaces(clazz)); replaceMethodBodyTemplate(clazz, toParse, getMethodBody); methodName = "eDerivedStructuralFeatureID"; toParse = "public int " + methodName + "(int featureID, Class<?> baseClass);"; getMethodBody = new TemplateHookPoint("ast_emf.additionalmethods.EStructuralFeature", clazz, methodName, astHelper.getAllSuperInterfaces(clazz)); replaceMethodBodyTemplate(clazz, toParse, getMethodBody); } /** * TODO: Write me! * * @param clazz * @param astHelper */ void addToString(ASTCDClass clazz, AstEmfGeneratorHelper astHelper) { if (clazz.getCDMethods().stream().anyMatch(m -> "toString".equals(m.getName()))) { return; } String toParse = "public String toString();"; HookPoint getMethodBody = new TemplateHookPoint("ast_emf.additionalmethods.EToString", astHelper.getCdName(), getEmfAttributes(clazz)); replaceMethodBodyTemplate(clazz, toParse, getMethodBody); } /** * TODO: Write me! * * @param clazz * @param astHelper */ void addEStaticClass(ASTCDClass clazz, AstEmfGeneratorHelper astHelper) { String toParse = "protected EClass eStaticClass();"; HookPoint getMethodBody = new StringHookPoint("return " + astHelper.getCdName() + "Package.Literals." + GeneratorHelper.getPlainName(clazz) + ";"); replaceMethodBodyTemplate(clazz, toParse, getMethodBody); } void addEmfAttribute(ASTCDType type, EmfAttribute attribute) { List<EmfAttribute> attributes = emfAttributes.get(type); if (attributes == null) { attributes = new ArrayList<>(); emfAttributes.put(type, attributes); } attributes.add(attribute); } void createEmfAttribute(ASTCDType ast, ASTCDAttribute cdAttribute, AstEmfGeneratorHelper astHelper, ETypeCollector eTypeCollector) { String attributeName = getPlainName(ast) + "_" + StringTransformations.capitalize(GeneratorHelper.getNativeAttributeName(cdAttribute .getName())); boolean isAstNode = astHelper.isAstNode(cdAttribute) || astHelper.isOptionalAstNode(cdAttribute); boolean isAstList = astHelper.isListAstNode(cdAttribute); boolean isOptional = AstGeneratorHelper.isOptional(cdAttribute); boolean isInherited = astHelper.attributeDefinedInOtherCd(cdAttribute); boolean isEnum = !isAstNode && astHelper.isAttributeOfTypeEnum(cdAttribute); boolean hasExternalType = eTypeCollector .isExternalType(astHelper.getNativeTypeName(cdAttribute)); String eDataType = createEDataType(cdAttribute, isAstList, astHelper, eTypeCollector); addEmfAttribute(ast, new EmfAttribute(cdAttribute, ast, attributeName, eDataType, astHelper.getDefinedGrammarName(cdAttribute), isAstNode, isAstList, isOptional, isInherited, astHelper.isExternal(cdAttribute), isEnum, hasExternalType)); } List<EmfAttribute> getEmfAttributes(ASTCDType type) { List<EmfAttribute> attributes = new ArrayList<>(); if (emfAttributes.containsKey(type)) { attributes.addAll(emfAttributes.get(type)); } return attributes; } List<EmfAttribute> getNotInheritedEmfAttributes(ASTCDType type, AstEmfGeneratorHelper astHelper) { List<EmfAttribute> attributes = new ArrayList<>(); if (emfAttributes.containsKey(type)) { emfAttributes.get(type).stream() .filter(e -> !astHelper.isAttributeOfSuperType(e.getCdAttribute(), type)) .forEach(attributes::add); } return attributes; } List<EmfAttribute> getEAttributes(ASTCDType type) { if (!emfAttributes.containsKey(type)) { return new ArrayList<>(); } return emfAttributes.get(type).stream().filter(e -> e.isEAttribute()) .collect(Collectors.toList()); } List<EmfAttribute> getEReferences(ASTCDType type) { if (!emfAttributes.containsKey(type)) { return new ArrayList<>(); } return emfAttributes.get(type).stream().filter(e -> e.isEReference()) .collect(Collectors.toList()); } List<EmfAttribute> getAllEmfAttributes() { List<EmfAttribute> attributes = new ArrayList<>(); emfAttributes.keySet().stream().forEach(t -> attributes.addAll(getEmfAttributes(t))); return attributes; } List<EmfAttribute> getAllNotInheritedEmfAttributes(AstEmfGeneratorHelper astHelper) { List<EmfAttribute> attributes = new ArrayList<>(); emfAttributes.keySet().stream() .forEach(t -> attributes.addAll(getNotInheritedEmfAttributes(t, astHelper))); return attributes; } String createEDataType(ASTCDAttribute cdAttribute, boolean isAstList, AstEmfGeneratorHelper astHelper, ETypeCollector eTypeCollector) { if (isAstList || AstEmfGeneratorHelper.istJavaList(cdAttribute)) { Optional<ASTSimpleReferenceType> typeArg = TypesHelper .getFirstTypeArgumentOfGenericType(cdAttribute.getType(), GeneratorHelper.JAVA_LIST); if (typeArg.isPresent()) { return Names.getSimpleName(TypesHelper .printType(typeArg.get())); } } String nativeType = astHelper.getNativeTypeName(cdAttribute); Optional<String> externalType = eTypeCollector.getExternalType(nativeType); if (externalType.isPresent()) { return externalType.get(); } return Names.getSimpleName(nativeType); } // TODO GV: not used now protected void addAdditionalCreateMethods(ASTCDClass nodeFactoryClass, ASTCDClass clazz) { String className = GeneratorHelper.getPlainName(clazz); String params = "owner, featureID"; String toParse = "public static " + className + " create" + className + "(InternalEObject owner, int featureID) ;"; HookPoint methodBody = new TemplateHookPoint("ast.factorymethods.Create", clazz, className, params); replaceMethodBodyTemplate(nodeFactoryClass, toParse, methodBody); toParse = "protected " + className + " doCreate" + className + "(InternalEObject owner, int featureID) ;"; methodBody = new TemplateHookPoint("ast.factorymethods.DoCreate", clazz, className, params); replaceMethodBodyTemplate(nodeFactoryClass, toParse, methodBody); } /** * @param cdCompilationUnit * @param nativeClasses * @param astHelper * @throws ANTLRException */ protected void addNodeFactoryClass(ASTCDCompilationUnit cdCompilationUnit, List<ASTCDClass> nativeClasses, AstGeneratorHelper astHelper) { // Add factory-attributes for all ast classes Set<String> astClasses = new LinkedHashSet<>(); nativeClasses.stream() .forEach(e -> astClasses.add(GeneratorHelper.getPlainName(e))); ASTCDClass nodeFactoryClass = createNodeFactoryClass(cdCompilationUnit, nativeClasses, astHelper, astClasses); List<String> imports = getImportsForNodeFactory(nodeFactoryClass, astClasses, astHelper); List<String> classNames = nativeClasses.stream() .map(e -> GeneratorHelper.getPlainName(e)) .collect(Collectors.toList()); glex.replaceTemplate(CLASS_CONTENT_TEMPLATE, nodeFactoryClass, new TemplateHookPoint( "ast_emf.AstNodeFactory", nodeFactoryClass, imports, classNames)); } void addLiteralsEnum(ASTCDCompilationUnit ast, AstGeneratorHelper astHelper) { ASTCDDefinition cdDefinition = ast.getCDDefinition(); String constantsEnumName = cdDefinition.getName() + ConstantsTranslation.CONSTANTS_ENUM; Optional<ASTCDEnum> enumConstants = cdDefinition.getCDEnums().stream() .filter(e -> e.getName().equals(constantsEnumName)).findAny(); if (!enumConstants.isPresent()) { Log.error("0xA5000 CdDecorator error: " + constantsEnumName + " class can't be created for the class diagramm " + cdDefinition.getName()); return; } ASTCDEnum astEnum = enumConstants.get(); astEnum.getCDEnumConstants().add(0, ASTCDEnumConstant.getBuilder().name("DEFAULT").build()); astEnum.getInterfaces() .add(new ASTCDRawTransformation().createType("org.eclipse.emf.common.util.Enumerator")); // Add methods of the implemented interface {@link Enumerator} String toParse = "public String getName();"; StringHookPoint methodBody = new StringHookPoint(" return toString(); \n"); replaceMethodBodyTemplate(astEnum, toParse, methodBody); toParse = "public String getLiteral();"; methodBody = new StringHookPoint(" return toString(); \n"); replaceMethodBodyTemplate(astEnum, toParse, methodBody); toParse = "public int getValue();"; methodBody = new StringHookPoint(" return intValue; \n"); replaceMethodBodyTemplate(astEnum, toParse, methodBody); } /** * Collects all external types used in the given class diagram */ public class ETypeCollector implements CD4AnalysisInheritanceVisitor { private AstEmfGeneratorHelper astHelper; private Map<String, String> externalTypes = Maps.newHashMap(); public Map<String, String> getExternalTypes() { return this.externalTypes; } public boolean isExternalType(String nativeType) { return externalTypes.containsKey(nativeType); } public Optional<String> getExternalType(String nativeType) { return Optional.ofNullable(externalTypes.get(nativeType)); } private void addExternalType(String extType, String simpleType) { if (externalTypes.containsKey(extType)) { return; } int i = 0; String typeName = "E" + simpleType; // String typeName = AstEmfGeneratorHelper.getEDataType(simpleType); while (externalTypes.values().contains(typeName)) { typeName = typeName + i; i++; } externalTypes.put(extType, typeName); } public ETypeCollector(AstEmfGeneratorHelper astHelper) { this.astHelper = astHelper; } @Override public void visit(ASTSimpleReferenceType ast) { collectExternalTypes(ast); } private void collectExternalTypes(ASTSimpleReferenceType astType) { String genericType = ""; ASTSimpleReferenceType convertedType = astType; if (AstGeneratorHelper.isOptional(astType)) { Optional<ASTSimpleReferenceType> typeArgument = TypesHelper .getFirstTypeArgumentOfOptional(astType); if (!typeArgument.isPresent()) { return; } convertedType = typeArgument.get(); genericType = AstGeneratorHelper.OPTIONAL; } else if (TypesHelper.isGenericTypeWithOneTypeArgument(astType, AstGeneratorHelper.JAVA_LIST)) { Optional<ASTSimpleReferenceType> typeArgument = TypesHelper .getFirstTypeArgumentOfGenericType(astType, AstGeneratorHelper.JAVA_LIST); if (!typeArgument.isPresent()) { return; } convertedType = typeArgument.get(); genericType = AstGeneratorHelper.JAVA_LIST; } String convertedTypeName = TypesPrinter.printType(convertedType); /* TODO GV if (!genericType.isEmpty() && !convertedTypeName.contains("<")) { String newType = ""; Optional<CDTypeSymbol> symbol = astHelper.resolveCdType(convertedTypeName); if (!symbol.isPresent()) { if (!genericType.isEmpty()) { newType = genericType + "<" + convertedTypeName + ">"; } else { newType = convertedTypeName; } addExternalType(newType, Names.getSimpleName(convertedTypeName)); } else if (symbol.get().isEnum()) { String simpleName = Names.getSimpleName(convertedTypeName); convertedTypeName = symbol.get().getModelName().toLowerCase() + GeneratorHelper.AST_DOT_PACKAGE_SUFFIX_DOT + simpleName; addExternalType(convertedTypeName, simpleName); } } else { String typeName = Names.getQualifiedName(astType.getNames()); addExternalType(typeName, Names.getSimpleName(convertedTypeName)); } */ if (!convertedTypeName.contains(".")) { return; } // TODO: GV, PN: path converter by resolving // TODO GV: typeArgs if (convertedTypeName.contains("<")) { return; } String newType = ""; Optional<CDTypeSymbol> symbol = astHelper.resolveCdType(convertedTypeName); if (!symbol.isPresent()) { if (!genericType.isEmpty()) { newType = genericType + "<" + convertedTypeName + ">"; } else { newType = convertedTypeName; } addExternalType(newType, Names.getSimpleName(convertedTypeName)); } else if (symbol.get().isEnum()) { String simpleName = Names.getSimpleName(convertedTypeName); convertedTypeName = symbol.get().getModelName().toLowerCase() + GeneratorHelper.AST_DOT_PACKAGE_SUFFIX_DOT + simpleName; addExternalType(convertedTypeName, simpleName); } } } }