r2540 - trunk/topia-persistence/src/main/java/org/nuiton/topia/generator
Author: tchemit Date: 2012-05-27 11:38:28 +0200 (Sun, 27 May 2012) New Revision: 2540 Url: http://nuiton.org/repositories/revision/topia/2540 Log: refs #2089: Use JPA (orm) mappings (deal with natural Id) Modified: trunk/topia-persistence/src/main/java/org/nuiton/topia/generator/EntityJPAMappingGenerator.java trunk/topia-persistence/src/main/java/org/nuiton/topia/generator/EntityTransformer.java trunk/topia-persistence/src/main/java/org/nuiton/topia/generator/TopiaGeneratorUtil.java Modified: trunk/topia-persistence/src/main/java/org/nuiton/topia/generator/EntityJPAMappingGenerator.java =================================================================== --- trunk/topia-persistence/src/main/java/org/nuiton/topia/generator/EntityJPAMappingGenerator.java 2012-05-25 16:40:59 UTC (rev 2539) +++ trunk/topia-persistence/src/main/java/org/nuiton/topia/generator/EntityJPAMappingGenerator.java 2012-05-27 09:38:28 UTC (rev 2540) @@ -210,7 +210,7 @@ // -- tag 'mapped-superclass' (fields are on Abstract so use a mapped-superclass) - addMappedSuperclass(output, input, attributes); + addMappedSuperclass(output, input, attributes, embeddableAttributes); // -- tag 'entity' @@ -277,7 +277,8 @@ // -- tag 'embeddable' - addAttribute(xmlAttributes, ATTRIBUTE_CLASS, embeddebaleName); + addAttribute(xmlAttributes, ATTRIBUTE_CLASS, + input.getPackageName() + "." + embeddebaleName); //NOTUSED addAttribute(xmlAttributes, ATTRIBUTE_ACCESS, AccessType.FIELD); /*{<%=flushTag(TAG_EMBEDDABLE, xmlAttributes)%> @@ -285,8 +286,7 @@ Collection<ObjectModelAttribute> attrs = embeddableAttributes.get(embeddebaleName); - generateAttributes(output, input, attrs, false); - + generateAttributes(output, input, attrs, null); /*{<%=closeTag(TAG_EMBEDDABLE)%> }*/ // -- tag 'embeddable' @@ -299,7 +299,8 @@ private void addMappedSuperclass(Writer output, ObjectModelClass input, - List<ObjectModelAttribute> attributes) throws IOException { + List<ObjectModelAttribute> attributes, + Multimap<String, ObjectModelAttribute> embeddableAttributes) throws IOException { Map<String, String> xmlAttributes = new TreeMap<String, String>(); @@ -311,7 +312,7 @@ // generate attributes for the entity - generateAttributes(output, input, attributes, true); + generateAttributes(output, input, attributes, embeddableAttributes); /*{<%=closeTag(TAG_MAPPED_SUPERCLASS)%> }*/ @@ -320,7 +321,7 @@ private void generateAttributes(Writer output, ObjectModelClass input, Collection<ObjectModelAttribute> attributes, - boolean mainEntity) throws IOException { + Multimap<String, ObjectModelAttribute> embeddableAttributes) throws IOException { // split attributes by their mapping type Multimap<PROPERTY_TYPE, ObjectModelAttribute> attributesByType = @@ -373,10 +374,31 @@ generateElementCollectionAttribute(output, input, attribute); } + // generate embedded attributes + if (embeddableAttributes != null) { + + // we are on main entity, check if there is some a natural id to generate + if (embeddableAttributes.containsKey(TopiaGeneratorUtil.GET_NATURAL_ID_CLASS_SIMPLE_NAME.apply(input))) { + + // there is a natural id embedded to generate + generateEmbeddedAttribute(output, input); + } + //TODO-tchemit-2012-05-27 Still nedd to deal with other embedded... + } + /*{<%=closeTag(TAG_ATTRIBUTES)%> }*/ } + private void generateEmbeddedAttribute(Writer output, + ObjectModelClass input) throws IOException { + Map<String, String> xmlAttributes = Maps.newTreeMap(); + addAttribute(xmlAttributes, ATTRIBUTE_NAME, EntityTransformer.NATURAL_ID_FIELD_NAME); + addAttribute(xmlAttributes, ATTRIBUTE_ACCESS, AccessType.FIELD); +/*{<%=flushTag(TAG_EMBEDDED, true, xmlAttributes)%> +}*/ + } + private void generateBasicAttribute(Writer output, ObjectModelClass input, ObjectModelAttribute attr) throws IOException { @@ -1105,9 +1127,10 @@ ObjectModelClass input, List<ObjectModelAttribute> normalAttributes) { Multimap<String, ObjectModelAttribute> result = ArrayListMultimap.create(); + String naturalIdClassName = TopiaGeneratorUtil.GET_NATURAL_ID_CLASS_SIMPLE_NAME.apply(input); for (ObjectModelAttribute attribute : input.getAttributes()) { if (TopiaGeneratorUtil.isNaturalId(attribute)) { - result.put("naturalId", attribute); + result.put(naturalIdClassName, attribute); } else { normalAttributes.add(attribute); } Modified: trunk/topia-persistence/src/main/java/org/nuiton/topia/generator/EntityTransformer.java =================================================================== --- trunk/topia-persistence/src/main/java/org/nuiton/topia/generator/EntityTransformer.java 2012-05-25 16:40:59 UTC (rev 2539) +++ trunk/topia-persistence/src/main/java/org/nuiton/topia/generator/EntityTransformer.java 2012-05-27 09:38:28 UTC (rev 2540) @@ -85,12 +85,17 @@ /** Logger */ private static final Log log = LogFactory.getLog(EntityTransformer.class); + public static final String NATURAL_ID_FIELD_NAME = "naturalId"; + + protected ObjectModelInterface outputInterface; protected ObjectModelClass outputAbstract; protected ObjectModelClass outputImpl; + protected ObjectModelClass outputNaturalIdEmbedded; + private boolean associationClass; protected boolean generateInterface; @@ -99,12 +104,20 @@ protected boolean generateImpl; + protected boolean generateNaturalIdEmbedded; + protected boolean generateBooleanGetMethods; + // la liste des attributs faisant parti de la clef metier + protected List<ObjectModelAttribute> naturalAttributes = new ArrayList<ObjectModelAttribute>(); + // la liste des autres attributs + protected List<ObjectModelAttribute> noneNaturalAttributes = new ArrayList<ObjectModelAttribute>(); + protected void clean() { outputInterface = null; outputAbstract = null; outputImpl = null; + outputNaturalIdEmbedded = null; } @Override @@ -120,7 +133,11 @@ log.debug("for entity : " + input.getQualifiedName()); log.debug("Will use classLoader " + getClassLoader()); } - + + naturalAttributes = new ArrayList<ObjectModelAttribute>(); + + noneNaturalAttributes = new ArrayList<ObjectModelAttribute>(); + // fix once for all the constant prefix to use String prefix = getConstantPrefix(input, ""); if (StringUtils.isEmpty(prefix)) { @@ -135,9 +152,21 @@ } setConstantPrefix(prefix); + //obtains natural ids + for (ObjectModelAttribute attr : input.getAttributes()) { + if (TopiaGeneratorUtil.isNaturalId(attr)) { + // attribut metier + naturalAttributes.add(attr); + } else { + // attribut normal + noneNaturalAttributes.add(attr); + } + } + generateInterface = isGenerateInterface(input); generateAbstract = isGenerateAbstract(input); generateImpl = isGenerateImpl(input); + generateNaturalIdEmbedded= isGenerateNaturalIdEmbedded(input); String noGenerateBooleanGetMethods = TopiaGeneratorUtil.getDoNotGenerateBooleanGetMethods(model, input); @@ -157,12 +186,23 @@ createEntityAbstractClass(input); } + if (generateNaturalIdEmbedded) { + + // Create Entity Natural Id class and its header + createEntityNaturalIdEmbeddedClass(input); + } + // Generate i18n block String i18nPrefix = TopiaGeneratorUtil.getI18nPrefixTagValue(input, model); if (!StringUtils.isEmpty(i18nPrefix)) { generateI18nBlock(input, outputAbstract, i18nPrefix); } + if (!naturalAttributes.isEmpty()) { + + createNaturalIdField(input); + } + // Create accept operation, will be updated during property generation createAcceptOperation(); @@ -301,17 +341,6 @@ for (ObjectModelClass parent : input.getSuperclasses()) { //tchemit-2011-09-12 What ever abstract or not, we alwyas use an Impl, moreover use the util method instead String extendClass = TopiaGeneratorUtil.getDOType(parent, model); -// String extendClass = parent.getQualifiedName(); -// //Si une des classes parentes définies des méthodes abstraites, son -// // impl ne sera pas créé -// boolean abstractParent = TopiaGeneratorUtil.shouldBeAbstract(parent); -// if (TopiaGeneratorUtil.isEntity(parent)) { -// if (abstractParent) { -// extendClass += "Abstract"; -// } else { -// extendClass += "Impl"; -// } -// } setSuperClass(outputAbstract, extendClass); } @@ -323,6 +352,59 @@ addContextableMethods(input, outputAbstract); } + protected void createNaturalIdField(ObjectModelClass input) { + + String fieldName = NATURAL_ID_FIELD_NAME; + + // add a naturalId field + String naturalIdClassName = getNaturalIdClassName(input); + + addAttribute(outputAbstract, + fieldName, naturalIdClassName, "new " + naturalIdClassName + "()", + //ObjectModelModifier.toValue(attrVisibility), + ObjectModelModifier.PROTECTED + ); + + // add a getter + + // Interface operation + ObjectModelOperation interfaceOperation = + addOperation(outputInterface, getJavaBeanMethodName("get", fieldName), + naturalIdClassName, ObjectModelModifier.PUBLIC); + + // Implementation + ObjectModelOperation implOperation = + createImplOperation(interfaceOperation); + + String attrType = + TopiaGeneratorUtil.getSimpleName(naturalIdClassName); + + setOperationBody(implOperation, "" +/*{ + <%=attrType%> result = this.<%=fieldName%>; + return result; + }*/ + ); + } + + protected void createEntityNaturalIdEmbeddedClass(ObjectModelClass input) { + + outputNaturalIdEmbedded = createClass(getNaturalIdClassName(input), + input.getPackageName()); + + // Documentation + StringBuilder doc = new StringBuilder(); + doc.append("Classe représentant la clef naturel de l'entité {@link "); + doc.append(StringUtils.capitalize(outputInterface.getName())); + doc.append("}\n"); + + setDocumentation(outputNaturalIdEmbedded, doc.toString()); + } + + protected String getNaturalIdClassName(ObjectModelClass input) { + return TopiaGeneratorUtil.GET_NATURAL_ID_CLASS_SIMPLE_NAME.apply(input); + } + /** * Ajout les methodes necessaire à l'interface {@link TopiaEntityContextable} * si le tagValue {@link TopiaTagValues#TAG_CONTEXTABLE} est renseigné. @@ -372,6 +454,19 @@ return alreadyInClassPath; } + protected boolean isGenerateNaturalIdEmbedded(ObjectModelClass input) { + + String fqn = getNaturalIdClassName(input); + boolean alreadyInClassPath = isInClassPath(fqn); + if (alreadyInClassPath) { + + return false; + } + + // On génère le natural Id si l'entité possède une clef naturelle + return !naturalAttributes.isEmpty(); + } + protected boolean isGenerateImpl(ObjectModelClass input) { Collection<ObjectModelOperation> operations = input.getOperations(); @@ -538,9 +633,12 @@ //String attrVisibility = attr.getVisibility(); + boolean isNaturalId = isNaturalId(attribute); + // Declaration ObjectModelAttribute property = - addAttribute(outputAbstract, attrName, attrType, null, + addAttribute(isNaturalId ? outputNaturalIdEmbedded : outputAbstract, + attrName, attrType, null, //ObjectModelModifier.toValue(attrVisibility), ObjectModelModifier.PROTECTED ); @@ -561,8 +659,6 @@ // Annotation String annotation = TopiaGeneratorUtil.getAnnotationTagValue(attribute); if (!StringUtils.isEmpty(annotation)) { - //FIXME Make annotation works... - //TODO tchemit 20100513 Test it still works addAnnotation(outputAbstract, property, annotation); } } @@ -693,12 +789,13 @@ attrType = TopiaGeneratorUtil.getSimpleName(attrType); String constantName = getConstantName(attrName); + String receiverName = getReceiverName(attribute, attrName); setOperationBody(implOperation, "" /*{ - <%=attrType%> oldValue = this.<%=attrName%>; + <%=attrType%> oldValue = <%=receiverName%>; fireOnPreWrite(<%=constantName%>, oldValue, <%=attrName%>); - this.<%=attrName%> = <%=attrName%>; + <%=receiverName%> = <%=attrName%>; fireOnPostWrite(<%=constantName%>, oldValue, <%=attrName%>); }*/ ); @@ -720,6 +817,7 @@ String operationPrefix) { String attrName = getPropertyName(attribute); + String receiverName = getReceiverName(attribute, attrName); if (log.isDebugEnabled()) { log.debug("Generate single '" + operationPrefix + "' operation for property : " @@ -741,12 +839,27 @@ setOperationBody(implOperation, "" /*{ - fireOnPreRead(<%=constantName%>, <%=attrName%>); - <%=attrType%> result = this.<%=attrName%>; - fireOnPostRead(<%=constantName%>, <%=attrName%>); + fireOnPreRead(<%=constantName%>, <%=receiverName%>); + <%=attrType%> result = <%=receiverName%>; + fireOnPostRead(<%=constantName%>, <%=receiverName%>); return result; }*/ ); + + if (isNaturalId(attribute)) { + + // add also a getter in the natural id class + implOperation = + cloneOperationSignature(interfaceOperation, outputNaturalIdEmbedded, false, + ObjectModelModifier.PUBLIC ); + + setOperationBody(implOperation, "" +/*{ + <%=attrType%> result = <%=attrName%>; + return result; + }*/ + ); + } } protected void addMultipleAddOperation(ObjectModelAttribute attribute, @@ -775,13 +888,15 @@ attrType = TopiaGeneratorUtil.getSimpleName(attrType); + String receiverName = getReceiverName(attribute, attrName); + StringBuilder body = new StringBuilder(); body.append("" /*{ fireOnPreWrite(<%=constantName%>, null, <%=attrName%>); - if (this.<%=attrName%> == null) { - this.<%=attrName%> = new <%=collectionImpl%><<%=attrType%>>(); + if (<%=receiverName%> == null) { + <%=receiverName%> = new <%=collectionImpl%><<%=attrType%>>(); } }*/ ); @@ -813,8 +928,8 @@ } body.append("" /*{ - this.<%=attrName%>.add(<%=attrName%>); - fireOnPostWrite(<%=constantName%>, this.<%=attrName%>.size(), null, <%=attrName%>); + <%=receiverName%>.add(<%=attrName%>); + fireOnPostWrite(<%=constantName%>, <%=receiverName%>.size(), null, <%=attrName%>); }*/ ); setOperationBody(implOperation, body.toString()); @@ -880,18 +995,30 @@ attrType = TopiaGeneratorUtil.getSimpleName(attrType); referenceType = TopiaGeneratorUtil.getSimpleName(referenceType); + String receiverName = getReceiverName(attribute, attrName); + // Force fire for collection setOperationBody(implOperation, "" /*{ // Copy elements to keep data for fire with new reference - <%=attrType%> oldValue = this.<%=attrName%> != null ? new <%=collectionImpl%><<%=referenceType%>>(this.<%=attrName%>) : null; + <%=attrType%> oldValue = <%=receiverName%> != null ? new <%=collectionImpl%><<%=referenceType%>>(<%=receiverName%>) : null; fireOnPreWrite(<%=constantName%>, oldValue, <%=attrName%>); - this.<%=attrName%> = <%=attrName%>; + <%=receiverName%> = <%=attrName%>; fireOnPostWrite(<%=constantName%>, oldValue, <%=attrName%>); }*/ ); } + protected String getReceiverName(ObjectModelAttribute attribute, String attrName) { + String receiverName; + if (isNaturalId(attribute)) { + receiverName = NATURAL_ID_FIELD_NAME + "." + attrName; + } else { + receiverName = "this." + attrName; + } + return receiverName; + } + protected void addMultipleRemoveOperation(ObjectModelAttribute attribute) { String attrName = getPropertyName(attribute); @@ -916,12 +1043,14 @@ attrType = TopiaGeneratorUtil.getSimpleName(attrType); + String receiverName = getReceiverName(attribute, attrName); + StringBuilder body = new StringBuilder(); body.append("" /*{ fireOnPreWrite(<%=constantName%>, <%=attrName%>, null); - if (this.<%=attrName%> == null || !this.<%=attrName%>.remove(<%=attrName%>)) { + if (<%=receiverName%> == null || !<%=receiverName%>.remove(<%=attrName%>)) { throw new IllegalArgumentException("List does not contain given element"); } }*/ @@ -948,7 +1077,7 @@ } body.append("" /*{ - fireOnPostWrite(<%=constantName%>, this.<%=attrName%>.size() + 1, <%=attrName%>, null); + fireOnPostWrite(<%=constantName%>, <%=receiverName%>.size() + 1, <%=attrName%>, null); }*/ ); setOperationBody(implOperation, body.toString()); @@ -978,9 +1107,11 @@ attrType = TopiaGeneratorUtil.getSimpleName(attrType); + String receiverName = getReceiverName(attribute, attrName); + StringBuilder body = new StringBuilder("" /*{ - if (this.<%=attrName%> == null) { + if (<%=receiverName%> == null) { return; } }*/ @@ -991,7 +1122,7 @@ String getterName = getJavaBeanMethodName("get", reverse.getName()); String setterName = getJavaBeanMethodName("set", reverse.getName()); body.append("" -/*{ for (<%=attrType%> item : this.<%=attrName%>) { +/*{ for (<%=attrType%> item : <%=receiverName%>) { }*/ ); if (!TopiaGeneratorUtil.isNMultiplicity(reverse)) { @@ -1012,10 +1143,10 @@ ); } body.append("" -/*{ <%=collectionInterface%><<%=attrType%>> oldValue = new <%=collectionImpl%><<%=attrType%>>(this.<%=attrName%>); - fireOnPreWrite(<%=constantName%>, oldValue, this.<%=attrName%>); - this.<%=attrName%>.clear(); - fireOnPostWrite(<%=constantName%>, oldValue, this.<%=attrName%>); +/*{ <%=collectionInterface%><<%=attrType%>> oldValue = new <%=collectionImpl%><<%=attrType%>>(<%=receiverName%>); + fireOnPreWrite(<%=constantName%>, oldValue, <%=receiverName%>); + <%=receiverName%>.clear(); + fireOnPostWrite(<%=constantName%>, oldValue, <%=receiverName%>); }*/ ); setOperationBody(implOperation, body.toString()); @@ -1025,6 +1156,9 @@ String collectionInterface) { String attrName = getPropertyName(attribute); + + String receiverName = getReceiverName(attribute, attrName); + String attrType = collectionInterface + "<" + getPropertyType(attribute) + ">"; if (log.isDebugEnabled()) { @@ -1042,7 +1176,7 @@ setOperationBody(implOperation, "" /*{ - return <%=attrName%>; + return <%=receiverName%>; }*/ ); } @@ -1051,6 +1185,7 @@ String attrName = getPropertyName(attribute); String attrType = getPropertyType(attribute); + String receiverName = getReceiverName(attribute, attrName); if (log.isDebugEnabled()) { log.debug("Generate multiple 'getByTopiaId' operation for property : " + attrName + @@ -1072,7 +1207,7 @@ setOperationBody(implOperation, "" /*{ - return TopiaUtil.getEntityByTopiaId(<%=attrName%>, topiaId); + return TopiaUtil.getEntityByTopiaId(<%=receiverName%>, topiaId); }*/ ); } @@ -1087,6 +1222,7 @@ // association attribute name String attrName = getPropertyName(attribute); String attrType = getPropertyType(attribute); + String receiverName = getReceiverName(attribute, attrName); if (log.isDebugEnabled()) { log.debug("Generate multiple 'getFromEntity' operation for property : " + attrName + @@ -1107,10 +1243,10 @@ setOperationBody(implOperation, "" /*{ - if (<%=referenceName%> == null || this.<%=attrName%> == null) { + if (<%=referenceName%> == null || <%=receiverName%> == null) { return null; } - for (<%=attrType%> item : this.<%=attrName%>) { + for (<%=attrType%> item : <%=receiverName%>) { if (<%=referenceName%>.equals(item.<%=referenceGetterName%>())) { return item; } @@ -1123,6 +1259,7 @@ protected void addMultipleSizeOperation(ObjectModelAttribute attribute) { String attrName = getPropertyName(attribute); + String receiverName = getReceiverName(attribute, attrName); if (log.isDebugEnabled()) { log.debug("Generate multiple 'size' operation for property : " + attrName); @@ -1138,10 +1275,10 @@ setOperationBody(implOperation, "" /*{ - if (<%=attrName%> == null) { + if (<%=receiverName%> == null) { return 0; } - return <%=attrName%>.size(); + return <%=receiverName%>.size(); }*/ ); } @@ -1200,6 +1337,7 @@ protected void updateAcceptOperation(ObjectModelAttribute attribute) { String attrName = TopiaGeneratorUtil.getSimpleName(getPropertyName(attribute)); + String receiverName = getReceiverName(attribute, attrName); String attrType = TopiaGeneratorUtil.getSimpleName(getPropertyType(attribute)); String collectionType = getCollectionType(attribute); @@ -1207,12 +1345,12 @@ if (collectionType != null) { collectionType = TopiaGeneratorUtil.getSimpleName(collectionType); acceptOperationBody.append("" -/*{ visitor.visit(this, <%=constantName%>, <%=collectionType%>.class, <%=attrType%>.class, <%=attrName%>); +/*{ visitor.visit(this, <%=constantName%>, <%=collectionType%>.class, <%=attrType%>.class, <%=receiverName%>); }*/ ); } else { acceptOperationBody.append("" -/*{ visitor.visit(this, <%=constantName%>, <%=attrType%>.class, <%=attrName%>); +/*{ visitor.visit(this, <%=constantName%>, <%=attrType%>.class, <%=receiverName%>); }*/ ); } @@ -1262,9 +1400,10 @@ if (isEntity && (reverse == null || !reverse.isNavigable()) && !attr.hasAssociationClass() || !isEntity) { String attrName = attr.getName(); + String receiverName = getReceiverName(attr, attrName); String constantName = getConstantName(attrName); body.append("" -/*{ append(<%=constantName%>, this.<%=attrName%>). +/*{ append(<%=constantName%>, <%=receiverName%>). }*/ ); } @@ -1588,4 +1727,8 @@ } } + + protected boolean isNaturalId(ObjectModelAttribute attr) { + return naturalAttributes.contains(attr); + } } 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 2012-05-25 16:40:59 UTC (rev 2539) +++ trunk/topia-persistence/src/main/java/org/nuiton/topia/generator/TopiaGeneratorUtil.java 2012-05-27 09:38:28 UTC (rev 2540) @@ -25,6 +25,7 @@ package org.nuiton.topia.generator; +import com.google.common.base.Function; import com.google.common.base.Predicate; import com.google.common.base.Predicates; import com.google.common.collect.Collections2; @@ -1804,6 +1805,13 @@ return result; } + public static final Function<ObjectModelClassifier, String> GET_NATURAL_ID_CLASS_SIMPLE_NAME = new Function<ObjectModelClassifier, String>() { + @Override + public String apply(ObjectModelClassifier input) { + return input.getName() + "NaturalId"; + } + }; + public static final Predicate<ObjectModelAttribute> IS_ATTRIBUTE_COMPOSITE = new Predicate<ObjectModelAttribute>() { @Override public boolean apply(ObjectModelAttribute input) {
participants (1)
-
tchemit@users.nuiton.org