Author: tchemit Date: 2012-05-09 18:08:01 +0200 (Wed, 09 May 2012) New Revision: 2455 Url: http://nuiton.org/repositories/revision/topia/2455 Log: add new generator for jpa mapping move all legacy tests to a legacy package add a unit test model for mapping Added: trunk/topia-persistence-tck/src/main/java/org/nuiton/topia/tck/legacy/ trunk/topia-persistence-tck/src/main/java/org/nuiton/topia/tck/legacy/ano1882/ trunk/topia-persistence-tck/src/main/java/org/nuiton/topia/tck/legacy/ano1991/ trunk/topia-persistence-tck/src/main/java/org/nuiton/topia/tck/legacy/evo1912/ trunk/topia-persistence-tck/src/main/java/org/nuiton/topia/tck/legacy/framework/ trunk/topia-persistence-tck/src/main/java/org/nuiton/topia/tck/legacy/generator/ trunk/topia-persistence-tck/src/main/java/org/nuiton/topia/tck/legacy/persistence/ trunk/topia-persistence-tck/src/main/java/org/nuiton/topia/tck/mapping/ trunk/topia-persistence-tck/src/main/java/org/nuiton/topia/tck/mapping/test1/ trunk/topia-persistence-tck/src/main/java/org/nuiton/topia/tck/mapping/test10/ trunk/topia-persistence-tck/src/main/java/org/nuiton/topia/tck/mapping/test11/ trunk/topia-persistence-tck/src/main/java/org/nuiton/topia/tck/mapping/test2/ trunk/topia-persistence-tck/src/main/java/org/nuiton/topia/tck/mapping/test3/ trunk/topia-persistence-tck/src/main/java/org/nuiton/topia/tck/mapping/test4/ trunk/topia-persistence-tck/src/main/java/org/nuiton/topia/tck/mapping/test5/ trunk/topia-persistence-tck/src/main/java/org/nuiton/topia/tck/mapping/test6/ trunk/topia-persistence-tck/src/main/java/org/nuiton/topia/tck/mapping/test7/ trunk/topia-persistence-tck/src/main/java/org/nuiton/topia/tck/mapping/test8/ trunk/topia-persistence-tck/src/main/java/org/nuiton/topia/tck/mapping/test9/ trunk/topia-persistence-tck/src/main/xmi/topia-tck-mapping.properties trunk/topia-persistence-tck/src/main/xmi/topia-tck-mapping.zargo trunk/topia-persistence/src/main/java/org/nuiton/topia/generator/EntityJPAMappingGenerator.java Removed: trunk/topia-persistence-tck/src/main/java/org/nuiton/topia/tck/ano1882/ trunk/topia-persistence-tck/src/main/java/org/nuiton/topia/tck/ano1991/ trunk/topia-persistence-tck/src/main/java/org/nuiton/topia/tck/evo1912/ trunk/topia-persistence-tck/src/main/java/org/nuiton/topia/tck/framework/ trunk/topia-persistence-tck/src/main/java/org/nuiton/topia/tck/generator/ trunk/topia-persistence-tck/src/main/java/org/nuiton/topia/tck/persistence/ Modified: trunk/topia-persistence-tck/src/main/java/org/nuiton/topia/tck/TopiaTckTestSuite.java trunk/topia-persistence-tck/src/main/java/org/nuiton/topia/tck/legacy/ano1882/DAOAbstractTransformerTest.java trunk/topia-persistence-tck/src/main/java/org/nuiton/topia/tck/legacy/ano1991/TopiaQueryTest.java trunk/topia-persistence-tck/src/main/java/org/nuiton/topia/tck/legacy/evo1912/EntityDTOTransformerTest.java trunk/topia-persistence-tck/src/main/java/org/nuiton/topia/tck/legacy/framework/TopiaContextReplicateTest.java trunk/topia-persistence-tck/src/main/java/org/nuiton/topia/tck/legacy/framework/TopiaUtilTest.java trunk/topia-persistence-tck/src/main/java/org/nuiton/topia/tck/legacy/generator/TopiaTestCase.java trunk/topia-persistence-tck/src/main/java/org/nuiton/topia/tck/legacy/persistence/EntityVisitorExportXmlTest.java trunk/topia-persistence-tck/src/main/java/org/nuiton/topia/tck/legacy/persistence/ExportXMLVisitor.java trunk/topia-persistence-tck/src/main/java/org/nuiton/topia/tck/legacy/persistence/NaturalIdTest.java trunk/topia-persistence/pom.xml trunk/topia-persistence/src/main/java/org/nuiton/topia/generator/TopiaMetaTransformer.java Modified: trunk/topia-persistence/pom.xml =================================================================== --- trunk/topia-persistence/pom.xml 2012-05-09 16:07:09 UTC (rev 2454) +++ trunk/topia-persistence/pom.xml 2012-05-09 16:08:01 UTC (rev 2455) @@ -78,6 +78,11 @@ </dependency> <dependency> + <groupId>com.google.guava</groupId> + <artifactId>guava</artifactId> + </dependency> + + <dependency> <groupId>dom4j</groupId> <artifactId>dom4j</artifactId> </dependency> Added: trunk/topia-persistence/src/main/java/org/nuiton/topia/generator/EntityJPAMappingGenerator.java =================================================================== --- trunk/topia-persistence/src/main/java/org/nuiton/topia/generator/EntityJPAMappingGenerator.java (rev 0) +++ trunk/topia-persistence/src/main/java/org/nuiton/topia/generator/EntityJPAMappingGenerator.java 2012-05-09 16:08:01 UTC (rev 2455) @@ -0,0 +1,873 @@ +package org.nuiton.topia.generator; + +import com.google.common.base.Strings; +import com.google.common.collect.ArrayListMultimap; +import com.google.common.collect.LinkedHashMultimap; +import com.google.common.collect.Maps; +import com.google.common.collect.Multimap; +import org.apache.commons.collections.CollectionUtils; +import org.apache.commons.collections.MapUtils; +import org.apache.commons.lang3.BooleanUtils; +import org.apache.commons.lang3.StringUtils; +import org.apache.commons.logging.Log; +import org.apache.commons.logging.LogFactory; +import org.nuiton.eugene.models.object.ObjectModelAttribute; +import org.nuiton.eugene.models.object.ObjectModelClass; +import org.nuiton.eugene.models.object.ObjectModelGenerator; +import org.nuiton.topia.persistence.TopiaEntity; + +import javax.persistence.AccessType; +import javax.persistence.EnumType; +import javax.persistence.FetchType; +import java.beans.Introspector; +import java.io.File; +import java.io.IOException; +import java.io.Writer; +import java.util.ArrayList; +import java.util.Collection; +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import java.util.Set; +import java.util.TreeMap; + +import static org.nuiton.topia.generator.TopiaGeneratorUtil.hasUnidirectionalRelationOnAbstractType; + +/** + * To generate entity jpa mapping files for entities. + * + * @author tchemit <chemit@codelutin.com> + * @plexus.component role="org.nuiton.eugene.Template" role-hint="org.nuiton.topia.generator.EntityJPAMappingGenerator" + * @since 3.0 + */ +public class EntityJPAMappingGenerator extends ObjectModelGenerator { + + /** Logger. */ + private static final Log log = LogFactory + .getLog(EntityJPAMappingGenerator.class); + + public static final String TAG_ENTITY_MAPPINGS = "entity-mappings"; + + public static final String TAG_PACKAGE = "package"; + + public static final String TAG_ENTITY = "entity"; + + public static final String TAG_TABLE = "table"; + + public static final String TAG_UNIQUE_CONTRAINT = "unique-constraint"; + + public static final String TAG_COLUMN_NAME = "column-name"; + + public static final String TAG_ATTRIBUTES = "attributes"; + + public static final String TAG_ID = "id"; + + public static final String TAG_VERSION = "version"; + + public static final String TAG_MANY_TO_ONE = "many-to-one"; + + public static final String TAG_ONE_TO_MANY = "one-to-many"; + + public static final String TAG_ONE_TO_ONE = "one-to-one"; + + public static final String TAG_MANY_TO_MANY = "many-to-many"; + + public static final String TAG_ELEMENT_COLLECTION = "element-collection"; + + public static final String TAG_BASIC = "basic"; + + public static final String TAG_EMBEDDED = "embedded"; + + public static final String TAG_EMBEDDABLE = "embeddable"; + + public static final String TAG_ENUMERATED = "enumerated"; + + public static final String TAG_TEMPORAL = "temporal"; + + public static final String TAG_COLUMN = "column"; + + public static final String TAG_JOIN_COLUMN = "join-column"; + + public static final String TAG_JOIN_TABLE = "join-table"; + + public static final String TAG_GENERATED_VALUE = "generated-value"; + + public static final String TAG_CASCADE = "cascade"; + + public static final String TAG_CASCADE_ALL = "cascade-all"; + + public static final String TAG_CASCADE_REMOVE = "cascade-remove"; + + public static final String ATTRIBUTE_CLASS = "class"; + + public static final String ATTRIBUTE_GENERATOR = "generator"; + + public static final String ATTRIBUTE_STRATEGY = "strategy"; + + public static final String ATTRIBUTE_ACCESS = "access"; + + public static final String ATTRIBUTE_METADATA_COMPLETE = "metadata-complete"; + + public static final String ATTRIBUTE_NAME = "name"; + + public static final String ATTRIBUTE_CACHEABLE = "cacheable"; + + public static final String ATTRIBUTE_SCHEMA = "schema"; + + public static final String ATTRIBUTE_CATALOG = "catalog"; + + public static final String ATTRIBUTE_OPTIONAL = "optional"; + + public static final String ATTRIBUTE_FETCH = "fetch"; + + private static final String ATTRIBUTE_ORPHAN_REMOVAL = "orphan-removal"; + + public static final String ATTRIBUTE_COLUMN_DEFINITION = "column-definition"; + + public static final String ATTRIBUTE_INSERTABLE = "insertable"; + + public static final String ATTRIBUTE_LENGTH = "length"; + + public static final String ATTRIBUTE_NULLABLE = "nullable"; + + public static final String ATTRIBUTE_PRECISION = "precision"; + + public static final String ATTRIBUTE_SCALE = "scale"; + + public static final String ATTRIBUTE_TABLE = "table"; + + public static final String ATTRIBUTE_UNIQUE = "unique"; + + public static final String ATTRIBUTE_UPDATABLE = "updatable"; + + public static final String ATTRIBUTE_REFERENCE_COLUMN_NAME = "referencedColumnName"; + + private Map<String, String[]> columnNamesMap = new HashMap<String, String[]>(); + + @Override + public String getFilenameForClass(ObjectModelClass clazz) { + String result = TopiaGeneratorUtil.getDOType(clazz, model); + return result.replace('.', File.separatorChar) + "-orm.xml"; + } + + + protected Multimap<String, ObjectModelAttribute> splitAttributes( + ObjectModelClass input, + List<ObjectModelAttribute> normalAttributes) { + Multimap<String, ObjectModelAttribute> result = ArrayListMultimap.create(); + for (ObjectModelAttribute attribute : input.getAttributes()) { + if (TopiaGeneratorUtil.isNaturalId(attribute)) { + result.put("naturalId", attribute); + } else { + normalAttributes.add(attribute); + } + } + return result; + } + + @Override + public void generateFromClass(Writer output, + ObjectModelClass input) throws IOException { + + xmlLevel=0; + + String persistenceType = TopiaGeneratorUtil.getPersistenceType(input); + if (!TopiaGeneratorUtil.isEntity(input) && + TopiaGeneratorUtil.PERSISTENCE_TYPE_HIBERNATE.equals(persistenceType)) { + return; + } +/*{<?xml version="1.0" encoding="UTF-8"?> +}*/ + Map<String, String> xmlAttributes = new TreeMap<String, String>(); + + // -- tag 'entity-mappings' + + addAttribute(xmlAttributes, "xmlns", "http://java.sun.com/xml/ns/persistence/orm"); + addAttribute(xmlAttributes, "xmlns:xsi", "http://www.w3.org/2001/XMLSchema-instance"); + addAttribute(xmlAttributes, "xsi:schemaLocation", "http://java.sun.com/xml/ns/persistence/orm http://java.sun.com/xml/ns/persistence/orm_2_0.xsd"); + addAttribute(xmlAttributes, "version", "2.0"); +/*{<%=flushTag(TAG_ENTITY_MAPPINGS, xmlAttributes)%> +}*/ + + // -- tag 'package' + +/*{<%=flushTag(TAG_PACKAGE, input.getPackageName())%><%=closeStrictTag(TAG_PACKAGE)%> +}*/ + + // -- tag 'entity' + + String clazzFQN = input.getQualifiedName(); + + + addAttribute(xmlAttributes, ATTRIBUTE_NAME, clazzFQN); + addAttribute(xmlAttributes, ATTRIBUTE_CLASS, input.getName() + "Impl"); + addAttribute(xmlAttributes, ATTRIBUTE_ACCESS, AccessType.FIELD); + addAttribute(xmlAttributes, ATTRIBUTE_METADATA_COMPLETE, true); +//NOTUSED addAttribute(xmlAttributes, ATTRIBUTE_CACHEABLE, true); +//NOTUSED addAttribute(xmlAttributes, ATTRIBUTE_NAME, ""); +/*{<%=flushTag(TAG_ENTITY, xmlAttributes)%> +}*/ + + boolean haveSuper = input.getSuperclasses().size() > 0; + + // la liste des autres attributs + List<ObjectModelAttribute> attributes = + new ArrayList<ObjectModelAttribute>(); + + // Split attributes for each embeddable + Multimap<String, ObjectModelAttribute> embeddableAttributes = + splitAttributes(input, attributes); + + // get all unique constraints to add + Multimap<String, String> uniqueContraints = getUniqueConstraints( + input, attributes, embeddableAttributes); + + String tableName = TopiaGeneratorUtil.getDbName(input); + String isAbstract = BooleanUtils.toStringTrueFalse(input.isAbstract()); + String clazzDOType = TopiaGeneratorUtil.getDOType(input, model); + + // -- tag 'table' + + addAttribute(xmlAttributes, ATTRIBUTE_NAME, tableName); + String schema = TopiaGeneratorUtil.getDbSchemaNameTagValue(input, model); + if (schema != null) { + addAttribute(xmlAttributes, ATTRIBUTE_SCHEMA, schema); + } +//NOTUSED addAttribute(attributes, ATTRIBUTE_CATALOG, ""); +/*{<%=flushTag(TAG_TABLE, uniqueContraints.isEmpty(), xmlAttributes)%> +}*/ + if (!uniqueContraints.isEmpty()) { + for (String uniqueContraintName : uniqueContraints.keySet()) { + addAttribute(xmlAttributes, ATTRIBUTE_NAME, uniqueContraintName); +/*{<%=flushTag(TAG_UNIQUE_CONTRAINT, xmlAttributes)%> +}*/ + for (String uniqueContraint : + uniqueContraints.get(uniqueContraintName)) { +/*{<%=flushTag(TAG_COLUMN_NAME, uniqueContraint)%> +}*/ + } +/*{<%=closeTag(TAG_UNIQUE_CONTRAINT)%> +}*/ + } +/*{<%=closeTag(TAG_TABLE)%> +}*/ + } + + // generate attributes for the entity + + generateAttributes(output, input, attributes, true); + +/*{<%=closeTag(TAG_ENTITY)%> +}*/ + + // generate embeddable if necessary + + Set<String> embeddebaleNames = embeddableAttributes.keySet(); + + if (CollectionUtils.isNotEmpty(embeddebaleNames)) { + + for (String embeddebaleName : embeddebaleNames) { + + // -- tag 'embeddable' + + addAttribute(xmlAttributes, ATTRIBUTE_CLASS, embeddebaleName); +//NOTUSED addAttribute(xmlAttributes, ATTRIBUTE_ACCESS, AccessType.FIELD); + +/*{<%=flushTag(TAG_EMBEDDABLE, xmlAttributes)%> +}*/ + Collection<ObjectModelAttribute> attrs = + embeddableAttributes.get(embeddebaleName); + + generateAttributes(output, input, attrs, false); + +/*{<%=closeTag(TAG_EMBEDDABLE)%> +}*/ + // -- tag 'embeddable' + } + } + +/*{<%=closeTag(TAG_ENTITY_MAPPINGS)%> +}*/ + } + + private void generateAttributes(Writer output, + ObjectModelClass input, + Collection<ObjectModelAttribute> attributes, + boolean mainEntity) throws IOException { + + // split attributes by their mapping type + Multimap<PROPERTY_TYPE, ObjectModelAttribute> attributesByType = + splitAttributesByType(attributes); + + Map<String, String> xmlAttributes = Maps.newTreeMap(); + + // -- tag 'attributes' + +/*{<%=flushTag(TAG_ATTRIBUTES)%> +}*/ + if (mainEntity) { + + // add id tag + + addAttribute(xmlAttributes, ATTRIBUTE_NAME, TopiaEntity.TOPIA_ID); +//NOTUSED addAttribute(xmlAttributes, ATTRIBUTE_ACCESS, AccessType.FIELD); +/*{<%=flushTag(TAG_ID, xmlAttributes)%> +}*/ +//NOTUSED addAttribute(xmlAttributes, ATTRIBUTE_GENERATOR, "generatorFQN"); +//NOTUSED addAttribute(xmlAttributes, ATTRIBUTE_STRATEGY, GenerationType.AUTO); + +/*{<%=flushTag(TAG_GENERATED_VALUE, true, xmlAttributes)%> +<%=closeTag(TAG_ID)%> +}*/ + // add topiaCreateDate + /** + * <property name="topiaCreateDate" type="timestamp" node="@topiaCreateDate"/> + */ + addAttribute(xmlAttributes, ATTRIBUTE_NAME, TopiaEntity.TOPIA_CREATE_DATE); + + } + + // generate basic attributes + Collection<ObjectModelAttribute> basicAttributes = + attributesByType.get(PROPERTY_TYPE.BASIC); + for (ObjectModelAttribute attribute : basicAttributes) { + generateBasicAttribute(output, input, attribute, xmlAttributes); + } + + if (mainEntity) { + + // add version tag + addAttribute(xmlAttributes, ATTRIBUTE_NAME, TopiaEntity.TOPIA_VERSION); +//NOTUSED addAttribute(xmlAttributes, ATTRIBUTE_ACCESS, AccessType.FIELD); +/*{<%=flushTag(TAG_VERSION, true, xmlAttributes)%> +}*/ + } + // generate many-to-one attributes + Collection<ObjectModelAttribute> manyToOneAttributes = + attributesByType.get(PROPERTY_TYPE.MANY_TO_ONE); + for (ObjectModelAttribute attribute : manyToOneAttributes) { + generateManyToOneAttribute(output, input, attribute, false); + } + // generate one-to-many attributes + Collection<ObjectModelAttribute> oneToManyAttributes = + attributesByType.get(PROPERTY_TYPE.ONE_TO_MANY); + for (ObjectModelAttribute attribute : oneToManyAttributes) { + generateOneToManyAttribute(output, input, attribute); + } + + // generate one-to-one attributes + Collection<ObjectModelAttribute> oneToOneAttributes = + attributesByType.get(PROPERTY_TYPE.ONE_TO_ONE); + for (ObjectModelAttribute attribute : oneToOneAttributes) { + generateOneToOneAttribute(output, input, attribute); + } + + // generate many-to-many attributes + Collection<ObjectModelAttribute> manyToManyAttributes = + attributesByType.get(PROPERTY_TYPE.MANY_TO_MANY); + for (ObjectModelAttribute attribute : manyToManyAttributes) { + generateManyToManyAttribute(output, input, attribute); + } + + // generate element-collection attributes + Collection<ObjectModelAttribute> elementCollectionAttributes = + attributesByType.get(PROPERTY_TYPE.ELEMENT_COLLECTION); + for (ObjectModelAttribute attribute : elementCollectionAttributes) { + generateElementCollectionAttribute(output, input, attribute); + } + +/*{<%=closeTag(TAG_ATTRIBUTES)%> +}*/ + } + + private void generateBasicAttribute(Writer output, + ObjectModelClass input, + ObjectModelAttribute attr, + Map<String, String> xmlAttributes) throws IOException { + + Map<String, String> columnAttributes = Maps.newTreeMap(); + String attrType = getType(attr); + String attrName = attr.getName(); + String declaringElementDBName = + TopiaGeneratorUtil.getDbName(attr.getDeclaringElement()); + String tableName = declaringElementDBName + "_" + attrName; + boolean attrIsEnumeration = attr.getClassifier() != null + && attr.getClassifier().isEnum(); + + addAttribute(xmlAttributes, ATTRIBUTE_NAME, attrName); + if (attrType.trim().endsWith("[]")) { + + //FIXME :( (perharps should use a element-collection instead ? + + } else { + if (TopiaGeneratorUtil.hasUniqueStereotype(attr)) { + addAttribute(columnAttributes, ATTRIBUTE_UNIQUE, true); + } + + if (StringUtils.isNotEmpty(attr.getDefaultValue())) { + //TC-20100129 with a default value we must use the column child tag + + //FIXME :( +// String defaultValue = attr.getDefaultValue().trim(); +// columnAttributes.put(HIBERNATE_ATTRIBUTE_DEFAULT, defaultValue); + } + String sqlType = TopiaGeneratorUtil.getSqlTypeTagValue(attr); + if (!StringUtils.isEmpty(sqlType)) { + + //FIXME :( +// // an specific sql type was specified for the attribute, use it +// columnAttributes.put(HIBERNATE_ATTRIBUTE_SQL_TYPE, sqlType); + } + + String lengthTagValue = TopiaGeneratorUtil.getLengthTagValue(attr); + if (!StringUtils.isEmpty(lengthTagValue)) { + + addAttribute(columnAttributes, ATTRIBUTE_LENGTH, lengthTagValue); + } + String notNullTagValue = TopiaGeneratorUtil.getNotNullTagValue(attr); + if ("true".equals(notNullTagValue)) { + + // not optional + addAttribute(xmlAttributes, ATTRIBUTE_OPTIONAL, false); + addAttribute(columnAttributes, ATTRIBUTE_NULLABLE, false); + } + + String[] columnNames = columnNamesMap.get(attrType); + + // to know if specific column name mapping is given + boolean noSpecifiedColumn = columnNames == null || columnNames.length == 0; + + if (noSpecifiedColumn) { + +/*{<%=flushTag(TAG_BASIC, xmlAttributes)%> +}*/ + String attrColumn = TopiaGeneratorUtil.getDbName(attr); + + if (!attrName.equals(attrColumn)) { + + // override column name + addAttribute(columnAttributes, ATTRIBUTE_NAME, attrColumn); + } + + // add column if required + + if (MapUtils.isNotEmpty(columnAttributes)) { + +/*{<%=flushTag(TAG_COLUMN, true, columnAttributes)%> +}*/ + } + + if (attrIsEnumeration) { + + // if the user tuned the model to use name instead of + // ordinal to store the values, we must add a clause + boolean useEnumerationName = + TopiaGeneratorUtil.hasUseEnumerationNameTagValue( + attr, model); + EnumType type = useEnumerationName ? EnumType.STRING : + EnumType.ORDINAL; +/*{<%=flushTag(TAG_ENUMERATED, true, type.name())%> +}*/ + } +/*{<%=closeTag(TAG_BASIC)%> +}*/ + } else { + + // there is a colum name mapping specified, must use it + //FIXME :( + } + } + } + + private void generateManyToOneAttribute(Writer output, + ObjectModelClass input, + ObjectModelAttribute attr, + boolean unique) throws IOException { + + Map<String, String> xmlAttributes = Maps.newTreeMap(); + Map<String, String> columnAttributes = Maps.newTreeMap(); + + String attrName = getName(attr); + addAttribute(xmlAttributes, ATTRIBUTE_NAME, attrName); + + String attrColumn = TopiaGeneratorUtil.getDbName(attr); + + if ("true".equals(TopiaGeneratorUtil.getNotNullTagValue(attr))) { + + // not-null property + addAttribute(xmlAttributes, ATTRIBUTE_OPTIONAL, false); + addAttribute(columnAttributes, ATTRIBUTE_NULLABLE, false); + } + + if ("true".equals(TopiaGeneratorUtil.getLazyTagValue(attr))) { + + // lazy property + addAttribute(xmlAttributes, ATTRIBUTE_FETCH, FetchType.LAZY); + } + + if (unique) { + addAttribute(columnAttributes, ATTRIBUTE_UNIQUE, true); + } + + if (!attrName.equals(attrColumn)) { + addAttribute(columnAttributes, ATTRIBUTE_NAME, attrColumn); + } + +//NOTUSED addAttribute(columnAttributes, ATTRIBUTE_REFERENCE_COLUMN_NAME, TopiaEntity.TOPIA_ID); + + boolean withDeleteCascade = false; + if (attr.isComposite() || attr.hasAssociationClass()) { + withDeleteCascade = true; + } + + // Pour le test suivant, on verifie d'abord que l'attribut a un reverse. + // S'il n'en a pas, cela signifie qu'il ne s'agit pas d'un entite + // (au sens stereotype entity), donc a donc pas besoin de faire un access=field. + if (attr.getReverseAttribute() != null && + hasUnidirectionalRelationOnAbstractType(attr.getReverseAttribute(), model)) { + addAttribute(xmlAttributes, ATTRIBUTE_ACCESS, AccessType.FIELD); + } + +/*{<%=flushTag(TAG_MANY_TO_ONE, xmlAttributes)%> +}*/ + if (MapUtils.isNotEmpty(columnAttributes)) { +/*{<%=flushTag(TAG_JOIN_COLUMN, true, columnAttributes)%> +}*/ + } + if (withDeleteCascade) { +/*{<%=flushTag(TAG_CASCADE)%> +<%=flushTag(TAG_CASCADE_REMOVE, true)%> +<%=closeTag(TAG_CASCADE)%> +}*/ + } +/*{<%=closeTag(TAG_MANY_TO_ONE)%> +}*/ + } + + private void generateOneToManyAttribute(Writer output, + ObjectModelClass input, + ObjectModelAttribute attr) throws IOException { + Map<String, String> xmlAttributes = Maps.newTreeMap(); + boolean needsIndex = TopiaGeneratorUtil.hasIndexedStereotype(attr); + boolean isInverse = attr.getReverseAttribute().isNavigable(); + isInverse |= hasUnidirectionalRelationOnAbstractType(attr, model); + + Map<String, String> columnAttributes = Maps.newTreeMap(); + + String attrName = getName(attr); + addAttribute(xmlAttributes, ATTRIBUTE_NAME, attrName); + + String reverseAttrDBName = TopiaGeneratorUtil.getReverseDbName(attr); + String orderBy = TopiaGeneratorUtil.getOrderByTagValue(attr); + + if ("true".equals(TopiaGeneratorUtil.getLazyTagValue(attr))) { + + // lazy property + addAttribute(xmlAttributes, ATTRIBUTE_FETCH, FetchType.LAZY); + } + if (attr.isComposite() || attr.hasAssociationClass()) { + addAttribute(xmlAttributes, ATTRIBUTE_ORPHAN_REMOVAL, true); + } + + addAttribute(columnAttributes, ATTRIBUTE_NAME, reverseAttrDBName); + +/*{<%=flushTag(TAG_ONE_TO_MANY, xmlAttributes)%> +}*/ + + if (StringUtils.isNotBlank(orderBy)) { + //TODO Order-by or order-column ? + } + + if (needsIndex) { + } else { + } + + if (MapUtils.isNotEmpty(columnAttributes)) { +/*{<%=flushTag(TAG_JOIN_COLUMN, true, columnAttributes)%> +}*/ + } + +/*{<%=flushTag(TAG_CASCADE)%> +<%=flushTag(TAG_CASCADE_ALL, true)%> +<%=closeTag(TAG_CASCADE)%> +}*/ +/*{<%=closeTag(TAG_ONE_TO_MANY)%> +}*/ + } + + private void generateOneToOneAttribute(Writer output, + ObjectModelClass input, + ObjectModelAttribute attr) throws IOException { + + + // for hibernate many-to-one with unique="true" => one-to-one + // but if it is one-to-zero-or-one unique contraints is violated + // with null values + boolean unique = TopiaGeneratorUtil.isOneMultiplicity(attr); + generateManyToOneAttribute(output, input, attr, unique); + } + + private void generateManyToManyAttribute(Writer output, + ObjectModelClass input, + ObjectModelAttribute attr) throws IOException { + Map<String, String> xmlAttributes = Maps.newTreeMap(); + } + + private void generateElementCollectionAttribute(Writer output, + ObjectModelClass input, + ObjectModelAttribute attr) throws IOException { + Map<String, String> xmlAttributes = Maps.newTreeMap(); + } + + private void addAttribute(Map<String, String> attributes, + String attributeName, + boolean attributeValue) { + attributes.put(attributeName, String.valueOf(attributeValue)); + } + + private void addAttribute(Map<String, String> attributes, + String attributeName, + String attributeValue) { + attributes.put(attributeName, attributeValue); + } + + private void addAttribute(Map<String, String> attributes, + String attributeName, + Enum attributeValue) { + attributes.put(attributeName, attributeValue.name()); + } + + private void addAttributeFromTagValue(Map<String, String> attributes, + String attributeName, String tagValue) { + addAttributeFromTagValue(attributes, + attributeName, tagValue, null); + } + + /** + * Generate hibernate xml attribute with a final space. + * + * @param attributeName + * @param tagValue + * @param defaultValue + * @return + */ + private void addAttributeFromTagValue(Map<String, String> attributes, + String attributeName, + String tagValue, + String defaultValue) { + if (StringUtils.isNotEmpty(tagValue)) { + attributes.put(attributeName, tagValue); + } else if (defaultValue != null) { + attributes.put(attributeName, defaultValue); + } + } + + private int xmlLevel = 0; + + private String flushTag(String tagName) { + return flushTag(tagName, false, null, null); + } + + private String flushTag(String tagName, boolean autoClose) { + return flushTag(tagName, autoClose, null, null); + } + + private String flushTag(String tagName, String textValue) { + return flushTag(tagName, false, null, textValue); + } + + private String flushTag(String tagName, boolean autoClose, + String textValue) { + return flushTag(tagName, autoClose, null, textValue); + } + + private String flushTag(String tagName, + Map<String, String> attributes, + String textValue) { + return flushTag(tagName, false, attributes, textValue); + } + + private String flushTag(String tagName, + boolean autoClose, + Map<String, String> attributes) { + return flushTag(tagName, autoClose, attributes, null); + } + + private String flushTag(String tagName, + Map<String, String> attributes) { + return flushTag(tagName, false, attributes, null); + } + + + private String flushTag(String tagName, + boolean autoClose, + Map<String, String> attributes, + String textValue) { + + if (log.isInfoEnabled()) { + log.info("flushTag <" + tagName + "> : level " + xmlLevel); + } + StringBuilder builder = new StringBuilder(getXmlPrefix()); + xmlLevel++; + builder.append("<").append(tagName); + if (MapUtils.isNotEmpty(attributes)) { + for (Map.Entry<String, String> e : attributes.entrySet()) { + String attrName = e.getKey(); + String attrValue = e.getValue(); + builder.append(' '); + builder.append(attrName); + builder.append("=\""); + builder.append(attrValue); + builder.append('\"'); + } + attributes.clear(); + } + if (autoClose) { + builder.append("/>"); + xmlLevel--; + } else { + builder.append(">"); + if (textValue != null) { + builder.append(textValue); + } + } + return builder.toString(); + } + + private String closeStrictTag(String tagName) { + xmlLevel--; + String result = "</" + tagName + ">"; + if (log.isInfoEnabled()) { + log.info("closeStrictTag <" + tagName + "> : level " + xmlLevel); + } + return result; + } + + private String closeTag(String tagName) { + xmlLevel--; + String result = getXmlPrefix() + "</" + tagName + ">"; + if (log.isInfoEnabled()) { + log.info("closeTag <" + tagName + "> : level " + xmlLevel); + } + return result; + } + + private String getXmlPrefix() { + String result = Strings.padStart("", xmlLevel * 2, ' '); + return result; + } + + + public enum PROPERTY_TYPE { + BASIC, + MANY_TO_ONE, + MANY_TO_MANY, + ONE_TO_ONE, + ONE_TO_MANY, + ELEMENT_COLLECTION + } + + private Multimap<PROPERTY_TYPE, ObjectModelAttribute> splitAttributesByType( + Collection<ObjectModelAttribute> attributes) { + + Multimap<PROPERTY_TYPE, ObjectModelAttribute> result = + LinkedHashMultimap.create(); + + for (ObjectModelAttribute attr : attributes) { + ObjectModelAttribute reverse = attr.getReverseAttribute(); + + // pour les asso quoi qu'il arrive il faut les lier des 2 cotes + // pour pouvoir supprimer en cascade l'asso lors de la suppression + // d'un des cotes + if (attr.isNavigable() + || hasUnidirectionalRelationOnAbstractType(reverse, model) + || attr.hasAssociationClass()) { + if (!TopiaGeneratorUtil.isNMultiplicity(attr)) { + if (attr.getClassifier() != null && TopiaGeneratorUtil.isEntity(attr.getClassifier())) { + if (TopiaGeneratorUtil.isNMultiplicity(attr.getReverseMaxMultiplicity()) && !attr.hasAssociationClass()) { + + result.put(PROPERTY_TYPE.MANY_TO_ONE, attr); + } else { + result.put(PROPERTY_TYPE.ONE_TO_ONE, attr); + } + } else { + result.put(PROPERTY_TYPE.BASIC, attr); + } + } else { + if (attr.getClassifier() != null && TopiaGeneratorUtil.isEntity(attr.getClassifier())) { + if (TopiaGeneratorUtil.isNMultiplicity(attr.getReverseMaxMultiplicity()) && !attr.hasAssociationClass()) { + result.put(PROPERTY_TYPE.MANY_TO_MANY, attr); + } else { + result.put(PROPERTY_TYPE.ONE_TO_MANY, attr); + } + } else { + result.put(PROPERTY_TYPE.ELEMENT_COLLECTION, attr); + } + } + } + } + + return result; + } + + private Multimap<String, String> getUniqueConstraints(ObjectModelClass input, + List<ObjectModelAttribute> attributes, + Multimap<String, ObjectModelAttribute> embeddableAttributes) { + Multimap<String, String> result = ArrayListMultimap.create(); + return result; + } + + protected String getName(ObjectModelAttribute attr) { + return getName(attr, false); + } + + protected String getName(ObjectModelAttribute attr, boolean isAssoc) { + String result = Introspector.decapitalize(attr.getName()); + if (attr.hasAssociationClass() && !isAssoc) { + result = TopiaGeneratorUtil.getAssocAttrName(attr); + } + return result; + } + + protected String getType(ObjectModelAttribute attr) { + return getType(attr, false); + } + + protected String getType(ObjectModelAttribute attr, boolean isAssoc) { + String type = attr.getType(); + String attrType = TopiaGeneratorUtil.getTypeTagValue(attr); + if (StringUtils.isNotEmpty(attrType)) { + + // tag value detected of the attribute + type = attrType; + } else { + + //FIXME :( + String modelType = model.getTagValue(type); + if (StringUtils.isNotEmpty(modelType)) { + + // tag value detected of the model + + //TODO tchemit 20100507 Explain What todes it do ? Dont understand the story of columnNamesMap + int bracketIndex = modelType.indexOf('('); + if (bracketIndex != -1) { + type = modelType.substring(0, bracketIndex); + int bracketEndIndex = modelType.indexOf(')', bracketIndex + 1); + String colmunList; + if (bracketEndIndex != -1) { + colmunList = modelType.substring(bracketIndex + 1, bracketEndIndex); + } else { + colmunList = modelType.substring(bracketIndex); + } + columnNamesMap.put(type, colmunList.split(",")); + } else { + type = modelType; + } + } + } + if (attr.hasAssociationClass() && !isAssoc) { + type = attr.getAssociationClass().getQualifiedName(); + } + return TopiaGeneratorUtil.getDOType(type, model); + } +} Modified: trunk/topia-persistence/src/main/java/org/nuiton/topia/generator/TopiaMetaTransformer.java =================================================================== --- trunk/topia-persistence/src/main/java/org/nuiton/topia/generator/TopiaMetaTransformer.java 2012-05-09 16:07:09 UTC (rev 2454) +++ trunk/topia-persistence/src/main/java/org/nuiton/topia/generator/TopiaMetaTransformer.java 2012-05-09 16:08:01 UTC (rev 2455) @@ -67,7 +67,8 @@ // DAOImplTransformer.class, // DAOAbstractTransformer.class, DAOHelperTransformer.class, - EntityHibernateMappingGenerator.class + EntityHibernateMappingGenerator.class, + EntityJPAMappingGenerator.class ); } Modified: trunk/topia-persistence-tck/src/main/java/org/nuiton/topia/tck/TopiaTckTestSuite.java =================================================================== --- trunk/topia-persistence-tck/src/main/java/org/nuiton/topia/tck/TopiaTckTestSuite.java 2012-05-09 16:07:09 UTC (rev 2454) +++ trunk/topia-persistence-tck/src/main/java/org/nuiton/topia/tck/TopiaTckTestSuite.java 2012-05-09 16:08:01 UTC (rev 2455) @@ -3,16 +3,16 @@ import org.junit.runner.RunWith; import org.junit.runners.Suite; import org.nuiton.topia.TopiaContextFactoryTest; -import org.nuiton.topia.tck.ano1882.DAOAbstractTransformerTest; -import org.nuiton.topia.tck.ano1991.TopiaQueryTest; -import org.nuiton.topia.tck.evo1912.EntityDTOTransformerTest; -import org.nuiton.topia.tck.framework.TopiaContextReplicateTest; -import org.nuiton.topia.tck.framework.TopiaUtilTest; -import org.nuiton.topia.tck.generator.TopiaTestCase; +import org.nuiton.topia.tck.legacy.ano1882.DAOAbstractTransformerTest; +import org.nuiton.topia.tck.legacy.ano1991.TopiaQueryTest; +import org.nuiton.topia.tck.legacy.evo1912.EntityDTOTransformerTest; +import org.nuiton.topia.tck.legacy.framework.TopiaContextReplicateTest; +import org.nuiton.topia.tck.legacy.framework.TopiaUtilTest; +import org.nuiton.topia.tck.legacy.generator.TopiaTestCase; import org.nuiton.topia.tck.it.EnumTest; import org.nuiton.topia.tck.it.deletetest.DeleteEntityTest; -import org.nuiton.topia.tck.persistence.EntityVisitorExportXmlTest; -import org.nuiton.topia.tck.persistence.NaturalIdTest; +import org.nuiton.topia.tck.legacy.persistence.EntityVisitorExportXmlTest; +import org.nuiton.topia.tck.legacy.persistence.NaturalIdTest; /** * @author Arnaud Thimel <thimel@codelutin.com> Modified: trunk/topia-persistence-tck/src/main/java/org/nuiton/topia/tck/legacy/ano1882/DAOAbstractTransformerTest.java =================================================================== --- trunk/topia-persistence-tck/src/main/java/org/nuiton/topia/tck/ano1882/DAOAbstractTransformerTest.java 2012-05-09 15:48:05 UTC (rev 2453) +++ trunk/topia-persistence-tck/src/main/java/org/nuiton/topia/tck/legacy/ano1882/DAOAbstractTransformerTest.java 2012-05-09 16:08:01 UTC (rev 2455) @@ -22,7 +22,7 @@ * <http://www.gnu.org/licenses/lgpl-3.0.html>. * #L% */ -package org.nuiton.topia.tck.ano1882; +package org.nuiton.topia.tck.legacy.ano1882; import org.junit.Rule; import org.junit.Test; Modified: trunk/topia-persistence-tck/src/main/java/org/nuiton/topia/tck/legacy/ano1991/TopiaQueryTest.java =================================================================== --- trunk/topia-persistence-tck/src/main/java/org/nuiton/topia/tck/ano1991/TopiaQueryTest.java 2012-05-09 15:48:05 UTC (rev 2453) +++ trunk/topia-persistence-tck/src/main/java/org/nuiton/topia/tck/legacy/ano1991/TopiaQueryTest.java 2012-05-09 16:08:01 UTC (rev 2455) @@ -22,7 +22,7 @@ * <http://www.gnu.org/licenses/lgpl-3.0.html>. * #L% */ -package org.nuiton.topia.tck.ano1991; +package org.nuiton.topia.tck.legacy.ano1991; import org.junit.Assert; import org.junit.Rule; Modified: trunk/topia-persistence-tck/src/main/java/org/nuiton/topia/tck/legacy/evo1912/EntityDTOTransformerTest.java =================================================================== --- trunk/topia-persistence-tck/src/main/java/org/nuiton/topia/tck/evo1912/EntityDTOTransformerTest.java 2012-05-09 15:48:05 UTC (rev 2453) +++ trunk/topia-persistence-tck/src/main/java/org/nuiton/topia/tck/legacy/evo1912/EntityDTOTransformerTest.java 2012-05-09 16:08:01 UTC (rev 2455) @@ -22,7 +22,7 @@ * <http://www.gnu.org/licenses/lgpl-3.0.html>. * #L% */ -package org.nuiton.topia.tck.evo1912; +package org.nuiton.topia.tck.legacy.evo1912; import org.junit.Assert; import org.junit.Test; Modified: trunk/topia-persistence-tck/src/main/java/org/nuiton/topia/tck/legacy/framework/TopiaContextReplicateTest.java =================================================================== --- trunk/topia-persistence-tck/src/main/java/org/nuiton/topia/tck/framework/TopiaContextReplicateTest.java 2012-05-09 15:48:05 UTC (rev 2453) +++ trunk/topia-persistence-tck/src/main/java/org/nuiton/topia/tck/legacy/framework/TopiaContextReplicateTest.java 2012-05-09 16:08:01 UTC (rev 2455) @@ -22,7 +22,7 @@ * <http://www.gnu.org/licenses/lgpl-3.0.html>. * #L% */ -package org.nuiton.topia.tck.framework; +package org.nuiton.topia.tck.legacy.framework; import org.junit.Assert; import org.junit.Rule; Modified: trunk/topia-persistence-tck/src/main/java/org/nuiton/topia/tck/legacy/framework/TopiaUtilTest.java =================================================================== --- trunk/topia-persistence-tck/src/main/java/org/nuiton/topia/tck/framework/TopiaUtilTest.java 2012-05-09 15:48:05 UTC (rev 2453) +++ trunk/topia-persistence-tck/src/main/java/org/nuiton/topia/tck/legacy/framework/TopiaUtilTest.java 2012-05-09 16:08:01 UTC (rev 2455) @@ -23,7 +23,7 @@ * #L% */ -package org.nuiton.topia.tck.framework; +package org.nuiton.topia.tck.legacy.framework; import org.junit.Rule; import org.junit.Test; Modified: trunk/topia-persistence-tck/src/main/java/org/nuiton/topia/tck/legacy/generator/TopiaTestCase.java =================================================================== --- trunk/topia-persistence-tck/src/main/java/org/nuiton/topia/tck/generator/TopiaTestCase.java 2012-05-09 15:48:05 UTC (rev 2453) +++ trunk/topia-persistence-tck/src/main/java/org/nuiton/topia/tck/legacy/generator/TopiaTestCase.java 2012-05-09 16:08:01 UTC (rev 2455) @@ -23,7 +23,7 @@ * #L% */ -package org.nuiton.topia.tck.generator; +package org.nuiton.topia.tck.legacy.generator; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; Modified: trunk/topia-persistence-tck/src/main/java/org/nuiton/topia/tck/legacy/persistence/EntityVisitorExportXmlTest.java =================================================================== --- trunk/topia-persistence-tck/src/main/java/org/nuiton/topia/tck/persistence/EntityVisitorExportXmlTest.java 2012-05-09 15:48:05 UTC (rev 2453) +++ trunk/topia-persistence-tck/src/main/java/org/nuiton/topia/tck/legacy/persistence/EntityVisitorExportXmlTest.java 2012-05-09 16:08:01 UTC (rev 2455) @@ -23,7 +23,7 @@ * #L% */ -package org.nuiton.topia.tck.persistence; +package org.nuiton.topia.tck.legacy.persistence; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; Modified: trunk/topia-persistence-tck/src/main/java/org/nuiton/topia/tck/legacy/persistence/ExportXMLVisitor.java =================================================================== --- trunk/topia-persistence-tck/src/main/java/org/nuiton/topia/tck/persistence/ExportXMLVisitor.java 2012-05-09 15:48:05 UTC (rev 2453) +++ trunk/topia-persistence-tck/src/main/java/org/nuiton/topia/tck/legacy/persistence/ExportXMLVisitor.java 2012-05-09 16:08:01 UTC (rev 2455) @@ -23,7 +23,7 @@ * #L% */ -package org.nuiton.topia.tck.persistence; +package org.nuiton.topia.tck.legacy.persistence; import org.apache.commons.logging.Log; Modified: trunk/topia-persistence-tck/src/main/java/org/nuiton/topia/tck/legacy/persistence/NaturalIdTest.java =================================================================== --- trunk/topia-persistence-tck/src/main/java/org/nuiton/topia/tck/persistence/NaturalIdTest.java 2012-05-09 15:48:05 UTC (rev 2453) +++ trunk/topia-persistence-tck/src/main/java/org/nuiton/topia/tck/legacy/persistence/NaturalIdTest.java 2012-05-09 16:08:01 UTC (rev 2455) @@ -23,7 +23,7 @@ * #L% */ -package org.nuiton.topia.tck.persistence; +package org.nuiton.topia.tck.legacy.persistence; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; Added: trunk/topia-persistence-tck/src/main/xmi/topia-tck-mapping.properties =================================================================== --- trunk/topia-persistence-tck/src/main/xmi/topia-tck-mapping.properties (rev 0) +++ trunk/topia-persistence-tck/src/main/xmi/topia-tck-mapping.properties 2012-05-09 16:08:01 UTC (rev 2455) @@ -0,0 +1,24 @@ +### +# #%L +# ToPIA :: Persistence +# +# $Id: topiatest.properties 2445 2012-05-09 13:48:32Z athimel $ +# $HeadURL: http://svn.nuiton.org/svn/topia/trunk/topia-persistence-tck/src/main/xmi/top... $ +# %% +# Copyright (C) 2004 - 2010 CodeLutin +# %% +# This program 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. +# +# This program 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 General Lesser Public License for more details. +# +# You should have received a copy of the GNU General Lesser Public +# License along with this program. If not, see +# <http://www.gnu.org/licenses/lgpl-3.0.html>. +# #L% +### Added: trunk/topia-persistence-tck/src/main/xmi/topia-tck-mapping.zargo =================================================================== (Binary files differ) Property changes on: trunk/topia-persistence-tck/src/main/xmi/topia-tck-mapping.zargo ___________________________________________________________________ Added: svn:mime-type + application/octet-stream