/*
* ******************************************************************************
* 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 java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.Comparator;
import java.util.List;
import java.util.Optional;
import java.util.stream.Collectors;
import de.monticore.codegen.GeneratorHelper;
import de.monticore.codegen.cd2java.ast.AstGeneratorHelper;
import de.monticore.codegen.mc2cd.manipul.BaseInterfaceAddingManipulation;
import de.monticore.emf._ast.ASTECNode;
import de.monticore.emf._ast.ASTENodePackage;
import de.monticore.symboltable.GlobalScope;
import de.monticore.types.TypesHelper;
import de.monticore.types.TypesPrinter;
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.ASTCDType;
import de.monticore.umlcd4a.symboltable.CDFieldSymbol;
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;
/**
* A helper for emf-compatible generation
*/
public class AstEmfGeneratorHelper extends AstGeneratorHelper {
public static final String JAVA_MAP = "java.util.Map";
public AstEmfGeneratorHelper(ASTCDCompilationUnit topAst, GlobalScope symbolTable) {
super(topAst, symbolTable);
}
public String getPackageURI() {
return "http://" + getCdName() + "/1.0";
}
/**
* @return externalTypes
*/
@Override
public String getAstAttributeValue(ASTCDAttribute attribute, ASTCDType clazz) {
if (attribute.getValue().isPresent()) {
return attribute.printValue();
}
if (isOptional(attribute)) {
return "Optional.empty()";
}
String typeName = TypesPrinter.printType(attribute.getType());
if (isListType(typeName)) {
String attributeName = getPlainName(clazz) + "_"
+ StringTransformations.capitalize(GeneratorHelper.getNativeAttributeName(attribute
.getName()));
Optional<ASTSimpleReferenceType> typeArg = TypesHelper
.getFirstTypeArgumentOfGenericType(attribute.getType(), JAVA_LIST);
if (typeArg.isPresent()) {
String typeArgName = TypesHelper.printType(typeArg.get());
if (Names.getQualifier(typeArgName).equals(getAstPackage())) {
typeName = Names.getSimpleName(typeArgName);
return "new EObjectContainmentEList<" + typeName + ">(" + typeName + ".class, this, "
+ this.getCdName() + "Package." + attributeName + ")";
}
else {
typeName = typeArgName;
return "new EDataTypeEList<" + typeName + ">(" + typeName + ".class, this, "
+ this.getCdName() + "Package." + attributeName + ")";
}
}
}
if (isMapType(typeName)) {
return "new java.util.HashMap<>()";
}
return "";
}
public String getNativeTypeName(ASTCDAttribute attribute) {
if (isOptional(attribute)) {
return TypesHelper
.printType(TypesHelper.getSimpleReferenceTypeFromOptional(attribute.getType()));
}
if (isListAstNode(attribute)) {
Optional<ASTSimpleReferenceType> typeArg = TypesHelper
.getFirstTypeArgumentOfGenericType(attribute.getType(), JAVA_LIST);
if (typeArg.isPresent()) {
return printType(typeArg.get());
}
}
return attribute.printType();
}
public List<String> getASTESuperPackages() {
List<String> ePackages = new ArrayList<>();
for (String superGrammar : getSuperGrammarCds()) {
ePackages.add(getEPackageName(superGrammar));
}
if (ePackages.isEmpty()) {
ePackages.add(ASTENodePackage.class.getName());
}
return ePackages;
}
/**
* Get all native (not created by decorators) cd types
*
* @param cdDefinition
* @return
*/
public List<ASTCDType> getNativeTypes(ASTCDDefinition cdDefinition) {
List<ASTCDType> types = new ArrayList<>(cdDefinition.getCDClasses());
types.addAll(cdDefinition.getCDInterfaces());
String genNode = BaseInterfaceAddingManipulation.getBaseInterfaceName(getCdDefinition());
return types.stream().filter(c -> !c.getName().equals(genNode))
.collect(Collectors.toList());
}
public boolean attributeDefinedInOtherCd(ASTCDAttribute attribute) {
String definedGrammar = getDefinedGrammarName(attribute);
return !definedGrammar.isEmpty()
&& !definedGrammar.equalsIgnoreCase(getQualifiedCdName());
}
public String getDefinedGrammarName(ASTCDAttribute attribute) {
String type = getNativeTypeName(attribute);
if (isAstNode(attribute) || isListAstNode(attribute) || isOptional(attribute)) {
return Names.getQualifier(Names.getQualifier(type));
}
return type;
}
/**
* Gets super types recursively (without duplicates - the first occurrence in
* the type hierarchy is used) in the order according to the EMF-generator
* requirements
*
* @param type
* @return all supertypes (without the type itself)
*/
public List<CDTypeSymbol> getAllSuperTypesEmfOrder(ASTCDType type) {
if (!type.getSymbol().isPresent()) {
Log.error("0xA4097 Could not load symbol information for " + type.getName() + ".");
}
CDTypeSymbol sym = (CDTypeSymbol) type.getSymbol().get();
return getAllSuperTypesEmfOrder(sym);
}
/**
* Gets super types recursively (without duplicates - the first occurrence in
* the type hierarchy is used) in the order according to the EMF-generator
* requirements
*
* @param type
* @return all supertypes (without the type itself)
*/
public List<CDTypeSymbol> getAllSuperTypesEmfOrder(CDTypeSymbol type) {
List<CDTypeSymbol> allSuperTypes = new ArrayList<>();
for (CDTypeSymbol s : type.getSuperTypes()) {
List<CDTypeSymbol> supers = getAllSuperTypesEmfOrder(s);
for (CDTypeSymbol sup : supers) {
addIfNotContained(sup, allSuperTypes);
}
addIfNotContained(s, allSuperTypes);
}
return allSuperTypes;
}
/**
* Gets super types recursively (without duplicates - the first occurrence in
* the type hierarchy is used) in the order according to the EMF-generator
* requirements
*
* @param type
* @return all supertypes (without the type itself)
*/
public List<CDTypeSymbol> getAllTypesEmfOrder(ASTCDType type) {
if (!type.getSymbol().isPresent()) {
Log.error("0xA4098 Could not load symbol information for " + type.getName() + ".");
}
CDTypeSymbol sym = (CDTypeSymbol) type.getSymbol().get();
List<CDTypeSymbol> types = getAllSuperTypesEmfOrder(sym);
types.add(sym);
return types;
}
/**
* TODO: Write me!
*
* @param cdType
* @return
*/
public Collection<CDFieldSymbol> getAllVisibleFields(ASTCDType type) {
List<CDFieldSymbol> allSuperTypeFields = new ArrayList<>();
if (!type.getSymbol().isPresent()) {
Log.error("0xA4099 Could not load symbol information for " + type.getName() + ".");
return new ArrayList<>();
}
CDTypeSymbol sym = (CDTypeSymbol) type.getSymbol().get();
for (CDTypeSymbol sup : getAllSuperTypesEmfOrder(sym)) {
sup.getFields().forEach(a -> addIfNotContained(a, allSuperTypeFields));
}
// filter-out all private fields
List<CDFieldSymbol> allFields = allSuperTypeFields.stream()
.filter(field -> !field.isPrivate()).collect(Collectors.toList());
// add own fields if not inherited
sym.getFields().stream()
.filter(e -> !isAttributeOfSuperType(e, sym)).forEach(allFields::add);
return allFields;
}
// TODO: fix me
public boolean isExternal(ASTCDAttribute attribute) {
return getNativeTypeName(attribute).endsWith("Ext");
}
public String getDefaultValue(CDFieldSymbol attribute) {
if (isAstNode(attribute)) {
return "null";
}
if (isOptional(attribute)) {
return "Optional.empty()";
}
String typeName = attribute.getType().getName();
switch (typeName) {
case "boolean":
return "false";
case "int":
return "0";
case "short":
return "(short) 0";
case "long":
return "0";
case "float":
return "0.0f";
case "double":
return "0.0";
case "char":
return "'\u0000'";
default:
return "null";
}
}
public static String getEPackageName(String qualifiedSuperGrammar) {
return qualifiedSuperGrammar.toLowerCase() + "._ast."
+ StringTransformations.capitalize(Names.getSimpleName(qualifiedSuperGrammar)) + "Package";
}
public String getIdentifierName(String qualifiedName) {
return Names.getSimpleName(qualifiedName) + "_"
+ Names.getQualifier(qualifiedName).replace('.', '_');
}
public static boolean istJavaList(ASTCDAttribute attribute) {
return TypesPrinter.printTypeWithoutTypeArgumentsAndDimension(attribute.getType())
.equals(JAVA_LIST);
}
public static String getEmfRuntimePackage() {
return "de.monticore.emf._ast";
}
public static String getEDataType(String typeName) {
switch (typeName) {
case JAVA_LIST:
return "Elist";
case JAVA_MAP:
return "EMap";
case "boolean":
return "EBoolean";
case "Boolean":
return "EBooleanObject";
case "int":
return "EInt";
case "Integer":
return "EIntegerObject";
case "byte":
return "EByte";
case "Byte":
return "EByteObject";
case "short":
return "EShort";
case "Short":
return "EShortObject";
case "long":
return "ELong";
case "Long":
return "ELongObject";
case "double":
return "EDouble";
case "Double":
return "EDoubleObject";
case "float":
return "EFloat";
case "Float":
return "EFloatObject";
case "char":
return "EChar";
case "Character":
return "ECharacterObject";
default:
return "E" + typeName;
}
}
public static String getSuperClass(ASTCDClass clazz) {
if (!clazz.getSuperclass().isPresent()) {
return ASTECNode.class.getName();
}
return clazz.printSuperClass();
}
public static List<EmfAttribute> getSortedEmfAttributes(List<EmfAttribute> list) {
List<EmfAttribute> sortedAttributes = new ArrayList<>(list);
Collections.sort(sortedAttributes, new Comparator<EmfAttribute>() {
public int compare(EmfAttribute attr1, EmfAttribute attr2) {
return attr1.getAttributeName().compareTo(attr2.getAttributeName());
}
});
return sortedAttributes;
}
public static void sortEmfAttributes(List<EmfAttribute> list) {
Collections.sort(list, new Comparator<EmfAttribute>() {
public int compare(EmfAttribute attr1, EmfAttribute attr2) {
return attr1.getAttributeName().compareTo(attr2.getAttributeName());
}
});
}
}