package org.hibernate.tool.hbm2x.pojo; import java.io.Serializable; import java.util.ArrayList; import java.util.Enumeration; import java.util.HashSet; import java.util.Iterator; import java.util.List; import java.util.Properties; import java.util.Set; import java.util.StringTokenizer; import org.hibernate.boot.Metadata; import org.hibernate.id.PersistentIdentifierGenerator; import org.hibernate.id.enhanced.TableGenerator; import org.hibernate.internal.util.StringHelper; import org.hibernate.internal.util.collections.JoinedIterator; import org.hibernate.mapping.Collection; import org.hibernate.mapping.Column; import org.hibernate.mapping.Component; import org.hibernate.mapping.Formula; import org.hibernate.mapping.KeyValue; import org.hibernate.mapping.ManyToOne; import org.hibernate.mapping.OneToMany; import org.hibernate.mapping.OneToOne; import org.hibernate.mapping.PersistentClass; import org.hibernate.mapping.Property; import org.hibernate.mapping.RootClass; import org.hibernate.mapping.Selectable; import org.hibernate.mapping.SimpleValue; import org.hibernate.mapping.Subclass; import org.hibernate.mapping.Table; import org.hibernate.mapping.ToOne; import org.hibernate.mapping.UniqueKey; import org.hibernate.mapping.Value; import org.hibernate.tool.hbm2x.Cfg2JavaTool; import org.hibernate.type.ForeignKeyDirection; public class EntityPOJOClass extends BasicPOJOClass { private PersistentClass clazz; public EntityPOJOClass(PersistentClass clazz, Cfg2JavaTool cfg) { super(clazz, cfg); this.clazz = clazz; init(); } protected String getMappedClassName() { return clazz.getClassName(); } /** * @return whatever the class (or interface) extends (null if it does not extend anything) */ public String getExtends() { String extendz = ""; if ( isInterface() ) { if ( clazz.getSuperclass() != null ) { extendz = clazz.getSuperclass().getClassName(); } if ( clazz.getMetaAttribute( EXTENDS ) != null ) { if ( !"".equals( extendz ) ) { extendz += ","; } extendz += getMetaAsString( EXTENDS, "," ); } } else if ( clazz.getSuperclass() != null ) { if ( c2j.getPOJOClass(clazz.getSuperclass()).isInterface() ) { // class cannot extend it's superclass because the superclass is marked as an interface } else { extendz = clazz.getSuperclass().getClassName(); } } else if ( clazz.getMetaAttribute( EXTENDS ) != null ) { extendz = getMetaAsString( EXTENDS, "," ); } return "".equals( extendz ) ? null : extendz; } @SuppressWarnings("unchecked") public String getImplements() { List<String> interfaces = new ArrayList<String>(); // implement proxy, but NOT if the proxy is the class it self! if ( clazz.getProxyInterfaceName() != null && ( !clazz.getProxyInterfaceName().equals( clazz.getClassName() ) ) ) { interfaces.add( clazz.getProxyInterfaceName() ); } if ( !isInterface() ) { if ( clazz.getSuperclass() != null && c2j.getPOJOClass(clazz.getSuperclass()).isInterface() ) { interfaces.add( clazz.getSuperclass().getClassName() ); } if ( clazz.getMetaAttribute( IMPLEMENTS ) != null ) { interfaces.addAll( clazz.getMetaAttribute( IMPLEMENTS ).getValues() ); } interfaces.add( Serializable.class.getName() ); // TODO: is this "nice" ? shouldn't it be a user choice ? } else { // interfaces can't implement suff } if ( interfaces.size() > 0 ) { StringBuffer sbuf = new StringBuffer(); for ( Iterator<String> iter = interfaces.iterator(); iter.hasNext() ; ) { //sbuf.append(JavaTool.shortenType(iter.next().toString(), pc.getImports() ) ); sbuf.append( iter.next() ); if ( iter.hasNext() ) sbuf.append( "," ); } return sbuf.toString(); } else { return null; } } public Iterator<Property> getAllPropertiesIterator() { return getAllPropertiesIterator(clazz); } @SuppressWarnings("unchecked") public Iterator<Property> getAllPropertiesIterator(PersistentClass pc) { List<Property> properties = new ArrayList<Property>(); List<Iterator<Property>> iterators = new ArrayList<Iterator<Property>>(); if ( pc.getSuperclass() == null ) { // only include identifier for the root class. if ( pc.hasIdentifierProperty() ) { properties.add( pc.getIdentifierProperty() ); } else if ( pc.hasEmbeddedIdentifier() ) { Component embeddedComponent = (Component) pc.getIdentifier(); iterators.add( embeddedComponent.getPropertyIterator() ); } /*if(clazz.isVersioned() ) { // version is already in property set properties.add(clazz.getVersion() ); }*/ } // iterators.add( pc.getPropertyIterator() ); // Need to skip <properties> element which are defined via "embedded" components // Best if we could return an intelligent iterator, but for now we just iterate explicitly. Iterator<Property> pit = pc.getPropertyIterator(); while(pit.hasNext()) { Property element = (Property) pit.next(); if ( element.getValue() instanceof Component && element.getPropertyAccessorName().equals( "embedded" )) { Component component = (Component) element.getValue(); // need to "explode" property to get proper sequence in java code. Iterator<Property> embeddedProperty = component.getPropertyIterator(); while(embeddedProperty.hasNext()) { properties.add(embeddedProperty.next()); } } else { properties.add(element); } } iterators.add( properties.iterator() ); Iterator<Property>[] it = (Iterator<Property>[]) iterators.toArray( new Iterator[iterators.size()] ); return new SkipBackRefPropertyIterator( new JoinedIterator<Property>( it ) ); } public boolean isComponent() { return false; } public boolean hasIdentifierProperty() { return clazz.hasIdentifierProperty() && clazz instanceof RootClass; } public Property getIdentifierProperty() { return clazz.getIdentifierProperty(); } public String generateAnnTableUniqueConstraint() { if ( ! ( clazz instanceof Subclass ) ) { Table table = clazz.getTable(); return generateAnnTableUniqueConstraint( table ); } return ""; } protected String generateAnnTableUniqueConstraint(Table table) { Iterator<UniqueKey> uniqueKeys = table.getUniqueKeyIterator(); List<String> cons = new ArrayList<String>(); while ( uniqueKeys.hasNext() ) { UniqueKey key = (UniqueKey) uniqueKeys.next(); if (table.hasPrimaryKey() && table.getPrimaryKey().getColumns().equals(key.getColumns())) { continue; } AnnotationBuilder constraint = AnnotationBuilder.createAnnotation( importType("javax.persistence.UniqueConstraint") ); constraint.addQuotedAttributes( "columnNames", new IteratorTransformer<Column>(key.getColumnIterator()) { public String transform(Column column) { return column.getName(); } }); cons.add( constraint.getResult() ); } AnnotationBuilder builder = AnnotationBuilder.createAnnotation( "dummyAnnotation" ); builder.addAttributes( "dummyAttribute", cons.iterator() ); String attributeAsString = builder.getAttributeAsString( "dummyAttribute" ); return attributeAsString==null?"":attributeAsString; } public String generateAnnIdGenerator() { KeyValue identifier = clazz.getIdentifier(); String strategy = null; Properties properties = null; StringBuffer wholeString = new StringBuffer( " " ); if ( identifier instanceof Component ) { wholeString.append( AnnotationBuilder.createAnnotation( importType("javax.persistence.EmbeddedId") ).getResult()); } else if ( identifier instanceof SimpleValue ) { SimpleValue simpleValue = (SimpleValue) identifier; strategy = simpleValue.getIdentifierGeneratorStrategy(); properties = c2j.getFilteredIdentifierGeneratorProperties(simpleValue); StringBuffer idResult = new StringBuffer(); AnnotationBuilder builder = AnnotationBuilder.createAnnotation( importType("javax.persistence.Id") ); idResult.append(builder.getResult()); idResult.append(" "); boolean isGenericGenerator = false; //TODO: how to handle generic now?? if ( !"assigned".equals( strategy ) ) { if ( !"native".equals( strategy ) ) { if ( "identity".equals( strategy ) ) { builder.resetAnnotation( importType("javax.persistence.GeneratedValue") ); builder.addAttribute( "strategy", staticImport("javax.persistence.GenerationType", "IDENTITY" ) ); idResult.append(builder.getResult()); } else if ( "sequence".equals( strategy ) ) { builder.resetAnnotation( importType("javax.persistence.GeneratedValue") ) .addAttribute( "strategy", staticImport("javax.persistence.GenerationType", "SEQUENCE" ) ) .addQuotedAttribute( "generator", clazz.getClassName()+"IdGenerator" ); idResult.append(builder.getResult()); builder.resetAnnotation( importType("javax.persistence.SequenceGenerator") ) .addQuotedAttribute( "name", clazz.getClassName()+"IdGenerator" ) .addQuotedAttribute( "sequenceName", properties.getProperty( org.hibernate.id.enhanced.SequenceStyleGenerator.SEQUENCE_PARAM, null ) ); // TODO HA does not support initialValue and allocationSize wholeString.append( builder.getResult() ); } else if ( TableGenerator.class.getName().equals( strategy ) ) { builder.resetAnnotation( importType("javax.persistence.GeneratedValue") ) .addAttribute( "strategy", staticImport("javax.persistence.GenerationType", "TABLE" ) ) .addQuotedAttribute( "generator", "generator" ); idResult.append(builder.getResult()); buildAnnTableGenerator( wholeString, properties ); } else { isGenericGenerator = true; builder.resetAnnotation( importType("javax.persistence.GeneratedValue") ); builder.addQuotedAttribute( "generator", "generator" ); idResult.append(builder.getResult()); } } else { builder.resetAnnotation( importType("javax.persistence.GeneratedValue") ); idResult.append(builder.getResult()); } } if ( isGenericGenerator ) { builder.resetAnnotation( importType("org.hibernate.annotations.GenericGenerator") ) .addQuotedAttribute( "name", "generator" ) .addQuotedAttribute( "strategy", strategy); List<AnnotationBuilder> params = new ArrayList<AnnotationBuilder>(); //wholeString.append( "parameters = { " ); if ( properties != null ) { Enumeration<?> propNames = properties.propertyNames(); while ( propNames.hasMoreElements() ) { String propertyName = (String) propNames.nextElement(); AnnotationBuilder parameter = AnnotationBuilder.createAnnotation( importType("org.hibernate.annotations.Parameter") ) .addQuotedAttribute( "name", propertyName ) .addQuotedAttribute( "value", properties.getProperty( propertyName ) ); params.add( parameter ); } } builder.addAttributes( "parameters", params.iterator() ); wholeString.append(builder.getResult()); } wholeString.append( idResult ); } return wholeString.toString(); } private void buildAnnTableGenerator(StringBuffer wholeString, Properties properties) { AnnotationBuilder builder = AnnotationBuilder.createAnnotation( importType("javax.persistence.TableGenerator") ); builder.addQuotedAttribute( "name", "generator" ); builder.addQuotedAttribute( "table", properties.getProperty( "generatorTableName", "hibernate_sequences" ) ); if ( ! isPropertyDefault( PersistentIdentifierGenerator.CATALOG, properties ) ) { builder.addQuotedAttribute( "catalog", properties.getProperty( PersistentIdentifierGenerator.CATALOG, "") ); } if ( ! isPropertyDefault( PersistentIdentifierGenerator.SCHEMA, properties ) ) { builder.addQuotedAttribute( "schema", properties.getProperty( PersistentIdentifierGenerator.SCHEMA, "") ); } if (! isPropertyDefault( TableGenerator.SEGMENT_VALUE_PARAM, properties ) ) { builder.addQuotedAttribute( "pkColumnValue", properties.getProperty( TableGenerator.SEGMENT_VALUE_PARAM, "") ); } if ( ! isPropertyDefault( TableGenerator.INCREMENT_PARAM, properties, "50" ) ) { builder.addAttribute( "allocationSize", properties.getProperty( TableGenerator.INCREMENT_PARAM, "50" ) ); } if (! isPropertyDefault( TableGenerator.SEGMENT_COLUMN_PARAM, properties ) ) { builder.addQuotedAttribute( "pkColumnName", properties.getProperty( TableGenerator.SEGMENT_COLUMN_PARAM, "") ); } if (! isPropertyDefault( TableGenerator.VALUE_COLUMN_PARAM, properties ) ) { builder.addQuotedAttribute( "valueColumnName", properties.getProperty( TableGenerator.VALUE_COLUMN_PARAM, "") ); } wholeString.append( builder.getResult() + "\n " ); } private boolean isPropertyDefault(String property, Properties properties) { return StringHelper.isEmpty( properties.getProperty( property ) ); } private boolean isPropertyDefault(String property, Properties properties, String defaultValue) { String propertyValue = properties.getProperty( property ); return propertyValue != null && propertyValue.equals( defaultValue ); } @SuppressWarnings("unchecked") public String generateJoinColumnsAnnotation(Property property, Metadata md) { boolean insertable = property.isInsertable(); boolean updatable = property.isUpdateable(); Value value = property.getValue(); int span; Iterator<Selectable> columnIterator; Iterator<Selectable> referencedColumnsIterator = null; if (value != null && value instanceof Collection) { Collection collection = (Collection) value; span = collection.getKey().getColumnSpan(); columnIterator = collection.getKey().getColumnIterator(); } else { span = property.getColumnSpan(); columnIterator = property.getColumnIterator(); } if(property.getValue() instanceof ToOne) { String referencedEntityName = ((ToOne)property.getValue()).getReferencedEntityName(); PersistentClass target = md.getEntityBinding(referencedEntityName); if(target!=null) { referencedColumnsIterator = target.getKey().getColumnIterator(); } } StringBuffer annotations = new StringBuffer( " " ); if ( span == 1 ) { Selectable selectable = columnIterator.next(); buildJoinColumnAnnotation( selectable, null, annotations, insertable, updatable ); } else { Iterator<Selectable> columns = columnIterator; annotations.append("@").append( importType("javax.persistence.JoinColumns") ).append("( { " ); buildArrayOfJoinColumnAnnotation( columns, referencedColumnsIterator, annotations, insertable, updatable ); annotations.append( " } )" ); } return annotations.toString(); } private void buildArrayOfJoinColumnAnnotation( Iterator<Selectable> columns, Iterator<Selectable> referencedColumnsIterator, StringBuffer annotations, boolean insertable, boolean updatable ) { while ( columns.hasNext() ) { Selectable selectable = columns.next(); Selectable referencedColumn = null; if(referencedColumnsIterator!=null) { referencedColumn = referencedColumnsIterator.next(); } if ( selectable.isFormula() ) { //TODO formula in multicolumns not supported by annotations //annotations.append("/* TODO formula in multicolumns not supported by annotations */"); } else { annotations.append( "\n " ); buildJoinColumnAnnotation( selectable, referencedColumn, annotations, insertable, updatable ); annotations.append( ", " ); } } annotations.setLength( annotations.length() - 2 ); } private void buildJoinColumnAnnotation( Selectable selectable, Selectable referencedColumn, StringBuffer annotations, boolean insertable, boolean updatable ) { if ( selectable.isFormula() ) { //TODO not supported by HA } else { Column column = (Column) selectable; annotations.append("@").append( importType("javax.persistence.JoinColumn") ) .append("(name=\"" ).append( column.getName() ).append( "\"" ); //TODO handle referenced column name, this is a hard one if(referencedColumn!=null) { annotations.append(", referencedColumnName=\"" ).append( referencedColumn.getText() ).append( "\"" ); } appendCommonColumnInfo(annotations, column, insertable, updatable); //TODO support secondary table annotations.append( ")" ); } } public String[] getCascadeTypes(Property property) { StringTokenizer st = new StringTokenizer( property.getCascade(), ", ", false ); List<String> types = new ArrayList<String>(); while ( st.hasMoreElements() ) { String element = ( (String) st.nextElement() ).toLowerCase(); if ( "persist".equals( element ) ) { types.add(importType( "javax.persistence.CascadeType" ) + ".PERSIST"); } else if ( "merge".equals( element ) ) { types.add(importType( "javax.persistence.CascadeType") + ".MERGE"); } else if ( "delete".equals( element ) ) { types.add(importType( "javax.persistence.CascadeType") + ".REMOVE"); } else if ( "refresh".equals( element ) ) { types.add(importType( "javax.persistence.CascadeType") + ".REFRESH"); } else if ( "all".equals( element ) ) { types.add(importType( "javax.persistence.CascadeType") + ".ALL"); } } return (String[]) types.toArray( new String[types.size()] ); } public String generateManyToOneAnnotation(Property property) { StringBuffer buffer = new StringBuffer(AnnotationBuilder.createAnnotation( importType("javax.persistence.ManyToOne") ) .addAttribute( "cascade", getCascadeTypes(property)) .addAttribute( "fetch", getFetchType(property)) .getResult()); buffer.append(getHibernateCascadeTypeAnnotation(property)); return buffer.toString(); } public boolean isSharedPkBasedOneToOne(OneToOne oneToOne){ Iterator<Selectable> joinColumnsIt = oneToOne.getColumnIterator(); Set<Selectable> joinColumns = new HashSet<Selectable>(); while ( joinColumnsIt.hasNext() ) { joinColumns.add( joinColumnsIt.next() ); } if ( joinColumns.size() == 0 ) return false; Iterator<?> idColumnsIt = getIdentifierProperty().getColumnIterator(); while ( idColumnsIt.hasNext() ) { if (!joinColumns.contains(idColumnsIt.next()) ) return false; } return true; } public String generateOneToOneAnnotation(Property property, Metadata md) { OneToOne oneToOne = (OneToOne)property.getValue(); boolean pkIsAlsoFk = isSharedPkBasedOneToOne(oneToOne); AnnotationBuilder ab = AnnotationBuilder.createAnnotation( importType("javax.persistence.OneToOne") ) .addAttribute( "cascade", getCascadeTypes(property)) .addAttribute( "fetch", getFetchType(property)); if ( oneToOne.getForeignKeyType().equals(ForeignKeyDirection.TO_PARENT) ){ ab.addQuotedAttribute("mappedBy", getOneToOneMappedBy(md, oneToOne)); } StringBuffer buffer = new StringBuffer(ab.getResult()); buffer.append(getHibernateCascadeTypeAnnotation(property)); if ( pkIsAlsoFk && oneToOne.getForeignKeyType().equals(ForeignKeyDirection.FROM_PARENT) ){ AnnotationBuilder ab1 = AnnotationBuilder.createAnnotation( importType("javax.persistence.PrimaryKeyJoinColumn") ); buffer.append(ab1.getResult()); } return buffer.toString(); } public String getHibernateCascadeTypeAnnotation(Property property) { StringTokenizer st = new StringTokenizer( property.getCascade(), ", ", false ); String cascadeType = null; StringBuffer cascade = new StringBuffer(); while ( st.hasMoreElements() ) { String element = ( (String) st.nextElement() ).toLowerCase(); if ( "all-delete-orphan".equals( element ) ) { if (cascadeType == null) cascadeType = importType( "org.hibernate.annotations.CascadeType"); cascade.append( cascadeType ).append(".ALL").append(", ") .append( cascadeType ).append(".DELETE_ORPHAN").append(", "); } else if ( "delete-orphan".equals( element ) ) { if (cascadeType == null) cascadeType = importType( "org.hibernate.annotations.CascadeType"); cascade.append( cascadeType ).append(".DELETE_ORPHAN").append(", "); } else if ( "save-update".equals( element ) ) { if (cascadeType == null) cascadeType = importType( "org.hibernate.annotations.CascadeType"); cascade.append( cascadeType ).append(".SAVE_UPDATE").append(", "); } else if ( "replicate".equals( element ) ) { if (cascadeType == null) cascadeType = importType( "org.hibernate.annotations.CascadeType"); cascade.append( cascadeType ).append(".REPLICATE").append(", "); } else if ( "lock".equals( element ) ) { if (cascadeType == null) cascadeType = importType( "org.hibernate.annotations.CascadeType"); cascade.append( cascadeType ).append(".LOCK").append(", "); } else if ( "evict".equals( element ) ) { if (cascadeType == null) cascadeType = importType( "org.hibernate.annotations.CascadeType"); cascade.append( cascadeType ).append(".EVICT").append(", "); } } if ( cascade.length() >= 2 ) { String hibernateCascade = importType("org.hibernate.annotations.Cascade"); cascade.insert(0, "@" + hibernateCascade + "( {"); cascade.setLength( cascade.length() - 2 ); cascade.append("} )"); } return cascade.toString(); } public String getFetchType(Property property) { Value value = property.getValue(); String fetchType = importType( "javax.persistence.FetchType"); boolean lazy = false; if ( value instanceof ToOne ) { lazy = ( (ToOne) value ).isLazy(); } else if ( value instanceof Collection ) { lazy = ( (Collection) value ).isLazy(); } else { //we're not collection neither *toone so we are looking for property fetching lazy = property.isLazy(); } if ( lazy ) { return fetchType + "." + "LAZY"; } else { return fetchType + "." + "EAGER"; } } public Object getDecoratedObject() { return clazz; } public String generateCollectionAnnotation(Property property, Metadata md) { StringBuffer annotation = new StringBuffer(); Value value = property.getValue(); if ( value != null && value instanceof Collection) { Collection collection = (Collection) value; if ( collection.isOneToMany() ) { String mappedBy = null; AnnotationBuilder ab = AnnotationBuilder.createAnnotation( importType( "javax.persistence.OneToMany") ); ab.addAttribute( "cascade", getCascadeTypes( property ) ); ab.addAttribute( "fetch", getFetchType (property) ); if ( collection.isInverse() ) { mappedBy = getOneToManyMappedBy( md, collection ); ab.addQuotedAttribute( "mappedBy", mappedBy ); } annotation.append( ab.getResult() ); if (mappedBy == null) annotation.append("\n").append( generateJoinColumnsAnnotation(property, md) ); } else { //TODO do the @OneToMany @JoinTable //TODO composite element String mappedBy = null; AnnotationBuilder ab = AnnotationBuilder.createAnnotation( importType( "javax.persistence.ManyToMany") ); ab.addAttribute( "cascade", getCascadeTypes( property ) ); ab.addAttribute( "fetch", getFetchType (property) ); if ( collection.isInverse() ) { mappedBy = getManyToManyMappedBy( md, collection ); ab.addQuotedAttribute( "mappedBy", mappedBy ); } annotation.append(ab.getResult()); if (mappedBy == null) { annotation.append("\n @"); annotation.append( importType( "javax.persistence.JoinTable") ).append( "(name=\"" ); Table table = collection.getCollectionTable(); annotation.append( table.getName() ); annotation.append( "\"" ); if ( StringHelper.isNotEmpty( table.getSchema() ) ) { annotation.append(", schema=\"").append( table.getSchema() ).append("\""); } if ( StringHelper.isNotEmpty( table.getCatalog() ) ) { annotation.append(", catalog=\"").append( table.getCatalog() ).append("\""); } String uniqueConstraint = generateAnnTableUniqueConstraint(table); if ( uniqueConstraint.length() > 0 ) { annotation.append(", uniqueConstraints=").append(uniqueConstraint); } annotation.append( ", joinColumns = { "); buildArrayOfJoinColumnAnnotation( collection.getKey().getColumnIterator(), null, annotation, property.isInsertable(), property.isUpdateable() ); annotation.append( " }"); annotation.append( ", inverseJoinColumns = { "); buildArrayOfJoinColumnAnnotation( collection.getElement().getColumnIterator(), null, annotation, property.isInsertable(), property.isUpdateable() ); annotation.append( " }"); annotation.append(")"); } } String hibernateCascade = getHibernateCascadeTypeAnnotation( property ); if (hibernateCascade.length() > 0) annotation.append("\n ").append(hibernateCascade); } return annotation.toString(); } private String getManyToManyMappedBy(Metadata md, Collection collection) { String mappedBy; Iterator<Selectable> joinColumnsIt = collection.getKey().getColumnIterator(); Set<Selectable> joinColumns = new HashSet<Selectable>(); while ( joinColumnsIt.hasNext() ) { joinColumns.add( joinColumnsIt.next() ); } ManyToOne manyToOne = (ManyToOne) collection.getElement(); PersistentClass pc = md.getEntityBinding(manyToOne.getReferencedEntityName()); Iterator<?> properties = pc.getPropertyClosureIterator(); //TODO we should check the table too boolean isOtherSide = false; mappedBy = "unresolved"; while ( ! isOtherSide && properties.hasNext() ) { Property collectionProperty = (Property) properties.next(); Value collectionValue = collectionProperty.getValue(); if ( collectionValue != null && collectionValue instanceof Collection ) { Collection realCollectionValue = (Collection) collectionValue; if ( ! realCollectionValue.isOneToMany() ) { if ( joinColumns.size() == realCollectionValue.getElement().getColumnSpan() ) { isOtherSide = true; Iterator<?> it = realCollectionValue.getElement().getColumnIterator(); while ( it.hasNext() ) { Object column = it.next(); if (! joinColumns.contains( column ) ) { isOtherSide = false; break; } } if (isOtherSide) { mappedBy = collectionProperty.getName(); } } } } } return mappedBy; } private String getOneToManyMappedBy(Metadata md, Collection collection) { String mappedBy; Iterator<Selectable> joinColumnsIt = collection.getKey().getColumnIterator(); Set<Selectable> joinColumns = new HashSet<Selectable>(); while ( joinColumnsIt.hasNext() ) { joinColumns.add( joinColumnsIt.next() ); } OneToMany oneToMany = (OneToMany) collection.getElement(); PersistentClass pc = md.getEntityBinding(oneToMany.getReferencedEntityName()); Iterator<?> properties = pc.getPropertyClosureIterator(); //TODO we should check the table too boolean isOtherSide = false; mappedBy = "unresolved"; while ( ! isOtherSide && properties.hasNext() ) { Property manyProperty = (Property) properties.next(); Value manyValue = manyProperty.getValue(); if ( manyValue != null && manyValue instanceof ManyToOne ) { if ( joinColumns.size() == manyValue.getColumnSpan() ) { isOtherSide = true; Iterator<?> it = manyValue.getColumnIterator(); while ( it.hasNext() ) { Object column = it.next(); if (! joinColumns.contains( column ) ) { isOtherSide = false; break; } } if (isOtherSide) { mappedBy = manyProperty.getName(); } } } } return mappedBy; } private String getOneToOneMappedBy(Metadata md, OneToOne oneToOne) { String mappedBy; Iterator<Selectable> joinColumnsIt = oneToOne.getColumnIterator(); Set<Selectable> joinColumns = new HashSet<Selectable>(); while ( joinColumnsIt.hasNext() ) { joinColumns.add( joinColumnsIt.next() ); } PersistentClass pc = md.getEntityBinding(oneToOne.getReferencedEntityName()); String referencedPropertyName = oneToOne.getReferencedPropertyName(); if ( referencedPropertyName != null ) return referencedPropertyName; Iterator<?> properties = pc.getPropertyClosureIterator(); //TODO we should check the table too boolean isOtherSide = false; mappedBy = "unresolved"; while ( ! isOtherSide && properties.hasNext() ) { Property oneProperty = (Property) properties.next(); Value manyValue = oneProperty.getValue(); if ( manyValue != null && ( manyValue instanceof OneToOne || manyValue instanceof ManyToOne ) ) { if ( joinColumns.size() == manyValue.getColumnSpan() ) { isOtherSide = true; Iterator<?> it = manyValue.getColumnIterator(); while ( it.hasNext() ) { Object column = it.next(); if (! joinColumns.contains( column ) ) { isOtherSide = false; break; } } if (isOtherSide) { mappedBy = oneProperty.getName(); } } } } return mappedBy; } public boolean isSubclass() { return clazz.getSuperclass()!=null; } public List<Property> getPropertyClosureForFullConstructor() { return getPropertyClosureForFullConstructor(clazz); } protected List<Property> getPropertyClosureForFullConstructor(PersistentClass pc) { List<Property> l = new ArrayList<Property>(getPropertyClosureForSuperclassFullConstructor( pc )); l.addAll(getPropertiesForFullConstructor( pc )); return l; } public List<Property> getPropertiesForFullConstructor() { return getPropertiesForFullConstructor(clazz); } protected List<Property> getPropertiesForFullConstructor(PersistentClass pc) { List<Property> result = new ArrayList<Property>(); for ( Iterator<Property> myFields = getAllPropertiesIterator(pc); myFields.hasNext() ; ) { Property field = (Property) myFields.next(); // TODO: if(!field.isGenerated() ) ) { if(field.equals(pc.getIdentifierProperty()) && !isAssignedIdentifier(pc, field)) { continue; // dont add non assigned identifiers } else if(field.equals(pc.getVersion())) { continue; // version prop } else if(field.isBackRef()) { continue; } else if(isFormula(field)) { continue; } else { result.add( field ); } } return result; } private boolean isFormula(Property field) { Value value = field.getValue(); boolean foundFormula = false; if(value!=null && value.getColumnSpan()>0) { Iterator<Selectable> columnIterator = value.getColumnIterator(); while ( columnIterator.hasNext() ) { Selectable element = columnIterator.next(); if(!(element instanceof Formula)) { return false; } else { foundFormula = true; } } } else { return false; } return foundFormula; } public List<Property> getPropertyClosureForSuperclassFullConstructor() { return getPropertyClosureForSuperclassFullConstructor(clazz); } public List<Property> getPropertyClosureForSuperclassFullConstructor(PersistentClass pc) { List<Property> result = new ArrayList<Property>(); if ( pc.getSuperclass() != null ) { // The correct sequence is vital here, as the subclass should be // able to invoke the fullconstructor based on the sequence returned // by this method! result.addAll( getPropertyClosureForSuperclassFullConstructor( pc.getSuperclass() ) ); result.addAll( getPropertiesForFullConstructor( pc.getSuperclass() ) ); } return result; } public List<Property> getPropertyClosureForMinimalConstructor() { return getPropertyClosureForMinimalConstructor(clazz); } protected List<Property> getPropertyClosureForMinimalConstructor(PersistentClass pc) { List<Property> l = new ArrayList<Property>(getPropertyClosureForSuperclassMinConstructor( pc )); l.addAll(getPropertiesForMinimalConstructor( pc )); return l; } public List<Property> getPropertiesForMinimalConstructor() { return getPropertiesForMinimalConstructor(clazz); } protected List<Property> getPropertiesForMinimalConstructor(PersistentClass pc) { List<Property> result = new ArrayList<Property>(); for ( Iterator<Property> myFields = getAllPropertiesIterator(pc); myFields.hasNext() ; ) { Property property = (Property) myFields.next(); if(property.equals(pc.getIdentifierProperty())) { if(isAssignedIdentifier(pc, property)) { result.add(property); } else { continue; } } else if (property.equals(pc.getVersion())) { continue; // the version property should not be in the result. } else if( isRequiredInConstructor(property) ) { result.add(property); } } return result; } protected boolean isAssignedIdentifier(PersistentClass pc, Property property) { if(property.equals(pc.getIdentifierProperty())) { if(property.getValue().isSimpleValue()) { SimpleValue sv = (SimpleValue) property.getValue(); if("assigned".equals(sv.getIdentifierGeneratorStrategy())) { return true; } } } return false; } public List<Property> getPropertyClosureForSuperclassMinimalConstructor() { return getPropertyClosureForSuperclassMinConstructor(clazz); } protected List<Property> getPropertyClosureForSuperclassMinConstructor(PersistentClass pc) { List<Property> result = new ArrayList<Property>(); if ( pc.getSuperclass() != null ) { // The correct sequence is vital here, as the subclass should be // able to invoke the fullconstructor based on the sequence returned // by this method! result.addAll( getPropertyClosureForSuperclassMinConstructor( pc.getSuperclass() ) ); result.addAll( getPropertiesForMinimalConstructor( pc.getSuperclass() ) ); } return result; } public POJOClass getSuperClass(){ if (!isSubclass()) return null; return new EntityPOJOClass(clazz.getSuperclass(),c2j); } public String toString() { return "Entity: " + (clazz==null?"<none>":clazz.getEntityName()); } public boolean hasVersionProperty() { return clazz.isVersioned() && clazz instanceof RootClass; } /* * @see org.hibernate.tool.hbm2x.pojo.POJOClass#getVersionProperty() */ public Property getVersionProperty() { return clazz.getVersion(); } }