Author: tchemit Date: 2010-12-29 16:31:14 +0100 (Wed, 29 Dec 2010) New Revision: 2172 Url: http://nuiton.org/repositories/revision/topia/2172 Log: Evolution #1176: Introduce the tag-value sqlType to specify the sql-type to use in a hibernate mapping Evolution #1177: Improve Hibernate mapping generator Modified: trunk/topia-persistence/src/main/java/org/nuiton/topia/generator/EntityHibernateMappingGenerator.java trunk/topia-persistence/src/main/java/org/nuiton/topia/generator/TopiaGeneratorUtil.java trunk/topia-persistence/src/main/java/org/nuiton/topia/generator/TopiaTagValues.java Modified: trunk/topia-persistence/src/main/java/org/nuiton/topia/generator/EntityHibernateMappingGenerator.java =================================================================== --- trunk/topia-persistence/src/main/java/org/nuiton/topia/generator/EntityHibernateMappingGenerator.java 2010-12-27 12:16:41 UTC (rev 2171) +++ trunk/topia-persistence/src/main/java/org/nuiton/topia/generator/EntityHibernateMappingGenerator.java 2010-12-29 15:31:14 UTC (rev 2172) @@ -60,6 +60,8 @@ import java.util.HashMap; import java.util.List; import java.util.Map; +import java.util.TreeMap; + import org.apache.commons.lang.BooleanUtils; /** @@ -77,6 +79,12 @@ private static final Log log = LogFactory .getLog(EntityHibernateMappingGenerator.class); + private static final String HIBERNATE_ATTRIBUTE_DEFAULT = "default"; + + private static final String HIBERNATE_ATTRIBUTE_SQL_TYPE = "sql-type"; + + private static final String HIBERNATE_ATTRIBUTE_NAME = "name"; + private Map<String, String[]> columnNamesMap = new HashMap<String, String[]>(); public static final String HIBERNATE_ATTRIBUTE_LAZY = "lazy"; @@ -96,7 +104,8 @@ } @Override - public void generateFromClass(Writer output, ObjectModelClass input) throws IOException { + public void generateFromClass(Writer output, + ObjectModelClass input) throws IOException { String persistenceType = TopiaGeneratorUtil.getPersistenceType(input); if (!TopiaGeneratorUtil.hasEntityStereotype(input) && TopiaGeneratorUtil.PERSISTENCE_TYPE_HIBERNATE.equals(persistenceType)) { @@ -187,7 +196,10 @@ }*/ } - protected void generateAttributes(Writer output, ObjectModelClass clazz, List<ObjectModelAttribute> attributes, String prefix) throws IOException { + protected void generateAttributes(Writer output, + ObjectModelClass clazz, + List<ObjectModelAttribute> attributes, + String prefix) throws IOException { for (ObjectModelAttribute attr : attributes) { ObjectModelAttribute reverse = attr.getReverseAttribute(); @@ -289,7 +301,7 @@ // tag value detected of the model - //TODO TChemit 20100507 Explain What todes it do ? Dont understand the story of columnNamesMap + //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); @@ -312,7 +324,9 @@ return TopiaGeneratorUtil.getDOType(type, model); } - protected void generateHibernateProperty(Writer output, ObjectModelAttribute attr, String prefix) throws IOException { + protected void generateHibernateProperty(Writer output, + ObjectModelAttribute attr, + String prefix) throws IOException { String attrType = getType(attr); String accessField = "field"; @@ -350,38 +364,81 @@ String indexName = tableName + "_idx"; optionalAttributes += "index=\"" + indexName + "\""; } + if (TopiaGeneratorUtil.hasUniqueStereotype(attr)) { // the trim method is called on optionalAttributes after this set to suppress unusual space if no index is set on this attribute optionalAttributes += " unique=\"true\""; } optionalAttributes += generateFromTagValue(HIBERNATE_ATTRIBUTE_NOT_NULL, TopiaGeneratorUtil.getNotNullTagValue(attr)); -/*{<%=prefix%> <property name="<%=attrName%>" type="<%=attrType%>" access="<%=accessField%>" }*/ +/*{<%=prefix%> <property name="<%=attrName%>" type="<%=attrType%>" access="<%=accessField%>"}*/ optionalAttributes = optionalAttributes.trim(); String[] columnNames = columnNamesMap.get(attrType); - if (columnNames == null || columnNames.length == 0) { - optionalAttributes += generateFromTagValue(HIBERNATE_ATTRIBUTE_LENGTH, TopiaGeneratorUtil.getLengthTagValue(attr)); + + // contains all required attributes for a column node + Map<String,String> columnAttributes = new TreeMap<String, String>(); + if (StringUtils.isNotEmpty(attr.getDefaultValue())) { + //TC-20100129 with a default value we must use the column child tag + + String defaultValue = attr.getDefaultValue().trim(); + columnAttributes.put(HIBERNATE_ATTRIBUTE_DEFAULT, defaultValue); + } + String sqlType = TopiaGeneratorUtil.getSqlTypeTagValue(attr); + if (!StringUtils.isEmpty(sqlType)) { + + // an specific sql type was specified for the attribute, use it + columnAttributes.put(HIBERNATE_ATTRIBUTE_SQL_TYPE, sqlType); + } + + // add length attribute if required + String lengthTagValue = TopiaGeneratorUtil.getLengthTagValue(attr); + if (!StringUtils.isEmpty(lengthTagValue)) { + + optionalAttributes += generateFromTagValue(HIBERNATE_ATTRIBUTE_LENGTH, lengthTagValue); + } + + optionalAttributes = optionalAttributes.trim(); + if (!optionalAttributes.isEmpty()) { + optionalAttributes = " " + optionalAttributes; + } + + // to know if specific column name mapping is given + boolean noSpecifiedColumn = columnNames == null || columnNames.length == 0; + + if (noSpecifiedColumn) { + String attrColumn = TopiaGeneratorUtil.getDbName(attr); - optionalAttributes = optionalAttributes.trim(); - if (!optionalAttributes.isEmpty()) { - optionalAttributes = " " + optionalAttributes; - } - if (StringUtils.isNotEmpty(attr.getDefaultValue())) { - //TC-20100129 with a default value we must use the column child tag - String defaultValue = attr.getDefaultValue().trim(); + if (columnAttributes.isEmpty()) { + + // simple case with no column node to generate + +/*{ column="<%=attrColumn%>" node="<%=attrName%>"<%=optionalAttributes%>/> +}*/ + } else { + + // there is some attributes to write for the column node + + columnAttributes.put(HIBERNATE_ATTRIBUTE_NAME, attrColumn); + + String columnAttributesAsString =""; + for (Map.Entry<String, String> entry : + columnAttributes.entrySet()) { + String name = entry.getKey(); + String value = entry.getValue(); + columnAttributesAsString += generateFromTagValue(name, value, null); + } + columnAttributesAsString = " " + columnAttributesAsString.trim(); /*{<%=optionalAttributes%>> -<%=prefix%> <column name="<%=attrColumn%>" default="<%=defaultValue%>"/> +<%=prefix%> <column<%=columnAttributesAsString%>/> <%=prefix%> </property> }*/ - + } } else { -/*{column="<%=attrColumn%>" node="<%=attrName%>"<%=optionalAttributes%>/> -}*/ - } - } else { + + // there is a colum name mapping specified, must use it + //FIXME tchemit 2010-12-29 Really don't know how to apply columnAttributes for multi-columns... /*{<%=optionalAttributes%>> }*/ - //TC-20100129 : should we deal default value in such case ? for (String columnName : columnNames) { columnName = attrName + "_" + columnName.trim(); /*{<%=prefix%> <column name="<%=columnName%>"/> @@ -393,7 +450,9 @@ } } - protected void generateHibernateOneToOne(Writer output, ObjectModelAttribute attr, String prefix) throws IOException { + protected void generateHibernateOneToOne(Writer output, + ObjectModelAttribute attr, + String prefix) throws IOException { // boolean accessField = hasUnidirectionalRelationOnAbstractType(attr.getReverseAttribute(), model); /// *{ <one-to-one name="<%=getName(attr)%>" class="<%=getType(attr)%>"<%=(TopiaGeneratorUtil.notEmpty(attr.getTagValue(GeneratorUtil.TAG_LENGTH))?(" length=\"" + attr.getTagValue(GeneratorUtil.TAG_LENGTH) + "\""):"")%><%=((attr.isComposite() || attr.hasAssociationClass())?" cascade=\"delete\"":"")%><%=((accessField)?" access=\"field\"":"")%> node="<%=getName(attr)%>/@topiaId" embed-xml="false"/> //} */ @@ -406,7 +465,9 @@ } - protected void generateHibernateOneToMany(Writer output, ObjectModelAttribute attr, String prefix) throws IOException { + protected void generateHibernateOneToMany(Writer output, + ObjectModelAttribute attr, + String prefix) throws IOException { boolean needsIndex = JavaGeneratorUtil.hasIndexedStereotype(attr); boolean isInverse = attr.getReverseAttribute().isNavigable(); isInverse |= hasUnidirectionalRelationOnAbstractType(attr, model); @@ -464,7 +525,7 @@ String result = ""; if (StringUtils.isNotEmpty(tagValue)) { result+= attributeName + "=\"" + tagValue+"\" "; - } else if (defaultValue !=null) { + } else if (defaultValue != null) { result+= attributeName + "=\"" + defaultValue +"\" "; } // if (attr.hasTagValue(tagName) || defaultValue != null) { @@ -479,7 +540,9 @@ return result; } - protected void generateHibernateMany(Writer output, ObjectModelAttribute attr, String prefix) throws IOException { + protected void generateHibernateMany(Writer output, + ObjectModelAttribute attr, + String prefix) throws IOException { boolean needsIndex = JavaGeneratorUtil.hasIndexedStereotype(attr); String attrName = getName(attr); String attrType = getType(attr); @@ -499,11 +562,16 @@ }*/ } - protected void generateHibernateManyToOne(Writer output, ObjectModelAttribute attr, String prefix) throws IOException { + protected void generateHibernateManyToOne(Writer output, + ObjectModelAttribute attr, + String prefix) throws IOException { generateHibernateManyToOne(output, attr, false, prefix); } - protected void generateHibernateManyToOne(Writer output, ObjectModelAttribute attr, boolean isUnique, String prefix) throws IOException { + protected void generateHibernateManyToOne(Writer output, + ObjectModelAttribute attr, + boolean isUnique, + String prefix) throws IOException { String attrName = getName(attr); String attrType = getType(attr); String attrColumn = TopiaGeneratorUtil.getDbName(attr); @@ -531,7 +599,9 @@ }*/ } - protected void generateHibernateManyToMany(Writer output, ObjectModelAttribute attr, String prefix) throws IOException { + protected void generateHibernateManyToMany(Writer output, + ObjectModelAttribute attr, + String prefix) throws IOException { // On ne met le inverse="true" uniquement pour un seul coté de la relation. // Dans le cas contraire, les modifications dans la relation ne seront // pas sauvegardées. Ceci n'est vrai que si les deux coté sont navigable 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-12-27 12:16:41 UTC (rev 2171) +++ trunk/topia-persistence/src/main/java/org/nuiton/topia/generator/TopiaGeneratorUtil.java 2010-12-29 15:31:14 UTC (rev 2172) @@ -1576,6 +1576,21 @@ } /** + * Obtain the value of the {@link TopiaTagValues#TAG_SQL_TYPE} + * tag value on the given attribute. + * <p/> + * + * @param attribute attribute to seek + * @return the none empty value of the found tag value or {@code null} if not found nor empty. + * @see TopiaTagValues#TAG_TYPE + * @since 2.5 + */ + public static String getSqlTypeTagValue(ObjectModelAttribute attribute) { + String value = findTagValue(TopiaTagValues.TAG_SQL_TYPE, attribute, null); + return value; + } + + /** * Obtain the value of the {@link TopiaTagValues#TAG_EXCEPTION_CLASS} * tag value on the given interface. * <p/> Modified: trunk/topia-persistence/src/main/java/org/nuiton/topia/generator/TopiaTagValues.java =================================================================== --- trunk/topia-persistence/src/main/java/org/nuiton/topia/generator/TopiaTagValues.java 2010-12-27 12:16:41 UTC (rev 2171) +++ trunk/topia-persistence/src/main/java/org/nuiton/topia/generator/TopiaTagValues.java 2010-12-29 15:31:14 UTC (rev 2172) @@ -291,6 +291,14 @@ String TAG_TYPE = "type"; /** + * Tag pour spécifier le type sql d'une propriété dans le mapping hibernate. + * + * @see TopiaGeneratorUtil#getSqlTypeTagValue(ObjectModelAttribute) + * @since 2.5 + */ + @TagValueDefinition(target = {ObjectModelAttribute.class}) + String TAG_SQL_TYPE = "sqlType"; + /** * To use the legacy DAO generation. * * @see TopiaGeneratorUtil#getTypeTagValue(ObjectModelAttribute)