r2025 - in trunk/topia-persistence: . src/main/java/org/nuiton/topia/generator src/test/java/org/nuiton/topia/generator
Author: fdesbois Date: 2010-06-24 16:13:08 +0200 (Thu, 24 Jun 2010) New Revision: 2025 Url: http://nuiton.org/repositories/revision/topia/2025 Log: Evo #707 : QueryHelperTransformer (todo javadoc) Added: trunk/topia-persistence/src/main/java/org/nuiton/topia/generator/QueryHelperTransformer.java trunk/topia-persistence/src/test/java/org/nuiton/topia/generator/QueryHelperTransformerTest.java Modified: trunk/topia-persistence/pom.xml Modified: trunk/topia-persistence/pom.xml =================================================================== --- trunk/topia-persistence/pom.xml 2010-06-24 14:10:48 UTC (rev 2024) +++ trunk/topia-persistence/pom.xml 2010-06-24 14:13:08 UTC (rev 2025) @@ -192,7 +192,8 @@ org.nuiton.topia.generator.EntityTransformer, org.nuiton.topia.generator.InterfaceTransformer, org.nuiton.topia.generator.BeanTransformer, - org.nuiton.topia.generator.EntityDTOTransformer + org.nuiton.topia.generator.EntityDTOTransformer, + org.nuiton.topia.generator.QueryHelperTransformer </templates> <excludeTemplates> <excludeTemplate>org.nuiton.topia.generator.EntityAbstractTransformer</excludeTemplate> Added: trunk/topia-persistence/src/main/java/org/nuiton/topia/generator/QueryHelperTransformer.java =================================================================== --- trunk/topia-persistence/src/main/java/org/nuiton/topia/generator/QueryHelperTransformer.java (rev 0) +++ trunk/topia-persistence/src/main/java/org/nuiton/topia/generator/QueryHelperTransformer.java 2010-06-24 14:13:08 UTC (rev 2025) @@ -0,0 +1,512 @@ +package org.nuiton.topia.generator; + +import org.apache.commons.lang.RandomStringUtils; +import org.apache.commons.lang.StringUtils; +import org.apache.commons.lang.math.RandomUtils; +import org.apache.commons.logging.Log; +import org.apache.commons.logging.LogFactory; +import org.nuiton.eugene.java.JavaBuilder; +import org.nuiton.eugene.java.ObjectModelTransformerToJava; +import org.nuiton.eugene.models.object.ObjectModel; +import org.nuiton.eugene.models.object.ObjectModelAssociationClass; +import org.nuiton.eugene.models.object.ObjectModelAttribute; +import org.nuiton.eugene.models.object.ObjectModelClass; +import org.nuiton.eugene.models.object.ObjectModelClassifier; +import org.nuiton.eugene.models.object.ObjectModelModifier; +import org.nuiton.eugene.models.object.ObjectModelOperation; +import org.nuiton.eugene.models.object.ObjectModelType; +import org.nuiton.topia.framework.TopiaQuery; +import org.nuiton.topia.persistence.TopiaEntity; + +import java.util.HashMap; +import java.util.Map; + +/** + * Created: 23 juin 2010 + * + * @author fdesbois <fdesbois@codelutin.com> + * @version $Id$ + */ +public class QueryHelperTransformer extends ObjectModelTransformerToJava { + + private static final Log log = LogFactory.getLog(QueryHelperTransformer.class); + + protected ObjectModelClass helperClass; + + protected ObjectModelClass abstractEntityPropertyClass; + + protected static final String ENTITY_PROPERTY_CLASS_NAME = "EntityProperty"; + + protected static final String ENTITY_PROPERTY_GENERIC_TYPE = "<E>"; + + protected String mainException; + + protected Map<String, String> aliases; + + public static final String CONSTANT_PREFIX = "ALIAS_"; + + /*************************** MAIN PART OF THE HELPER **********************/ + + @Override + public void transformFromModel(ObjectModel model) { + + aliases = new HashMap<String, String>(); + + String modelName = StringUtils.capitalize(model.getName()); + String packageName = getOutputProperties().getProperty(PROP_DEFAULT_PACKAGE); + helperClass = createClass(modelName + "QueryHelper", packageName); + + addImport(helperClass, TopiaQuery.class); + addImport(helperClass, TopiaEntity.class); + + String exception = model.getTagValue(TopiaGeneratorUtil.TAG_EXCEPTION_CLASS); + if (exception != null) { + addImport(helperClass, exception); + mainException = TopiaGeneratorUtil.getSimpleName(exception); + } + + initConstantPrefixFromModel(); + + createInnerAbstractEntityPropertyClass(); + createUtilOperations(); + } + + protected void createInnerAbstractEntityPropertyClass() { + + abstractEntityPropertyClass = (ObjectModelClass)addInnerClassifier(helperClass, + ObjectModelType.OBJECT_MODEL_CLASS, + ENTITY_PROPERTY_CLASS_NAME + ENTITY_PROPERTY_GENERIC_TYPE, + ObjectModelModifier.ABSTRACT, + ObjectModelModifier.STATIC); + + addImport(helperClass, HashMap.class); + addImport(helperClass, Map.class); + + addAttribute(abstractEntityPropertyClass, "alias", + String.class, null, + ObjectModelModifier.PROTECTED); + + addAttribute(abstractEntityPropertyClass, "propertiesCache", + "Map<String, String>", null, + ObjectModelModifier.PROTECTED); + + // Constructor + // FIXME-fdesbois-2010-06-23 : need to take care of generic case in JavaBuilder in EUGene +// ObjectModelOperation constructor = +// addConstructor(abstractEntityPropertyClass, ObjectModelModifier.PUBLIC); + ObjectModelOperation constructor = + builder.addOperation(abstractEntityPropertyClass, ENTITY_PROPERTY_CLASS_NAME, null, ObjectModelModifier.PUBLIC); + + setOperationBody(constructor, "" + /*{ + propertiesCache = new HashMap<String, String>(); + }*/ + ); + + // Getter and setter for alias + ObjectModelOperation setAlias = + addOperation(abstractEntityPropertyClass, "setAlias", "void", + ObjectModelModifier.PROTECTED); + addParameter(setAlias, String.class, "alias"); + + + setOperationBody(setAlias, "" + /*{ + this.alias = alias; + }*/ + ); + + ObjectModelOperation getAlias = + addOperation(abstractEntityPropertyClass, "$alias", String.class, + ObjectModelModifier.PUBLIC); + + + setOperationBody(getAlias, "" + /*{ + return alias; + }*/ + ); + + // Getter for properties + ObjectModelOperation getProperty = + addOperation(abstractEntityPropertyClass, "$property", String.class, + ObjectModelModifier.PUBLIC); + addParameter(getProperty, String.class, "propertyName"); + + + setOperationBody(getProperty, "" + /*{ + String result = propertiesCache.get(propertyName); + if (result == null) { + result = TopiaQuery.getProperty(alias, propertyName); + propertiesCache.put(propertyName, result); + } + return result; + }*/ + ); + + ObjectModelOperation topiaCreateDate = + addOperation(abstractEntityPropertyClass, "topiaCreateDate", String.class, + ObjectModelModifier.PUBLIC); + + setOperationBody(topiaCreateDate, "" + /*{ + return $property(TopiaEntity.TOPIA_CREATE_DATE); + }*/ + ); + + ObjectModelOperation topiaId = + addOperation(abstractEntityPropertyClass, "topiaId", String.class, + ObjectModelModifier.PUBLIC); + + setOperationBody(topiaId, "" + /*{ + return $property(TopiaEntity.TOPIA_ID); + }*/ + ); + + ObjectModelOperation topiaVersion = + addOperation(abstractEntityPropertyClass, "topiaVersion", String.class, + ObjectModelModifier.PUBLIC); + + setOperationBody(topiaVersion, "" + /*{ + return $property(TopiaEntity.TOPIA_VERSION); + }*/ + ); + + // Abstract methods + addOperation(abstractEntityPropertyClass, "getEntityClass", + "Class" + ENTITY_PROPERTY_GENERIC_TYPE, + ObjectModelModifier.PUBLIC, ObjectModelModifier.ABSTRACT); + + addOperation(abstractEntityPropertyClass, "defaultAlias", String.class, + ObjectModelModifier.PUBLIC, ObjectModelModifier.ABSTRACT); + } + + protected void createUtilOperations() { + + // createQuery method with EntityProperty in argument + ObjectModelOperation createQuery = + addOperation(helperClass, "createQuery", TopiaQuery.class, + ObjectModelModifier.PUBLIC, ObjectModelModifier.STATIC); + addParameter(createQuery, ENTITY_PROPERTY_CLASS_NAME, "property"); + + setOperationBody(createQuery, "" + /*{ + return new TopiaQuery((Class<? extends TopiaEntity>)property.getEntityClass(), property.$alias()); + }*/ + ); + + // format method to format statement using $1, $2 corresponding to property names + ObjectModelOperation format = + addOperation(helperClass, "format", String.class, + ObjectModelModifier.PUBLIC, ObjectModelModifier.STATIC); + addParameter(format, String.class, "statement"); + addParameter(format, "String...", "propertyNames"); + + setOperationBody(format, "" + /*{ + for (int i = 1; i <= propertyNames.length; i++) { + statement = statement.replace("$" + i, propertyNames[i-1]); + } + return statement; + }*/ + ); + + // Methods to instantiate EntityProperty + String genericType = "<P extends " + ENTITY_PROPERTY_CLASS_NAME + "> P"; + ObjectModelOperation newEntityProperty1 = + addOperation(helperClass, "newEntityProperty", genericType, + ObjectModelModifier.PRIVATE, ObjectModelModifier.STATIC); + addParameter(newEntityProperty1, "Class<P>", "propertyClass"); + + setOperationBody(newEntityProperty1, "" + /*{ + return newEntityProperty(propertyClass, null); + }*/ + ); + ObjectModelOperation newEntityProperty2 = + addOperation(helperClass, "newEntityProperty", genericType, + ObjectModelModifier.PRIVATE, ObjectModelModifier.STATIC); + addParameter(newEntityProperty2, "Class<P>", "propertyClass"); + addParameter(newEntityProperty2, String.class, "alias"); + + StringBuilder buffer = new StringBuilder("" + /*{ + try { + P property = propertyClass.newInstance(); + if (alias == null) { + alias = property.defaultAlias(); + } + property.setAlias(alias); + return property; + } catch (Exception eee) { + }*/ + ); + + if (mainException != null) { + addException(newEntityProperty1, mainException); + addException(newEntityProperty2, mainException); + buffer.append("" + /*{ + throw new <%=mainException%>("Error instantiate " + propertyClass.getName(), eee); + }*/ + ); + } else { + buffer.append("" + /*{ + throw new Error("Error instantiate " + propertyClass.getName(), eee); + }*/ + ); + } + buffer.append("" + /*{ + } + }*/ + ); + + setOperationBody(newEntityProperty2, buffer.toString()); + } + + /*************************** INNER PROPERTY CLASSES ***********************/ + + @Override + public void transformFromClass(ObjectModelClass clazz) { + if (!TopiaGeneratorUtil.hasStereotype(clazz, TopiaGeneratorUtil.STEREOTYPE_ENTITY)) { + return; + } + + // Create default alias for this entity + String aliasConstant = createAliasConstant(clazz.getName()); + + // Create inner class for this entity + ObjectModelClass entityPropertyClass = createInnerClass(clazz, aliasConstant); + + // Create methods to instantiate the inner class + createNewOperations(entityPropertyClass); + } + + protected String getPropertyClassName(ObjectModelClassifier entityClass) { + return entityClass.getName() + "Property"; + } + + protected String createAliasConstant(String entityName) { + + String constantName = + TopiaGeneratorUtil.convertVariableNameToConstantName(entityName); + + String[] words = constantName.split("_"); + String alias = ""; + // Use first letter of each word as alias + for (String word : words) { + alias += word.substring(0, 1); + } + + // Case of existing alias, check other letters in lastWord + String lastWord = words[words.length - 1]; + while(aliases.containsKey(alias)) { + // Remove first letter + lastWord = lastWord.substring(1, lastWord.length()); + if (!lastWord.isEmpty()) { + // Use first letter of new lastWord to concat the alias + alias += lastWord.charAt(0); + } else { + // Generate an alea char to concat + alias += StringUtils.upperCase(RandomStringUtils.randomAlphabetic(1)); + } + } + + String aliasPropertyName = CONSTANT_PREFIX + constantName; + + if (log.isDebugEnabled()) { + log.debug("Add alias '" + alias + "' named " + aliasPropertyName); + } + + aliases.put(alias, aliasPropertyName); + + addAttribute(helperClass, aliasPropertyName, String.class, "\"" + alias + "\"", + ObjectModelModifier.PUBLIC, ObjectModelModifier.STATIC, ObjectModelModifier.FINAL); + + return aliasPropertyName; + } + + protected ObjectModelClass createInnerClass(ObjectModelClass input, String aliasConstant) { + String className = getPropertyClassName(input); + + ObjectModelClass propertyClass = (ObjectModelClass) + addInnerClassifier(helperClass, + ObjectModelType.OBJECT_MODEL_CLASS, + className, + ObjectModelModifier.STATIC); + + if (log.isDebugEnabled()) { + log.debug("Generate for entity : " + input.getQualifiedName()); + } + + // FIXME-fdesbois-2010-06-23 : need to manage imports for inner classes : EUGene ImportsManager + addImport(helperClass, input.getQualifiedName()); + + // Important to keep qualifiedName for setSuperClass + String superClassQualifiedName = abstractEntityPropertyClass.getQualifiedName(). + replace(ENTITY_PROPERTY_GENERIC_TYPE, "<" + input.getName() + ">"); + + setSuperClass(propertyClass, superClassQualifiedName); + + ObjectModelOperation constructor = + addConstructor(propertyClass, ObjectModelModifier.PROTECTED); + + setOperationBody(constructor, "" + /*{ + }*/ + ); + + ObjectModelOperation getEntityClass = + addOperation(propertyClass, "getEntityClass", "Class<" + input.getName() + ">", + ObjectModelModifier.PUBLIC); + + addAnnotation(propertyClass, getEntityClass, "Override"); + + setOperationBody(getEntityClass, "" + /*{ + return <%=input.getName()%>.class; + }*/ + ); + + ObjectModelOperation defaultAlias = + addOperation(propertyClass, "defaultAlias", String.class, + ObjectModelModifier.PUBLIC); + + addAnnotation(propertyClass, defaultAlias, "Override"); + + setOperationBody(defaultAlias, "" + /*{ + return <%=aliasConstant%>; + }*/ + ); + + createGetterOperations(input, propertyClass); + + return propertyClass; + } + + protected void createGetterOperations(ObjectModelClass input, ObjectModelClass propertyClass) { + + // Generate for all attributes + for (ObjectModelAttribute attr : input.getAttributes()) { + + if (log.isDebugEnabled()) { + log.debug("Entity property : name=" + attr.getName() + + " _ navigable=" + attr.isNavigable() + + " _ maxMultiplicity=" + attr.getMaxMultiplicity() + + " _ associationClass=" + attr.hasAssociationClass() + + " _ referenceClassifier=" + attr.referenceClassifier()); + } + + // Case we don't want generation for + if (!attr.isNavigable() || attr.hasAssociationClass()) { + continue; + } + + ObjectModelOperation propertyNameOperation = + createGetPropertyNameOperation(propertyClass, attr.getName(), input.getName()); + + createGetPropertyObjectOperation(propertyClass, attr, propertyNameOperation); + } + + // Case of Association class + if (input instanceof ObjectModelAssociationClass) { + + ObjectModelAssociationClass assoc = (ObjectModelAssociationClass)input; + + for (ObjectModelAttribute attr : assoc.getParticipantsAttributes()) { + ObjectModelOperation propertyNameOperation = + createGetPropertyNameOperation(propertyClass, attr.getName(), input.getName()); + + createGetPropertyObjectOperation(propertyClass, attr, propertyNameOperation); + } + } + } + + protected ObjectModelOperation createGetPropertyNameOperation(ObjectModelClass output, String attrName, String entityClassName) { + ObjectModelOperation result = + addOperation(output, attrName, String.class, ObjectModelModifier.PUBLIC); + + String constantName = + entityClassName + "." + getConstantName(attrName); + + if (log.isDebugEnabled()) { + log.debug("Add getter for property : " + attrName + + " _ constantName = " + constantName + + " _ constantPrefix = " + getConstantPrefix()); + } + + setOperationBody(result, "" + /*{ + return $property(<%=constantName%>); + }*/ + ); + + return result; + } + + protected ObjectModelOperation createGetPropertyObjectOperation(ObjectModelClass output, + ObjectModelAttribute attrReference, + ObjectModelOperation propertyNameOperation) { + ObjectModelOperation result = null; + if (attrReference.referenceClassifier() && attrReference.getMaxMultiplicity() == 1) { + + String opName = attrReference.getName() + "Property"; + + String referencePropertyClassName = getPropertyClassName(attrReference.getClassifier()); + + result = addOperation(output, opName, referencePropertyClassName, ObjectModelModifier.PUBLIC); + + if (log.isDebugEnabled()) { + log.debug("Extra operation : " + opName + + " _ className = " + referencePropertyClassName); + } + + setOperationBody(result, "" + /*{ + return new<%=referencePropertyClassName%>(<%=propertyNameOperation.getName()%>()); + }*/ + ); + } + + return result; + } + + protected void createNewOperations(ObjectModelClass entityProperty) { + + String className = entityProperty.getName(); + + String methodName = "new" + className; + + ObjectModelOperation newEntityProperty1 = + addOperation(helperClass, "new" + className, className, + ObjectModelModifier.PUBLIC, ObjectModelModifier.STATIC); + + setOperationBody(newEntityProperty1, "" + /*{ + return <%=methodName%>(null); + }*/ + ); + + ObjectModelOperation newEntityProperty2 = + addOperation(helperClass, "new" + className, className, + ObjectModelModifier.PUBLIC, ObjectModelModifier.STATIC); + addParameter(newEntityProperty2, String.class, "alias"); + + setOperationBody(newEntityProperty2, "" + /*{ + return newEntityProperty(<%=className%>.class, alias); + }*/ + ); + } + + // For tests + protected void setBuilder(JavaBuilder builder) { + this.builder = builder; + } +} Added: trunk/topia-persistence/src/test/java/org/nuiton/topia/generator/QueryHelperTransformerTest.java =================================================================== --- trunk/topia-persistence/src/test/java/org/nuiton/topia/generator/QueryHelperTransformerTest.java (rev 0) +++ trunk/topia-persistence/src/test/java/org/nuiton/topia/generator/QueryHelperTransformerTest.java 2010-06-24 14:13:08 UTC (rev 2025) @@ -0,0 +1,44 @@ +package org.nuiton.topia.generator; + +import org.junit.Assert; +import org.junit.Test; +import org.nuiton.eugene.java.JavaBuilder; +import org.nuiton.eugene.models.object.xml.ObjectModelClassImpl; + +import java.util.HashMap; + +/** + * Created: 24 juin 2010 + * + * @author fdesbois <fdesbois@codelutin.com> + * @version $Id$ + */ +public class QueryHelperTransformerTest { + + @Test + public void testCreateAliasConstant() { + QueryHelperTransformer transformer = new QueryHelperTransformer(); + transformer.aliases = new HashMap<String, String>(); + transformer.helperClass = new ObjectModelClassImpl(); + transformer.setBuilder(new JavaBuilder("TopiaTest")); + + String entityName = "Department"; + transformer.createAliasConstant(entityName); + Assert.assertEquals(1, transformer.aliases.size()); + Assert.assertTrue(transformer.aliases.containsKey("D")); + + entityName = "Depot"; + transformer.createAliasConstant(entityName); + Assert.assertEquals(2, transformer.aliases.size()); + Assert.assertTrue(transformer.aliases.containsKey("DE")); + + entityName = "Deposite"; + transformer.createAliasConstant(entityName); + Assert.assertEquals(3, transformer.aliases.size()); + Assert.assertTrue(transformer.aliases.containsKey("DEP")); + + entityName = "Dep"; + transformer.createAliasConstant(entityName); + Assert.assertEquals(4, transformer.aliases.size()); + } +}
participants (1)
-
fdesbois@users.nuiton.org