/** * Copyright 2004-2016 Riccardo Solmi. All rights reserved. * This file is part of the Whole Platform. * * The Whole Platform 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 of the License, or * (at your option) any later version. * * The Whole Platform 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 the Whole Platform. If not, see <http://www.gnu.org/licenses/>. */ package org.whole.gen.lang.reflect; import java.util.HashMap; import java.util.Map; import java.util.Set; import org.eclipse.jdt.core.dom.Expression; import org.eclipse.jdt.core.dom.ExpressionStatement; import org.eclipse.jdt.core.dom.FieldDeclaration; import org.eclipse.jdt.core.dom.MethodDeclaration; import org.eclipse.jdt.core.dom.MethodInvocation; import org.eclipse.jdt.core.dom.TypeDeclaration; import org.eclipse.jdt.core.dom.Modifier.ModifierKeyword; import org.whole.gen.CompilationUnitBuilder; import org.whole.gen.lang.LanguageGenerator; import org.whole.lang.reflect.EntityDescriptor; import org.whole.lang.reflect.EntityDescriptorEnum; import org.whole.lang.util.StringUtils; /** * @author Riccardo Solmi */ @SuppressWarnings("serial") public class EntityDescriptorEnumBuilder extends CompilationUnitBuilder { private String fdEnumName; // private MethodDeclaration constructor; private MethodDeclaration initEntityDescriptors; private MethodDeclaration initForeignTypeRelations; int nextOrdinal = 0; Map<String, String> entities = new HashMap<String, String>(256); // maps names to types Map<String, ExpressionStatement> etypeExpressionMap = new HashMap<String, ExpressionStatement>(256); // maps entityType to argument list of entityDescriptor call @SuppressWarnings("unchecked") public EntityDescriptorEnumBuilder(LanguageGenerator generator) { super(generator); TypeDeclaration typeDec = addClassDeclaration(generator.specificEntityDescriptorEnumName()); typeDec.modifiers().add(0, newSingleMemberAnnotation("SuppressWarnings", "unchecked")); addImportDeclaration(fdEnumName = ((LanguageGenerator) generator).specificFeatureDescriptorEnumName(), false); addImportDeclaration(EntityDescriptorEnum.class.getName(), false); addImportDeclaration(EntityDescriptor.class.getName(), false); addImportDeclaration(generator.modelPackage(), true); setSuperclass(EntityDescriptorEnum.class.getName()); addSerialVersionUID(1L); /*constructor =*/ addSingletonField(); addBodyDeclaration(initEntityDescriptors = newMethodDeclaration("void", "initEntityDescriptors")); initEntityDescriptors.modifiers().clear(); initEntityDescriptors.modifiers().add(ast.newModifier(ModifierKeyword.PROTECTED_KEYWORD)); } protected MethodDeclaration initForeignTypeRelations() { if (initForeignTypeRelations == null) { addBodyDeclaration(initForeignTypeRelations = newMethodDeclaration("void", "initForeignTypeRelations")); initForeignTypeRelations.modifiers().clear(); initForeignTypeRelations.modifiers().add(ast.newModifier(ModifierKeyword.PROTECTED_KEYWORD)); } return initForeignTypeRelations; } public void addSetAssignableFromAll(String... types) { MethodInvocation mi = newMethodInvocation("setAssignableFromAll", newLiteral(true)); for (String type : types) mi.arguments().add(ast.newSimpleName(type+"_ord")); initForeignTypeRelations().getBody().statements().add( newExpressionStatement(mi)); } public void addSetAssignableFromForeignType(String foreignType, String... types) { MethodInvocation mi = newMethodInvocation("setAssignableFromForeignType", newLiteral(true), newLiteral(foreignType)); for (String type : types) mi.arguments().add(ast.newSimpleName(type+"_ord")); initForeignTypeRelations().getBody().statements().add( newExpressionStatement(mi)); } public void addSetAssignableToAll(String... types) { MethodInvocation mi = newMethodInvocation("setAssignableToAll", newLiteral(true)); for (String type : types) mi.arguments().add(ast.newSimpleName(type+"_ord")); initForeignTypeRelations().getBody().statements().add( newExpressionStatement(mi)); } public void addSetAssignableToForeignType(String foreignType, String... types) { MethodInvocation mi = newMethodInvocation("setAssignableToForeignType", newLiteral(true), newLiteral(foreignType)); for (String type : types) mi.arguments().add(ast.newSimpleName(type+"_ord")); initForeignTypeRelations().getBody().statements().add( newExpressionStatement(mi)); } public void addSetAliasOf(String foreignType, String type) { initForeignTypeRelations().getBody().statements().add( newExpressionStatement(newMethodInvocation("setAliasOf", newLiteral(true), newLiteral(foreignType), ast.newSimpleName(type+"_ord")))); } // public void addSupertypes(String eType, String name, Set<String> supertypes) { // if (supertypes.size()>1) {//!supertypes.isEmpty()) { // ExpressionStatement expStm = etypeExpressionMap.get(eType); // Expression edExp = expStm.getExpression(); // // MethodInvocation nfd = newMethodInvocation("withSupertypes"); // expStm.setExpression(nfd); // nfd.setExpression(edExp); // after unparenting edExp // // for (String sType : supertypes) // if (!sType.equals(name)) // nfd.arguments().add(ast.newSimpleName(sType+"_ord")); // } // } @SuppressWarnings("unchecked") public void addSimpleEntity(String eName, String name, String eType, Set<String> modifiers, Set<String> allSubtypes) { String eName_Ord = eName+"_ord"; String oldType = entities.put(eName, eType); if (oldType == null) { //public static final int [eName_ord] = [nextOrdinal]; FieldDeclaration fieldDecl = newFieldDeclaration("int", eName_Ord, newLiteral(nextOrdinal)); fieldDecl.modifiers().remove(0);//assume ModifierKeyword.PRIVATE_KEYWORD fieldDecl.modifiers().add(ast.newModifier(ModifierKeyword.PUBLIC_KEYWORD)); fieldDecl.modifiers().add(ast.newModifier(ModifierKeyword.STATIC_KEYWORD)); fieldDecl.modifiers().add(ast.newModifier(ModifierKeyword.FINAL_KEYWORD)); addBodyDeclaration(nextOrdinal++, fieldDecl); //public static final EntityDescriptor<eName> [eName] = (EntityDescriptor<eName>) instance.valueOf([eName_ord]); fieldDecl = newFieldDeclaration( newParameterizedType(EntityDescriptor.class.getName(), eName), newVariableDeclarationFragment(eName, newCastExpression( newParameterizedType(EntityDescriptor.class.getName(), eName), newMethodInvocation("instance", "valueOf", ast.newSimpleName(eName_Ord))))); fieldDecl.modifiers().remove(0);//assume ModifierKeyword.PRIVATE_KEYWORD fieldDecl.modifiers().add(ast.newModifier(ModifierKeyword.PUBLIC_KEYWORD)); fieldDecl.modifiers().add(ast.newModifier(ModifierKeyword.STATIC_KEYWORD)); fieldDecl.modifiers().add(ast.newModifier(ModifierKeyword.FINAL_KEYWORD)); addBodyDeclaration(nextOrdinal*2, fieldDecl); } else if (oldType.equals(eType)) return; //putSimpleEntity([eName_ord], "[eName]", [eType].class); MethodInvocation callExp = newMethodInvocation("putSimpleEntity"); callExp.arguments().add(ast.newSimpleName(eName_Ord)); callExp.arguments().add(newLiteral(name)); if (!eName.equals(name)) callExp.arguments().add(newLiteral(eName)); callExp.arguments().add(newTypeLiteral(eType)); callExp.arguments().add(newLiteral(modifiers!=null && modifiers.contains("ABSTRACT"))); if (!allSubtypes.isEmpty()) for (String type : allSubtypes) if (!type.equals(name)) callExp.arguments().add(ast.newSimpleName(type+"_ord")); ExpressionStatement expStm = newExpressionStatement(callExp); initEntityDescriptors.getBody().statements().add(expStm); etypeExpressionMap.put(eType, expStm); } @SuppressWarnings("unchecked") public void addFeature(String eType, String fType, String fName, String ofName, Set<String> modifiers) { ExpressionStatement expStm = etypeExpressionMap.get(eType); Expression edExp = expStm.getExpression(); MethodInvocation nfd = newMethodInvocation("withFeature"); expStm.setExpression(nfd); nfd.setExpression(edExp); // after unparenting edExp nfd.arguments().add(ast.newQualifiedName(ast.newSimpleName(StringUtils.toSimpleName(fdEnumName)), ast.newSimpleName(fName))); nfd.arguments().add(ast.newSimpleName(fType+"_ord")); if (ofName != null) nfd.arguments().add(ast.newQualifiedName(ast.newSimpleName(StringUtils.toSimpleName(fdEnumName)), ast.newSimpleName(ofName))); if (ofName != null || (modifiers!=null && !modifiers.isEmpty())) { nfd.arguments().add(newLiteral( modifiers!=null && modifiers.contains("OPTIONAL"))); nfd.arguments().add(newLiteral( modifiers!=null && modifiers.contains("ID"))); nfd.arguments().add(newLiteral( modifiers!=null && modifiers.contains("REFERENCE"))); nfd.arguments().add(newLiteral( modifiers!=null && modifiers.contains("DERIVED"))); nfd.arguments().add(newLiteral( modifiers!=null && modifiers.contains("SHARED"))); } } @SuppressWarnings("unchecked") public void addDataEntity(String eName, String name, String eType, Set<String> modifiers, String fType, String fName) { String eName_Ord = eName+"_ord"; String oldType = entities.put(eName, eType); if (oldType == null) { //public static final int [eName_ord] = [nextOrdinal]; FieldDeclaration fieldDecl = newFieldDeclaration("int", eName_Ord, newLiteral(nextOrdinal)); fieldDecl.modifiers().remove(0);//assume ModifierKeyword.PRIVATE_KEYWORD fieldDecl.modifiers().add(ast.newModifier(ModifierKeyword.PUBLIC_KEYWORD)); fieldDecl.modifiers().add(ast.newModifier(ModifierKeyword.STATIC_KEYWORD)); fieldDecl.modifiers().add(ast.newModifier(ModifierKeyword.FINAL_KEYWORD)); addBodyDeclaration(nextOrdinal++, fieldDecl); //public static final EntityDescriptor<eName> [eName] = (EntityDescriptor<eName>) instance.valueOf([eName_ord]); fieldDecl = newFieldDeclaration( newParameterizedType(EntityDescriptor.class.getName(), eName), newVariableDeclarationFragment(eName, newCastExpression( newParameterizedType(EntityDescriptor.class.getName(), eName), newMethodInvocation("instance", "valueOf", ast.newSimpleName(eName_Ord))))); fieldDecl.modifiers().remove(0);//assume ModifierKeyword.PRIVATE_KEYWORD fieldDecl.modifiers().add(ast.newModifier(ModifierKeyword.PUBLIC_KEYWORD)); fieldDecl.modifiers().add(ast.newModifier(ModifierKeyword.STATIC_KEYWORD)); fieldDecl.modifiers().add(ast.newModifier(ModifierKeyword.FINAL_KEYWORD)); addBodyDeclaration(nextOrdinal*2, fieldDecl); } else if (oldType.equals(eType)) return; //putDataEntity([eName_ord], "[eName]", [eType].class); MethodInvocation callExp = newMethodInvocation("putDataEntity"); callExp.arguments().add(ast.newSimpleName(eName_Ord)); callExp.arguments().add(newLiteral(name)); if (!eName.equals(name)) callExp.arguments().add(newLiteral(eName)); callExp.arguments().add(newTypeLiteral(eType)); callExp.arguments().add(newLiteral(modifiers!=null && modifiers.contains("RELATIONSHIP"))); // newEnumSetOfExpression(EntityModifiers.class.getName(), modifiers)); // if (fType.indexOf('.')!=-1 || fType.endsWith("Enum.Value")) callExp.arguments().add(newQualifiedTypeLiteral(fType)); // else // callExp.arguments().add(newTypeLiteral(fType)); ExpressionStatement expStm = newExpressionStatement(callExp); initEntityDescriptors.getBody().statements().add(expStm); etypeExpressionMap.put(eType, expStm); } @SuppressWarnings("unchecked") public void addCompositeEntity(String eName, String name, String eType, Set<String> modifiers, String elementType, Set<String> compositeModifiers) { // String eName = StringUtils.toSimpleName(eType); String eName_Ord = eName+"_ord"; String oldType = entities.put(eName, eType); if (oldType == null) { //public static final int [eName_ord] = [nextOrdinal]; FieldDeclaration fieldDecl = newFieldDeclaration("int", eName_Ord, newLiteral(nextOrdinal)); fieldDecl.modifiers().remove(0);//assume ModifierKeyword.PRIVATE_KEYWORD fieldDecl.modifiers().add(ast.newModifier(ModifierKeyword.PUBLIC_KEYWORD)); fieldDecl.modifiers().add(ast.newModifier(ModifierKeyword.STATIC_KEYWORD)); fieldDecl.modifiers().add(ast.newModifier(ModifierKeyword.FINAL_KEYWORD)); addBodyDeclaration(nextOrdinal++, fieldDecl); //public static final EntityDescriptor<eName> [eName] = (EntityDescriptor<eName>) instance.valueOf([eName_ord]); fieldDecl = newFieldDeclaration( newParameterizedType(EntityDescriptor.class.getName(), eName), newVariableDeclarationFragment(eName, newCastExpression( newParameterizedType(EntityDescriptor.class.getName(), eName), newMethodInvocation("instance", "valueOf", ast.newSimpleName(eName_Ord))))); fieldDecl.modifiers().remove(0);//assume ModifierKeyword.PRIVATE_KEYWORD fieldDecl.modifiers().add(ast.newModifier(ModifierKeyword.PUBLIC_KEYWORD)); fieldDecl.modifiers().add(ast.newModifier(ModifierKeyword.STATIC_KEYWORD)); fieldDecl.modifiers().add(ast.newModifier(ModifierKeyword.FINAL_KEYWORD)); addBodyDeclaration(nextOrdinal*2, fieldDecl); } else if (oldType.equals(eType)) return; boolean isOrdered = false, isUnique = false, isReference = false, isDerived = false, isShared = false; if (compositeModifiers != null) { isOrdered = compositeModifiers.contains("ORDERED"); isUnique = compositeModifiers.contains("UNIQUE"); isReference = compositeModifiers.contains("REFERENCE"); isDerived = compositeModifiers.contains("DERIVED"); isShared = compositeModifiers.contains("SHARED"); } //putCompositeEntity([eName_ord], "[eName]", [eType].class, ElementType_ord); MethodInvocation callExp = newMethodInvocation("putCompositeEntity"); callExp.arguments().add(ast.newSimpleName(eName_Ord)); callExp.arguments().add(newLiteral(name)); if (!eName.equals(name)) callExp.arguments().add(newLiteral(eName)); callExp.arguments().add(newTypeLiteral(eType)); callExp.arguments().add(newLiteral(modifiers!=null && modifiers.contains("RELATIONSHIP"))); callExp.arguments().add(ast.newSimpleName(generator.entityResolverSimpleName(elementType)+"_ord")); callExp.arguments().add(newLiteral(isOrdered)); callExp.arguments().add(newLiteral(isUnique)); if (isReference || isDerived || isShared) { callExp.arguments().add(newLiteral(isReference)); callExp.arguments().add(newLiteral(isDerived)); callExp.arguments().add(newLiteral(isShared)); } ExpressionStatement expStm = newExpressionStatement(callExp); initEntityDescriptors.getBody().statements().add(expStm); etypeExpressionMap.put(eType, expStm); } @SuppressWarnings("unchecked") public void addMapEntity(String eType, String name, Set<String> modifiers, String keyType, String valueType) { String eName = StringUtils.toSimpleName(eType); String eName_Ord = eName+"_ord"; String oldType = entities.put(eName, eType); if (oldType == null) { //public static final int [eName_ord] = [nextOrdinal]; FieldDeclaration fieldDecl = newFieldDeclaration("int", eName_Ord, newLiteral(nextOrdinal)); fieldDecl.modifiers().remove(0);//assume ModifierKeyword.PRIVATE_KEYWORD fieldDecl.modifiers().add(ast.newModifier(ModifierKeyword.PUBLIC_KEYWORD)); fieldDecl.modifiers().add(ast.newModifier(ModifierKeyword.STATIC_KEYWORD)); fieldDecl.modifiers().add(ast.newModifier(ModifierKeyword.FINAL_KEYWORD)); addBodyDeclaration(nextOrdinal++, fieldDecl); //public static final EntityDescriptor<eName> [eName] = (EntityDescriptor<eName>) instance.valueOf([eName_ord]); fieldDecl = newFieldDeclaration( newParameterizedType(EntityDescriptor.class.getName(), eName), newVariableDeclarationFragment(eName, newCastExpression( newParameterizedType(EntityDescriptor.class.getName(), eName), newMethodInvocation("instance", "valueOf", ast.newSimpleName(eName_Ord))))); fieldDecl.modifiers().remove(0);//assume ModifierKeyword.PRIVATE_KEYWORD fieldDecl.modifiers().add(ast.newModifier(ModifierKeyword.PUBLIC_KEYWORD)); fieldDecl.modifiers().add(ast.newModifier(ModifierKeyword.STATIC_KEYWORD)); fieldDecl.modifiers().add(ast.newModifier(ModifierKeyword.FINAL_KEYWORD)); addBodyDeclaration(nextOrdinal*2, fieldDecl); } else if (oldType.equals(eType)) return; //putMapEntity([eName_ord], "[eName]", [eType].class, ElementType_ord); MethodInvocation callExp = newMethodInvocation("putMapEntity"); callExp.arguments().add(ast.newSimpleName(eName_Ord)); callExp.arguments().add(newLiteral(name)); if (!eName.equals(name)) callExp.arguments().add(newLiteral(eName)); callExp.arguments().add(newTypeLiteral(eType)); callExp.arguments().add(newLiteral(modifiers!=null && modifiers.contains("RELATIONSHIP"))); // newEnumSetOfExpression(EntityModifiers.class.getName(), modifiers)); callExp.arguments().add(ast.newSimpleName(generator.entityResolverSimpleName(keyType)+"_ord")); callExp.arguments().add(ast.newSimpleName(generator.entityResolverSimpleName(valueType)+"_ord")); ExpressionStatement expStm = newExpressionStatement(callExp); initEntityDescriptors.getBody().statements().add(expStm); etypeExpressionMap.put(eType, expStm); } @SuppressWarnings("unchecked") public Expression newEnumSetOfExpression(String enumType, Set<String> enumConstants) { if (enumConstants.isEmpty()) return newMethodInvocation("noneOf"+StringUtils.toSimpleName(enumType)); // return newMethodInvocation("noneOf", newTypeLiteral(enumType)); MethodInvocation callExp = newMethodInvocation("of"); for (String enumConstant : enumConstants) callExp.arguments().add( enumConstant.equals("REFERENCE")||enumConstant.equals("DERIVED")||enumConstant.equals("SHARED") ? newMethodInvocation(StringUtils.toSimpleName(enumType)+enumConstant) : newSimpleName(enumConstant)); // newFieldAccess(enumType, enumConstant)); return callExp; } }