r1816 - trunk/topia-persistence/src/main/java/org/nuiton/topia/generator
Author: tchemit Date: 2010-02-26 19:52:36 +0100 (Fri, 26 Feb 2010) New Revision: 1816 Modified: trunk/topia-persistence/src/main/java/org/nuiton/topia/generator/DAOAbstractTransformer.java trunk/topia-persistence/src/main/java/org/nuiton/topia/generator/DAOHelperTransformer.java trunk/topia-persistence/src/main/java/org/nuiton/topia/generator/EntityAbstractTransformer.java trunk/topia-persistence/src/main/java/org/nuiton/topia/generator/TopiaGeneratorUtil.java Log: - Evolution #331: Add methods findUsages on TopiaDAO api - Evolution #332: Add getModelName method on generated DAOHelper - reformat code (80 caracters max on a line) - use caracters rather than one string Modified: trunk/topia-persistence/src/main/java/org/nuiton/topia/generator/DAOAbstractTransformer.java =================================================================== --- trunk/topia-persistence/src/main/java/org/nuiton/topia/generator/DAOAbstractTransformer.java 2010-02-26 18:48:25 UTC (rev 1815) +++ trunk/topia-persistence/src/main/java/org/nuiton/topia/generator/DAOAbstractTransformer.java 2010-02-26 18:52:36 UTC (rev 1816) @@ -31,6 +31,7 @@ import org.nuiton.topia.framework.TopiaContextImplementor; import org.nuiton.topia.persistence.TopiaDAO; import org.nuiton.topia.persistence.TopiaDAOImpl; +import org.nuiton.topia.persistence.TopiaEntity; import org.nuiton.util.StringUtil; import java.util.*; @@ -60,8 +61,16 @@ */ private static final Log log = LogFactory.getLog( DAOAbstractTransformer.class); - + + Map<ObjectModelClass, Set<ObjectModelClass>> usages; + @Override + public void transformFromModel(ObjectModel model) { + + usages = TopiaGeneratorUtil.searchDirectUsages(model); + } + + @Override public void transformFromClass(ObjectModelClass clazz) { if (!clazz.hasStereotype(TopiaGeneratorUtil.STEREOTYPE_ENTITY)) { return; @@ -70,7 +79,7 @@ String clazzName = clazz.getName(); ObjectModelClass result = createAbstractClass( - clazzName + "DAOAbstract<E extends " + clazzName + ">", + clazzName + "DAOAbstract<E extends " + clazzName + '>', clazz.getPackageName()); // super class @@ -148,91 +157,14 @@ generateDAOOperations(result, DAOoperations); - // delete - - op = addOperation(result, "delete", "void", ObjectModelModifier.PUBLIC); - addException(op, TopiaException.class); - addParameter(op, "E", "entity"); - StringBuilder body = new StringBuilder(); - String modelName = StringUtils.capitalize(model.getName()); - String providerFQN = getOutputProperties().getProperty( - Template.PROP_DEFAULT_PACKAGE) + "." + modelName + - "DAOHelper.getImplementationClass"; - for (ObjectModelAttribute attr : clazz.getAttributes()) { - String attrType = attr.getType(); - String reverseAttrName = attr.getReverseAttributeName(); - ObjectModelAttribute reverse = attr.getReverseAttribute(); - if (!attr.hasAssociationClass() && reverse != null && reverse.isNavigable() - && GeneratorUtil.isNMultiplicity(attr) && GeneratorUtil.isNMultiplicity(reverse)) { - // On doit absolument supprimer pour les relations many-to-many - // le this de la collection de l'autre cote + generateDelete(clazz,result); - String attrDBName = TopiaGeneratorUtil.getDBName(attr); - String attrClassifierDBName = TopiaGeneratorUtil.getDBName(attr.getClassifier()); - String attrJoinTableName = TopiaGeneratorUtil.getManyToManyTableName(attr); - String attrReverseDBName = TopiaGeneratorUtil.getReverseDBName(attr); - body.append("" -/*{ - { - List<<%=attrType%>> list = getContext().getHibernate().createSQLQuery( - "SELECT main.topiaid " + - "from <%=attrClassifierDBName%> main, <%=attrJoinTableName%> secondary " + - "where main.topiaid=secondary.<%=attrDBName%>" + - " and secondary.<%=attrReverseDBName%>='" + entity.getTopiaId() + "'") - .addEntity("main", <%=providerFQN%>(<%=attrType%>.class)).list(); - for (<%=attrType%> item : list) { - item.remove<%=StringUtils.capitalize(reverseAttrName)%>(entity); - } - } -}*/ - ); - } else if (!attr.hasAssociationClass() && reverse != null - && reverse.isNavigable() - && !GeneratorUtil.isNMultiplicity(reverse)) { - // On doit mettre a null les attributs qui ont cet objet sur les - // autres entites en one-to-* - // TODO peut-etre qu'hibernate est capable de faire ca tout seul ? - // THIMEL: J'ai remplacé reverse.getName() par reverseAttrName sans certitude - body.append("" - /*{ - { - List<<%=attrType%>> list = getContext() - .getDAO(<%=attrType%>.class) - .findAllByProperties("<%=reverseAttrName%>", entity); - for (<%=attrType%> item : list) { - item.set<%=StringUtils.capitalize(reverseAttrName)%>(null); -}*/ - ); - if(attr.isAggregate()){ - body.append("" -/*{ - item.delete(); -}*/ - ); - } - body.append("" -/*{ - } - } -}*/ - ); - - } - } - body.append("" -/*{ - super.delete(entity); - }*/ - ); - setOperationBody(op,body.toString()); - generateNaturalId(result, clazz); for (ObjectModelAttribute attr : clazz.getAttributes()) { if (!attr.isNavigable()) { continue; } - String attrName = attr.getName(); if (!GeneratorUtil.isNMultiplicity(attr)) { generateNoNMultiplicity(clazzName, result, attr, false); @@ -345,8 +277,274 @@ }*/ ); } + + Set<ObjectModelClass> usagesForclass = usages.get(clazz); + generateFindUsages(clazz,result,usagesForclass); } + private void generateDelete(ObjectModelClass clazz, + ObjectModelClass result) { + ObjectModelOperation op; + op = addOperation(result, "delete", "void", ObjectModelModifier.PUBLIC); + addException(op, TopiaException.class); + addParameter(op, "E", "entity"); + StringBuilder body = new StringBuilder(); + String modelName = StringUtils.capitalize(model.getName()); + String providerFQN = getOutputProperties().getProperty( + Template.PROP_DEFAULT_PACKAGE) + '.' + modelName + + "DAOHelper.getImplementationClass"; + for (ObjectModelAttribute attr : clazz.getAttributes()) { + String attrType = attr.getType(); + String reverseAttrName = attr.getReverseAttributeName(); + ObjectModelAttribute reverse = attr.getReverseAttribute(); + if (!attr.hasAssociationClass() && reverse != null && reverse.isNavigable() + && GeneratorUtil.isNMultiplicity(attr) && GeneratorUtil.isNMultiplicity(reverse)) { + // On doit absolument supprimer pour les relations many-to-many + // le this de la collection de l'autre cote + + String attrDBName = TopiaGeneratorUtil.getDBName(attr); + String attrClassifierDBName = TopiaGeneratorUtil.getDBName(attr.getClassifier()); + String attrJoinTableName = TopiaGeneratorUtil.getManyToManyTableName(attr); + String attrReverseDBName = TopiaGeneratorUtil.getReverseDBName(attr); + body.append("" +/*{ + { + List<<%=attrType%>> list = getContext().getHibernate().createSQLQuery( + "SELECT main.topiaid " + + "from <%=attrClassifierDBName%> main, <%=attrJoinTableName%> secondary " + + "where main.topiaid=secondary.<%=attrDBName%>" + + " and secondary.<%=attrReverseDBName%>='" + entity.getTopiaId() + "'") + .addEntity("main", <%=providerFQN%>(<%=attrType%>.class)).list(); + for (<%=attrType%> item : list) { + item.remove<%=StringUtils.capitalize(reverseAttrName)%>(entity); + } + } +}*/ + ); + } else if (!attr.hasAssociationClass() && reverse != null + && reverse.isNavigable() + && !GeneratorUtil.isNMultiplicity(reverse)) { + // On doit mettre a null les attributs qui ont cet objet sur les + // autres entites en one-to-* + // TODO peut-etre qu'hibernate est capable de faire ca tout seul ? + // THIMEL: J'ai remplacé reverse.getName() par reverseAttrName sans certitude + builder.addImport(result, attrType); + String attrSimpleType = TopiaGeneratorUtil.getClassNameFromQualifiedName(attrType); + + body.append("" + /*{ + { + List<<%=attrSimpleType%>> list = getContext() + .getDAO(<%=attrSimpleType%>.class) + .findAllByProperties(<%=attrSimpleType%>.<%=getConstantName(reverseAttrName)%>, entity); +// .findAllByProperties("<%=reverseAttrName%>", entity); + for (<%=attrSimpleType%> item : list) { + item.set<%=StringUtils.capitalize(reverseAttrName)%>(null); +}*/ + ); + if(attr.isAggregate()){ + body.append("" +/*{ + item.delete(); +}*/ + ); + } + body.append("" +/*{ + } + } +}*/ + ); + + } + } + body.append("" +/*{ + super.delete(entity); + }*/ + ); + + setOperationBody(op,body.toString()); + } + private void generateFindUsages(ObjectModelClass clazz, + ObjectModelClass result, + Set<ObjectModelClass> usagesForclass) { + + builder.addImport(result, ArrayList.class.getName()); + builder.addImport(result, Map.class.getName()); + builder.addImport(result, HashMap.class.getName()); + builder.addImport(result, TopiaEntity.class.getName()); + + if (clazz instanceof ObjectModelAssociationClass || usagesForclass.isEmpty()) { + // not for an association class + // just let a null method + ObjectModelOperation operation; + operation = addOperation(result, + "findUsages", + "<U extends TopiaEntity> List<U>", + ObjectModelModifier.PUBLIC); + + addParameter(operation, "Class<U>", "type"); + addParameter(operation, "E", "entity"); + addException(operation, TopiaException.class); + addAnnotation(result, operation,"Override"); + setOperationBody(operation,"" +/*{ + return new ArrayList<U>(); + }*/ + ); + + operation = addOperation(result, + "findAllUsages", + "Map<Class<?>, List<? extends TopiaEntity>>", + ObjectModelModifier.PUBLIC); + + addParameter(operation, "E", "entity"); + addException(operation, TopiaException.class); + addAnnotation(result, operation,"Override"); + setOperationBody(operation, "" +/*{ + return new HashMap<Class<?>, List<? extends TopiaEntity>>(); + }*/ + ); + + return; + } + List<ObjectModelClass> allEntities; + Map<String, ObjectModelClass> allEntitiesByFQN; + + allEntities = TopiaGeneratorUtil.getEntityClasses(model, true); + allEntitiesByFQN = new TreeMap<String, ObjectModelClass>(); + + // prepare usages map and fill allEntitiesByFQN map + for (ObjectModelClass klass : allEntities) { + allEntitiesByFQN.put(klass.getQualifiedName(), klass); + } + + ObjectModelOperation operation; + operation = addOperation(result, + "findUsages", + "<U extends TopiaEntity> List<U>", + ObjectModelModifier.PUBLIC); + + addParameter(operation,"Class<U>","type"); + addParameter(operation,"E","entity"); + addException(operation,TopiaException.class); + addAnnotation(result, operation,"Override"); + StringBuilder buffer = new StringBuilder(300); + buffer.append("" +/*{ + List<?> result = new ArrayList(); + List tmp; +}*/ + ); + + for (ObjectModelClass usageClass : usagesForclass) { + String usageType = usageClass.getQualifiedName(); + builder.addImport(result, usageType); + String usageSimpleType = + TopiaGeneratorUtil.getClassNameFromQualifiedName(usageType); + + for (ObjectModelAttribute attr : usageClass.getAttributes()) { + if (!attr.isNavigable()) { + // skip this case + continue; + } + String type; + String attrName = attr.getName(); + if (attr.hasAssociationClass()) { + //FIXME-TC20100224 dont known how to do this ? + continue; +// type = attr.getAssociationClass().getQualifiedName(); +// //FIXME-TC20100224 : this is crazy ??? must find the good name +// // Perhaps need to make different cases? +// attrName = attrName + "_" + TopiaGeneratorUtil.toLowerCaseFirstLetter(attr.getAssociationClass().getName()); + } else { + type = attr.getType(); + } + if (!allEntitiesByFQN.containsKey(type)) { + // not a entity, can skip for this attribute + continue; + } + ObjectModelClass targetEntity = allEntitiesByFQN.get(type); + //if (!type.equals(clazz.getQualifiedName())) { + if (!targetEntity.equals(clazz)) { + // not a good attribute reference + continue; + } + // found something to seek + + String methodName; + if (!GeneratorUtil.isNMultiplicity(attr)) { + methodName = "findAllBy"+ StringUtils.capitalize(attrName); + } else { + methodName = "findAllContains"+ StringUtils.capitalize(attrName); + } + String daoName = StringUtils.capitalize(usageSimpleType) + "DAO"; + + builder.addImport(result, usageClass.getPackageName() + '.' + daoName); + + buffer.append("" +/*{ + if (type == <%=usageSimpleType%>.class) { + <%=daoName%> dao = (<%=daoName%>) + getContext().getDAO(<%=usageSimpleType%>.class); + tmp = dao.<%=methodName%>(entity); +// tmp = dao.findAllByProperties(<%=usageSimpleType%>.<%=getConstantName(attrName)%>, entity); + result.addAll(tmp); + } +}*/ + ); + } + } + + buffer.append("" +/*{ + return (List<U>) result; + }*/ + ); + setOperationBody(operation, buffer.toString()); + + operation = addOperation(result, + "findAllUsages", + "Map<Class<?>, List<? extends TopiaEntity>>", + ObjectModelModifier.PUBLIC); + + addParameter(operation, "E", "entity"); + addException(operation, TopiaException.class); + addAnnotation(result, operation,"Override"); + + buffer = new StringBuilder(300); + buffer.append("" +/*{ + Map<Class<?>,List<? extends TopiaEntity>> result; + result = new HashMap<Class<?>, List<? extends TopiaEntity>>(<%=usagesForclass.size()%>); + + List<? extends TopiaEntity> list; +}*/ + ); + for (ObjectModelClass usageClass : usagesForclass) { + + String fqn = usageClass.getName(); + buffer.append("" +/*{ + list = findUsages(<%=fqn%>.class, entity); + if (!list.isEmpty()) { + result.put(<%=fqn%>.class, list); + } +}*/ + ); + + } + buffer.append("" +/*{ + return result; + }*/ + ); + + setOperationBody(operation, buffer.toString()); + } + /** * Generation of DAO operations signatures from class. * These operations are abstract and identified by <<dao>> stereotype in the model. @@ -445,7 +643,7 @@ String propertyName = attrName; if (!isAssoc && attr.hasAssociationClass()) { propertyName = TopiaGeneratorUtil.toLowerCaseFirstLetter( - attr.getAssociationClass().getName()) + "." + propertyName; + attr.getAssociationClass().getName()) + '.' + propertyName; } ObjectModelOperation op; op = addOperation(result, @@ -627,7 +825,7 @@ addParameter(create, attr.getType(), propName); searchProperties += - ", " + clazzName + "." + getConstantName(propName) + + ", " + clazzName + '.' + getConstantName(propName) + ", " + propName; params += ", " + propName; } Modified: trunk/topia-persistence/src/main/java/org/nuiton/topia/generator/DAOHelperTransformer.java =================================================================== --- trunk/topia-persistence/src/main/java/org/nuiton/topia/generator/DAOHelperTransformer.java 2010-02-26 18:48:25 UTC (rev 1815) +++ trunk/topia-persistence/src/main/java/org/nuiton/topia/generator/DAOHelperTransformer.java 2010-02-26 18:52:36 UTC (rev 1816) @@ -101,13 +101,21 @@ }*/ ); + // getModelName method + op = addOperation(resultClass, "getModelName", "String", ObjectModelModifier.PUBLIC, ObjectModelModifier.STATIC); + setOperationBody(op, "" + /*{ + return "<%=modelName%>"; + }*/ + ); + for (ObjectModelClass clazz : classes) { String clazzName = clazz.getName(); String daoClazzName = clazzName + "DAO"; // specialized getXXXDao method - op = addOperation(resultClass, "get" + daoClazzName, clazz.getPackageName() + "." + daoClazzName, ObjectModelModifier.PUBLIC, ObjectModelModifier.STATIC); + op = addOperation(resultClass, "get" + daoClazzName, clazz.getPackageName() + '.' + daoClazzName, ObjectModelModifier.PUBLIC, ObjectModelModifier.STATIC); addParameter(op, TopiaContext.class, "context"); addImport(resultClass, clazz); addException(op, TopiaException.class); @@ -234,7 +242,7 @@ for (ObjectModelClass clazz : classes) { String clazzName = clazz.getName(); - addLiteral(entityEnum, clazzName + "(" + clazzName + ".class)"); + addLiteral(entityEnum, clazzName + '(' + clazzName + ".class)"); } attr = (ObjectModelAttributeImpl) addAttribute(entityEnum, "contract", "Class<? extends TopiaEntity>"); attr.setDocumentation("the contract of the entity"); Modified: trunk/topia-persistence/src/main/java/org/nuiton/topia/generator/EntityAbstractTransformer.java =================================================================== --- trunk/topia-persistence/src/main/java/org/nuiton/topia/generator/EntityAbstractTransformer.java 2010-02-26 18:48:25 UTC (rev 1815) +++ trunk/topia-persistence/src/main/java/org/nuiton/topia/generator/EntityAbstractTransformer.java 2010-02-26 18:52:36 UTC (rev 1816) @@ -40,7 +40,6 @@ import java.util.List; /*{generator option: parentheses = false}*/ - /*{generator option: writeString = +}*/ /** @@ -175,7 +174,7 @@ if (GeneratorUtil.isNMultiplicity(attr)) { String collectionType = TopiaGeneratorUtil.getNMultiplicityInterfaceType(attr); - type = collectionType + "<" + type + ">"; + type = collectionType + '<' + type + '>'; } String attrVisibility = attr.getVisibility(); @@ -189,14 +188,14 @@ attr.hasTagValue(TopiaGeneratorUtil.TAG_DB_NAME)) { if (TopiaGeneratorUtil.hasDocumentation(attr)) { String attrDocumentation = attr.getDocumentation(); - doc.append(attrDocumentation).append("\n"); + doc.append(attrDocumentation).append('\n'); } if (attr.hasTagValue(TopiaGeneratorUtil.TAG_DB_NAME)) { String dbName = attr.getTagValue(TopiaGeneratorUtil.TAG_DB_NAME); doc.append("Nom de l'attribut en BD : "); doc.append(dbName); - doc.append("\n"); + doc.append('\n'); } } @@ -430,7 +429,7 @@ "addAll" + StringUtils.capitalize(attrName), "void", ObjectModelModifier.PUBLIC); - addParameter(op, collectionInterface + "<" + attrType + ">", "values"); + addParameter(op, collectionInterface + '<' + attrType + '>', "values"); setOperationBody(op, "" /*{ @@ -464,7 +463,7 @@ "set" + StringUtils.capitalize(attrName), "void", ObjectModelModifier.PUBLIC); - addParameter(op, collectionInterface + "<" + attrType + ">", "values"); + addParameter(op, collectionInterface + '<' + attrType + '>', "values"); setOperationBody(op, "" /*{ @@ -631,7 +630,7 @@ "addAll" + StringUtils.capitalize(assocAttrName), "void", ObjectModelModifier.PUBLIC); - addParameter(op, collectionInterface + "<" + assocClassFQN + ">", "values"); + addParameter(op, collectionInterface + '<' + assocClassFQN + '>', "values"); setOperationBody(op, "" /*{ if (values == null) { @@ -649,7 +648,7 @@ "set" + StringUtils.capitalize(assocAttrName), "void", ObjectModelModifier.PUBLIC); - addParameter(op, collectionInterface + "<" + assocClassFQN + ">", "values"); + addParameter(op, collectionInterface + '<' + assocClassFQN + '>', "values"); setOperationBody(op, "" /*{ // clear<%=StringUtils.capitalize(assocAttrName)%>(); @@ -738,7 +737,7 @@ op = addOperation(result, "get" + StringUtils.capitalize(attrName), - collectionInterface + "<" + attrType + ">", + collectionInterface + '<' + attrType + '>', ObjectModelModifier.PUBLIC); setOperationBody(op, "" /*{ @@ -783,7 +782,7 @@ op = addOperation(result, "get" + StringUtils.capitalize(assocAttrName), - collectionInterface + "<" + assocClassFQN + ">", + collectionInterface + '<' + assocClassFQN + '>', ObjectModelModifier.PUBLIC); setOperationBody(op, "" /*{ @@ -845,8 +844,9 @@ } } - protected void generateAssociationAccessors(ObjectModelClass result, - ObjectModelAssociationClass assoc) { + protected void generateAssociationAccessors( + ObjectModelClass result, + ObjectModelAssociationClass assoc) { for (ObjectModelAttribute attr : assoc.getParticipantsAttributes()) { if (attr != null) { String attrType = TopiaGeneratorUtil.getSimpleName(attr.getType()); @@ -915,7 +915,7 @@ ObjectModelOperation op = addOperation(result, "getComposite", - List.class.getName() + "<" + TopiaEntity.class.getName() + ">", + List.class.getName() + '<' + TopiaEntity.class.getName() + '>', ObjectModelModifier.PUBLIC); addException(op, TopiaException.class); StringBuilder body = new StringBuilder(); @@ -1014,7 +1014,7 @@ ObjectModelOperation op = addOperation(result, "accept", - List.class.getName() + "<" + TopiaEntity.class.getName() + ">", + List.class.getName() + '<' + TopiaEntity.class.getName() + '>', ObjectModelModifier.PUBLIC); addException(op, TopiaException.class); @@ -1065,7 +1065,8 @@ setOperationBody(op, body.length() == 0 ? " " : body.toString()); } - protected void generateAcceptMethod(ObjectModelClass result, ObjectModelClass clazz) { + protected void generateAcceptMethod(ObjectModelClass result, + ObjectModelClass clazz) { ObjectModelOperation op = addOperation(result, "accept", @@ -1160,7 +1161,8 @@ } - private void generateAssociationAccessors(ObjectModelClass result, String name, String type) { + private void generateAssociationAccessors(ObjectModelClass result, + String name, String type) { ObjectModelOperation op; op = addOperation(result, "set" + StringUtils.capitalize(name), @@ -1197,7 +1199,8 @@ * @param result ObjectModelClass result corresponding to the EntityAbstract * @param clazz ObjectModelClass source from ObjectModel */ - private void generateAbstractMethods(ObjectModelClass result, ObjectModelClass clazz) { + private void generateAbstractMethods(ObjectModelClass result, + ObjectModelClass clazz) { for (ObjectModelOperation op : clazz.getOperations()) { if (log.isDebugEnabled()) { log.debug("clazz : " + clazz.getQualifiedName() + @@ -1216,12 +1219,16 @@ } } - private void generateI18n(ObjectModelClass result, String i18nPrefix, ObjectModelClass clazz) { + private void generateI18n(ObjectModelClass result, String i18nPrefix, + ObjectModelClass clazz) { - StringBuilder buffer = new StringBuilder(); + StringBuilder buffer = new StringBuilder(300); addI18n(buffer, i18nPrefix, Introspector.decapitalize(clazz.getName())); for (ObjectModelAttribute attr : clazz.getAttributes()) { - addI18n(buffer, i18nPrefix, Introspector.decapitalize(attr.getName())); + //TC-20100225 only treate navigable relations + if (attr.isNavigable()) { + addI18n(buffer, i18nPrefix, Introspector.decapitalize(attr.getName())); + } } //FIXME : use a block extension for java @@ -1229,7 +1236,8 @@ setOperationBody(op, buffer.toString()); } - private void addI18n(StringBuilder buffer, String i18nPrefix, String suffix) { + private void addI18n(StringBuilder buffer, String i18nPrefix, + String suffix) { buffer.append("\n org.nuiton.i18n.I18n.n_(\""); buffer.append(i18nPrefix); buffer.append(suffix); Modified: trunk/topia-persistence/src/main/java/org/nuiton/topia/generator/TopiaGeneratorUtil.java =================================================================== --- trunk/topia-persistence/src/main/java/org/nuiton/topia/generator/TopiaGeneratorUtil.java 2010-02-26 18:48:25 UTC (rev 1815) +++ trunk/topia-persistence/src/main/java/org/nuiton/topia/generator/TopiaGeneratorUtil.java 2010-02-26 18:52:36 UTC (rev 1816) @@ -29,16 +29,11 @@ */ package org.nuiton.topia.generator; -import java.util.ArrayList; -import java.util.Arrays; -import java.util.Collection; -import java.util.HashSet; -import java.util.Iterator; -import java.util.LinkedList; -import java.util.List; -import java.util.Set; +import java.util.*; import org.apache.commons.lang.StringUtils; +import org.apache.commons.logging.Log; +import org.apache.commons.logging.LogFactory; import org.nuiton.eugene.AbstractGenerator; import org.nuiton.eugene.GeneratorUtil; import org.nuiton.eugene.models.Model; @@ -57,6 +52,11 @@ public class TopiaGeneratorUtil extends GeneratorUtil { /** + * Logger + */ + private static final Log log = LogFactory.getLog(TopiaGeneratorUtil.class); + + /** * Stéréotype pour les interfaces devant être générées sous forme de facades */ public final static String STEREOTYPE_FACADE = "facade"; @@ -308,7 +308,8 @@ } /** - * Cherche et renvoie le schema a utiliser sur cet element, sinon sur le model. + * Cherche et renvoie le schema a utiliser sur cet element, sinon sur le + * model. * * @param element l'élément à tester * @param model le modele utilisé @@ -320,7 +321,8 @@ } /** - * Cherche et renvoie le prefixe i18n à utiliser sur cet element, sinon sur le model. + * Cherche et renvoie le prefixe i18n à utiliser sur cet element, sinon sur + * le model. * * @param element l'élément à tester * @param model le modele utilisé @@ -332,25 +334,32 @@ } /** - * Cherche et renvoie le prefixe i18n à utiliser sur cet element, sinon sur le model. + * Cherche et renvoie le prefixe i18n à utiliser sur cet element, sinon sur + * le model. * * @param element l'élément à tester * @param model le modele utilisé * @return le prefix i18n ou <code>null</code> si non spécifié */ - public static boolean shouldgenerateOperatorForDAOHelper(ObjectModelElement element, - ObjectModel model) { - String tagValue = GeneratorUtil.findTagValue(TAG_GENERATE_OPERATOR_FOR_DAO_HELPER, element, model); - boolean generate = GeneratorUtil.notEmpty(tagValue) && Boolean.valueOf(tagValue); + public static boolean shouldgenerateOperatorForDAOHelper( + ObjectModelElement element, + ObjectModel model) { + String tagValue = GeneratorUtil.findTagValue( + TAG_GENERATE_OPERATOR_FOR_DAO_HELPER, element, model); + boolean generate = GeneratorUtil.notEmpty(tagValue) && + Boolean.valueOf(tagValue); return generate; } /** - * Cherche et renvoie la liste des attributs constituant la clef metier d'une classe. + * Cherche et renvoie la liste des attributs constituant la clef metier + * d'une classe. * * @param clazz la classe à tester - * @return la liste des attributs de la clef métier ou null si pas de clef métier. - * @deprecated use {@link #getNaturalIdAttributes(ObjectModelClass) } instead + * @return la liste des attributs de la clef métier ou null si pas de clef + * métier. + * @deprecated since 2.3.0 use + * {@link #getNaturalIdAttributes(ObjectModelClass) } instead * this usage is not allowed, prefer put tagvalue.naturalId on each * entity attribute needed */ @@ -358,7 +367,7 @@ public static List<String> getNaturalId(ObjectModelClass clazz) { String value = clazz.getTagValue(TAG_NATURAL_ID); if (value == null || value.trim().isEmpty()) { - return java.util.Collections.emptyList(); + return Collections.emptyList(); } List<String> result = new ArrayList<String>(); for (String attribute : value.split(",")) { @@ -368,13 +377,16 @@ } /** - * Cherche et renvoie la liste des attributs constituant la clef metier d'une classe. + * Cherche et renvoie la liste des attributs constituant la clef metier + * d'une classe. * * @param clazz la classe à tester * @return la liste des attributs de la clef métier */ - public static List<ObjectModelAttribute> getNaturalIdAttributes(ObjectModelClass clazz) { - List<ObjectModelAttribute> results = new ArrayList<ObjectModelAttribute>(); + public static List<ObjectModelAttribute> getNaturalIdAttributes( + ObjectModelClass clazz) { + List<ObjectModelAttribute> results = + new ArrayList<ObjectModelAttribute>(); for (ObjectModelAttribute attr : clazz.getAttributes()) { if (isNaturalId(attr)) { results.add(attr); @@ -384,11 +396,13 @@ } /** - * Cherche et renvoie la liste des attributs constituant la clef metier d'une classe. + * Cherche et renvoie la liste des attributs constituant la clef metier + * d'une classe. * * @param clazz la classe à tester * @param model le modele - * @return la liste des attributs de la clef métier ou null si pas de clef métier. + * @return la liste des attributs de la clef métier ou null si pas de + * clef métier. */ public static boolean generateToString(ObjectModelClass clazz, ObjectModel model) { @@ -402,17 +416,20 @@ } /** - * Cherche et renvoie la liste des attributs constituant la clef metier d'une classe. + * Cherche et renvoie la liste des attributs constituant la clef metier + * d'une classe. * * @param clazz la classe à tester * @param model le modele - * @return la liste des attributs de la clef métier ou null si pas de clef métier. + * @return la liste des attributs de la clef métier ou null si pas de + * clef métier. */ public static boolean sortAttribute(ObjectModelClass clazz, ObjectModel model) { String value; value = clazz.getTagValue(TAG_SORT_ATTRIBUTE); - if (value == null || value.trim().isEmpty() || "false".equals(value.trim())) { + if (value == null || value.trim().isEmpty() || + "false".equals(value.trim())) { return false; } if ("true".equals(value.trim())) { @@ -420,7 +437,8 @@ } value = model.getTagValue(TAG_SORT_ATTRIBUTE); - if (value == null || value.trim().isEmpty() || "false".equals(value.trim())) { + if (value == null || value.trim().isEmpty() || + "false".equals(value.trim())) { return false; } if ("true".equals(value.trim())) { @@ -433,7 +451,8 @@ * Detecte si un attribut fait partie d'une clef metier. * * @param attribute l'attribut à tester - * @return <code>true</code> si l'attribut fait partie d'une clef metier, <code>false</cdoe> sinon. + * @return <code>true</code> si l'attribut fait partie d'une clef metier, + * <code>false</cdoe> sinon. */ public static boolean isNaturalId(ObjectModelAttribute attribute) { String value = attribute.getTagValue(TAG_NATURAL_ID); @@ -506,10 +525,13 @@ public static String getPrimaryKeyAttributesListDeclaration( ObjectModelClass clazz, boolean includeName) { String attributes = ""; - for (ObjectModelAttribute attr : getElementsWithStereotype(clazz.getAttributes(), STEREOTYPE_PRIMARYKAY)) { + final Collection<ObjectModelAttribute> attributeCollection; + attributeCollection = getElementsWithStereotype(clazz.getAttributes(), + STEREOTYPE_PRIMARYKAY); + for (ObjectModelAttribute attr : attributeCollection) { attributes += attr.getType(); if (includeName) { - attributes += " " + attr.getName(); + attributes += ' ' + attr.getName(); } attributes += ", "; } @@ -524,7 +546,10 @@ // } public static boolean isAssociationClassDoublon(ObjectModelAttribute attr) { - return (attr.getReverseAttribute() != null) && (attr.getDeclaringElement().equals(attr.getReverseAttribute().getDeclaringElement())) && (!GeneratorUtil.isFirstAttribute(attr)); + return (attr.getReverseAttribute() != null) && + (attr.getDeclaringElement().equals( + attr.getReverseAttribute().getDeclaringElement())) && + (!GeneratorUtil.isFirstAttribute(attr)); } /** @@ -540,7 +565,8 @@ attr.getType().lastIndexOf(".") + 1); String result = attr.getName(); if (attr.getName().equalsIgnoreCase(typeName)) { - result += StringUtils.capitalize(attr.getAssociationClass().getName()); + result += StringUtils.capitalize( + attr.getAssociationClass().getName()); } return result; } @@ -656,7 +682,8 @@ * @return true dans ce cas, false sinon */ public static boolean shouldBeAbstract(ObjectModelClass clazz) { - return clazz != null && (clazz.isAbstract() && hasNothingOrAbstractMethods(clazz)); + return clazz != null && clazz.isAbstract() && + hasNothingOrAbstractMethods(clazz); } /** @@ -679,7 +706,8 @@ ObjectModelAttribute attr, ObjectModel model) { ObjectModelAttribute reverse = attr.getReverseAttribute(); //relation 1-n - if (reverse != null && isNMultiplicity(attr) && !isNMultiplicity(reverse)) { + if (reverse != null && isNMultiplicity(attr) && + !isNMultiplicity(reverse)) { //Pas de navigabilité if (!reverse.isNavigable()) { //Il s'agit d'une entity @@ -717,9 +745,9 @@ String revers = attr.getReverseAttributeName(); if (name.compareToIgnoreCase(revers) < 0) { - result = name + "_" + revers; + result = name + '_' + revers; } else { - result = revers + "_" + name; + result = revers + '_' + name; } } // String result; @@ -737,7 +765,8 @@ * @param attr l'attribut a traiter * @return String */ - public static String getNMultiplicityInterfaceType(ObjectModelAttribute attr) { + public static String getNMultiplicityInterfaceType( + ObjectModelAttribute attr) { if (attr.hasStereotype(STEREOTYPE_UNIQUE)) { return Set.class.getName(); } else if (attr.isIndexed() || attr.isOrdered()) { @@ -771,7 +800,8 @@ * @param attr l'attribut a traiter * @return String */ - public static String getNMultiplicityHibernateType(ObjectModelAttribute attr) { + public static String getNMultiplicityHibernateType( + ObjectModelAttribute attr) { if (attr.hasStereotype(STEREOTYPE_UNIQUE)) { return "set"; } else if (attr.isIndexed()) { @@ -782,7 +812,8 @@ } /** - * Obtain the list of entities classes with the possibility to sort the result. + * Obtain the list of entities classes with the possibility to sort the + * result. * * @param model the current model to scan * @param sort flag to allow sort the result @@ -794,7 +825,8 @@ } /** - * Obtain the list of classes for a given stereotype with the possibility to sort the result. + * Obtain the list of classes for a given stereotype with the possibility + * to sort the result. * * @param stereotype filter stereotype * @param model the current model to scan @@ -810,28 +842,34 @@ } } if (sort && !classes.isEmpty()) { - java.util.Collections.sort(classes, - new java.util.Comparator<ObjectModelClass>() { - @Override - public int compare(ObjectModelClass o1, - ObjectModelClass o2) { - return o1.getQualifiedName().compareTo( - o2.getQualifiedName()); - } - }); + Collections.sort(classes, OBJECT_MODEL_CLASS_COMPARATOR); } return classes; } + static public final Comparator<ObjectModelClass> + OBJECT_MODEL_CLASS_COMPARATOR = + new Comparator<ObjectModelClass>() { + + @Override + public int compare(ObjectModelClass o1, + ObjectModelClass o2) { + return o1.getQualifiedName().compareTo( + o2.getQualifiedName()); + } + }; + /** * Detecte si la clef metier d'une classe est mutable ou pas. * <p/> - * On respecte la valeur par defaut d'hibernate, à savoir que par default une clef metier est non mutable. + * On respecte la valeur par defaut d'hibernate, à savoir que par default + * une clef metier est non mutable. * * @param clazz la classe a tester - * @return <code>true</code> si le tag value a ete positionne sur la classe via le tag - * {@link #TAG_NATURAL_ID_MUTABLE}, , <code>false</code> sinon. + * @return <code>true</code> si le tag value a ete positionne sur la classe + * via le tag {@link #TAG_NATURAL_ID_MUTABLE}, <code>false</code> + * sinon. */ public static boolean isNaturalIdMutable(ObjectModelClass clazz) { String value = clazz.getTagValue(TAG_NATURAL_ID_MUTABLE); @@ -855,7 +893,8 @@ * @param incomingFqns incoming fqns * @return the list of fqn of attributes */ - public static List<String> getImports(ObjectModelClass aClass, String... incomingFqns) { + public static List<String> getImports(ObjectModelClass aClass, + String... incomingFqns) { Set<String> tmp = new HashSet<String>(); tmp.addAll(Arrays.asList(incomingFqns)); getImports(aClass, tmp); @@ -870,7 +909,8 @@ * @param incomingFqns incoming fqns * @return the list of fqn of attributes */ - public static List<String> getImports(ObjectModelInterface anInterface, String... incomingFqns) { + public static List<String> getImports(ObjectModelInterface anInterface, + String... incomingFqns) { Set<String> tmp = new HashSet<String>(); tmp.addAll(Arrays.asList(incomingFqns)); getImports(anInterface, tmp); @@ -899,7 +939,8 @@ * @param aClass the class to inspect * @param fqns where to store found fqns */ - protected static void getImports(ObjectModelClass aClass, Set<String> fqns) { + protected static void getImports(ObjectModelClass aClass, + Set<String> fqns) { // scan attributes for (ObjectModelAttribute attr : aClass.getAttributes()) { fqns.add(attr.getType()); @@ -915,8 +956,10 @@ } // scan associations if (aClass instanceof ObjectModelAssociationClass) { - ObjectModelAssociationClass assoc = (ObjectModelAssociationClass) aClass; - for (ObjectModelAttribute attr : assoc.getParticipantsAttributes()) { + ObjectModelAssociationClass assoc = + (ObjectModelAssociationClass) aClass; + for (ObjectModelAttribute attr : + assoc.getParticipantsAttributes()) { if (attr == null) { continue; } @@ -951,7 +994,8 @@ * @param anInterface the interface to inspect * @param fqns where to store found fqns */ - protected static void getImports(ObjectModelInterface anInterface, Set<String> fqns) { + protected static void getImports(ObjectModelInterface anInterface, + Set<String> fqns) { // scan operations for (ObjectModelOperation operation : anInterface.getOperations()) { getImports(operation, fqns); @@ -969,7 +1013,8 @@ * @param operation operation to inspect * @param fqns where to store found fqns */ - protected static void getImports(ObjectModelOperation operation, Set<String> fqns) { + protected static void getImports(ObjectModelOperation operation, + Set<String> fqns) { String fqn = operation.getReturnType(); fqns.add(fqn); for (ObjectModelParameter parameter : operation.getParameters()) { @@ -984,7 +1029,8 @@ * @param fqns the dirty set of fqns * @return the sorted cleaned list of fqns. */ - protected static List<String> cleanImports(String packageName, Set<String> fqns) { + protected static List<String> cleanImports(String packageName, + Set<String> fqns) { fqns.removeAll(primitiveTypes); fqns.remove(VOID_TYPE); int packageLength = packageName.length(); @@ -1006,7 +1052,7 @@ fqns.addAll(genericType); ArrayList<String> result = new ArrayList<String>(fqns); - java.util.Collections.sort(result); + Collections.sort(result); return result; } @@ -1042,5 +1088,65 @@ } return buffer.toString(); } + + public static Map<ObjectModelClass, Set<ObjectModelClass>> + searchDirectUsages(ObjectModel model) { + List<ObjectModelClass> allEntities; + Map<String, ObjectModelClass> allEntitiesByFQN; + Map<ObjectModelClass, Set<ObjectModelClass>> usages; + + allEntities = getEntityClasses(model, true); + + allEntitiesByFQN = new TreeMap<String, ObjectModelClass>(); + usages = new LinkedHashMap<ObjectModelClass, Set<ObjectModelClass>>(); + + // prepare usages map and fill allEntitiesByFQN map + for (ObjectModelClass klass : allEntities) { + usages.put(klass, new HashSet<ObjectModelClass>()); + allEntitiesByFQN.put(klass.getQualifiedName(), klass); + } + + // first pass to detect direct usages + for (ObjectModelClass klass : allEntities) { + searchDirectUsages(klass, allEntitiesByFQN, usages); + } + allEntities.clear(); + allEntitiesByFQN.clear(); + return usages; + + } + + public static void searchDirectUsages( + ObjectModelClass klass, + Map<String, ObjectModelClass> allEntitiesByFQN, + Map<ObjectModelClass, Set<ObjectModelClass>> usages) { + + if (log.isDebugEnabled()) { + log.debug("for entity " + klass.getQualifiedName()); + } + for (ObjectModelAttribute attr : klass.getAttributes()) { + if (!attr.isNavigable()) { + // skip this case + continue; + } + String type; + if (attr.hasAssociationClass()) { + type = attr.getAssociationClass().getQualifiedName(); + } else { + type = attr.getType(); + } + if (!allEntitiesByFQN.containsKey(type)) { + // not a entity, can skip for this attribute + continue; + } + if (log.isDebugEnabled()) { + log.debug(" uses " + type); + } + // register the klass as using the targetEntity + ObjectModelClass targetEntity = allEntitiesByFQN.get(type); + Set<ObjectModelClass> classes = usages.get(targetEntity); + classes.add(klass); + } + } } // GeneratorUtil
participants (1)
-
tchemit@users.nuiton.org