diff --git a/hibernate-core/src/main/java/org/hibernate/metamodel/binding/AbstractAttributeBinding.java b/hibernate-core/src/main/java/org/hibernate/metamodel/binding/AbstractAttributeBinding.java index 12e549658b..518ee2035d 100644 --- a/hibernate-core/src/main/java/org/hibernate/metamodel/binding/AbstractAttributeBinding.java +++ b/hibernate-core/src/main/java/org/hibernate/metamodel/binding/AbstractAttributeBinding.java @@ -28,7 +28,8 @@ import java.util.Collections; import java.util.List; import java.util.Map; -import org.hibernate.FetchMode; +import org.dom4j.Element; + import org.hibernate.mapping.MetaAttribute; import org.hibernate.metamodel.domain.Attribute; import org.hibernate.metamodel.relational.Column; @@ -37,6 +38,8 @@ import org.hibernate.metamodel.relational.SimpleValue; import org.hibernate.metamodel.relational.TableSpecification; import org.hibernate.metamodel.relational.Tuple; import org.hibernate.metamodel.relational.Value; +import org.hibernate.metamodel.source.hbm.HbmHelper; +import org.hibernate.metamodel.source.util.DomHelper; /** * TODO : javadoc @@ -50,8 +53,14 @@ public abstract class AbstractAttributeBinding implements AttributeBinding { private Attribute attribute; private Value value; - private FetchMode fetchMode; + private boolean isLazy; + private String propertyAccessorName; private boolean alternateUniqueKey; + private String cascade; + private boolean optimisticLockable; + + // DOM4J specific... + private String nodeName; private Map metaAttributes; @@ -59,6 +68,24 @@ public abstract class AbstractAttributeBinding implements AttributeBinding { this.entityBinding = entityBinding; } + public void fromHbmXml(MappingDefaults defaults, Element element, Attribute attribute) { + this.attribute = attribute; + hibernateTypeDescriptor.setTypeName( DomHelper.extractAttributeValue( element, "type", null ) ); + + metaAttributes = HbmHelper.extractMetas( element, entityBinding.getMetaAttributes() ); + nodeName = DomHelper.extractAttributeValue( element, "node", attribute.getName() ); + isLazy = DomHelper.extractBooleanAttributeValue( element, "lazy", isLazyDefault( defaults ) ); + propertyAccessorName = ( + DomHelper.extractAttributeValue( + element, + "access", + isEmbedded() ? "embedded" : defaults.getDefaultAccess() + ) + ); + cascade = DomHelper.extractAttributeValue( element, "cascade", defaults.getDefaultCascade() ); + optimisticLockable = DomHelper.extractBooleanAttributeValue( element, "optimistic-lock", true ); + } + @Override public EntityBinding getEntityBinding() { return entityBinding; @@ -89,14 +116,21 @@ public abstract class AbstractAttributeBinding implements AttributeBinding { return hibernateTypeDescriptor; } - @Override - public Map getMetaAttributes() { - return metaAttributes; + public String getCascade() { + return cascade; + } + + public boolean isOptimisticLockable() { + return optimisticLockable; + } + + public String getNodeName() { + return nodeName; } @Override - public void setMetaAttributes(Map metaAttributes) { - this.metaAttributes = metaAttributes; + public Map getMetaAttributes() { + return metaAttributes; } @Override @@ -114,13 +148,8 @@ public abstract class AbstractAttributeBinding implements AttributeBinding { } @Override - public FetchMode getFetchMode() { - return fetchMode; - } - - @Override - public void setFetchMode(FetchMode fetchMode) { - this.fetchMode = fetchMode; + public String getPropertyAccessorName() { + return propertyAccessorName; } @Override @@ -174,4 +203,15 @@ public abstract class AbstractAttributeBinding implements AttributeBinding { public boolean[] getColumnUpdateability() { return getColumnInsertability(); } + + @Override + public boolean isLazy() { + return isLazy; + } + + protected abstract boolean isLazyDefault(MappingDefaults defaults); + + protected void setLazy(boolean isLazy) { + this.isLazy = isLazy; + } } diff --git a/hibernate-core/src/main/java/org/hibernate/metamodel/binding/AttributeBinding.java b/hibernate-core/src/main/java/org/hibernate/metamodel/binding/AttributeBinding.java index 5ea339bda7..954a74b615 100644 --- a/hibernate-core/src/main/java/org/hibernate/metamodel/binding/AttributeBinding.java +++ b/hibernate-core/src/main/java/org/hibernate/metamodel/binding/AttributeBinding.java @@ -88,14 +88,7 @@ public interface AttributeBinding { public Map getMetaAttributes(); /** - * Set the meta attribute map associated with this binding - * - * @param metaAttributes The meta attributes - */ - public void setMetaAttributes(Map metaAttributes); - - /** - * In the case that {@link #getValue()} represnets a {@link org.hibernate.metamodel.relational.Tuple} this method + * In the case that {@link #getValue()} represents a {@link org.hibernate.metamodel.relational.Tuple} this method * gives access to its compound values. In the case of {@link org.hibernate.metamodel.relational.SimpleValue}, * we return an Iterable over that single simple value. * @@ -110,8 +103,7 @@ public interface AttributeBinding { @Deprecated public TableSpecification getTable(); - public FetchMode getFetchMode(); - public void setFetchMode(FetchMode fetchMode); + public String getPropertyAccessorName(); /** * @@ -124,4 +116,6 @@ public interface AttributeBinding { public boolean[] getColumnUpdateability(); public boolean[] getColumnInsertability(); public boolean isSimpleValue(); + public boolean isEmbedded(); + public boolean isLazy(); } diff --git a/hibernate-core/src/main/java/org/hibernate/metamodel/binding/CollectionElement.java b/hibernate-core/src/main/java/org/hibernate/metamodel/binding/CollectionElement.java index f267f0978e..25ac5c4023 100644 --- a/hibernate-core/src/main/java/org/hibernate/metamodel/binding/CollectionElement.java +++ b/hibernate-core/src/main/java/org/hibernate/metamodel/binding/CollectionElement.java @@ -23,7 +23,11 @@ */ package org.hibernate.metamodel.binding; +import org.dom4j.Element; + import org.hibernate.mapping.Value; +import org.hibernate.metamodel.source.hbm.HbmHelper; +import org.hibernate.metamodel.source.util.DomHelper; /** * TODO : javadoc @@ -34,9 +38,15 @@ public class CollectionElement { private final HibernateTypeDescriptor hibernateTypeDescriptor = new HibernateTypeDescriptor(); private final PluralAttributeBinding collectionBinding; + private String nodeName; + private Value elementValue; CollectionElement(PluralAttributeBinding collectionBinding) { this.collectionBinding = collectionBinding; } + + public void fromHbmXml(Element node) { + nodeName = DomHelper.extractAttributeValue( node, "node", null ); + } } diff --git a/hibernate-core/src/main/java/org/hibernate/metamodel/binding/ElementCollectionElement.java b/hibernate-core/src/main/java/org/hibernate/metamodel/binding/ElementCollectionElement.java new file mode 100644 index 0000000000..2a8b94499d --- /dev/null +++ b/hibernate-core/src/main/java/org/hibernate/metamodel/binding/ElementCollectionElement.java @@ -0,0 +1,39 @@ +/* + * Hibernate, Relational Persistence for Idiomatic Java + * + * Copyright (c) 2011, Red Hat Inc. or third-party contributors as + * indicated by the @author tags or express copyright attribution + * statements applied by the authors. All third-party contributions are + * distributed under license by Red Hat Inc. + * + * This copyrighted material is made available to anyone wishing to use, modify, + * copy, or redistribute it subject to the terms and conditions of the GNU + * Lesser General Public License, as published by the Free Software Foundation. + * + * 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 Lesser General Public License + * for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this distribution; if not, write to: + * Free Software Foundation, Inc. + * 51 Franklin Street, Fifth Floor + * Boston, MA 02110-1301 USA + */ +package org.hibernate.metamodel.binding; + +import org.dom4j.Element; + +/** + * @author Gail Badner + */ +public class ElementCollectionElement extends CollectionElement { + public ElementCollectionElement(PluralAttributeBinding binding) { + super( binding ); + } + + public void fromHbmXml() { + //TODO: + } +} diff --git a/hibernate-core/src/main/java/org/hibernate/metamodel/binding/EntityBinding.java b/hibernate-core/src/main/java/org/hibernate/metamodel/binding/EntityBinding.java index 99562d45d1..4ce3433066 100644 --- a/hibernate-core/src/main/java/org/hibernate/metamodel/binding/EntityBinding.java +++ b/hibernate-core/src/main/java/org/hibernate/metamodel/binding/EntityBinding.java @@ -25,13 +25,21 @@ package org.hibernate.metamodel.binding; import java.util.ArrayList; import java.util.HashMap; +import java.util.Iterator; import java.util.List; import java.util.Map; -import org.hibernate.engine.ExecuteUpdateResultCheckStyle; +import org.dom4j.Attribute; +import org.dom4j.Element; + +import org.hibernate.MappingException; +import org.hibernate.engine.Versioning; +import org.hibernate.internal.util.ReflectHelper; import org.hibernate.mapping.MetaAttribute; import org.hibernate.metamodel.domain.Entity; import org.hibernate.metamodel.relational.TableSpecification; +import org.hibernate.metamodel.source.hbm.HbmHelper; +import org.hibernate.metamodel.source.util.DomHelper; /** * TODO : javadoc @@ -64,13 +72,74 @@ public class EntityBinding { private int batchSize; private boolean selectBeforeUpdate; + private boolean hasSubselectLoadableCollections; private int optimisticLockMode; private Class entityPersisterClass; private Boolean isAbstract; + private CustomSQL customInsert; + private CustomSQL customUpdate; + private CustomSQL customDelete; + private List synchronizedTableNames; + public void fromHbmXml(MappingDefaults defaults, Element node, Entity entity) { + this.entity = entity; + metaAttributes = HbmHelper.extractMetas( node, true, defaults.getMappingMetas() ); + + // go ahead and set the lazy here, since pojo.proxy can override it. + lazy = DomHelper.extractBooleanAttributeValue( node, "lazy", defaults.isDefaultLazy() ); + + discriminatorValue = DomHelper.extractAttributeValue( node, "discriminator-value", entity.getName() ); + dynamicUpdate = DomHelper.extractBooleanAttributeValue( node, "dynamic-update", false ); + dynamicInsert = DomHelper.extractBooleanAttributeValue( node, "dynamic-insert", false ); + batchSize = DomHelper.extractIntAttributeValue( node, "batch-size", 0 ); + selectBeforeUpdate = DomHelper.extractBooleanAttributeValue( node, "select-before-update", false ); + + // OPTIMISTIC LOCK MODE + String optimisticLockModeString = DomHelper.extractAttributeValue( node, "optimistic-lock", "version" ); + if ( "version".equals( optimisticLockModeString ) ) { + optimisticLockMode = Versioning.OPTIMISTIC_LOCK_VERSION; + } + else if ( "dirty".equals( optimisticLockModeString ) ) { + optimisticLockMode = Versioning.OPTIMISTIC_LOCK_DIRTY; + } + else if ( "all".equals( optimisticLockModeString ) ) { + optimisticLockMode = Versioning.OPTIMISTIC_LOCK_ALL; + } + else if ( "none".equals( optimisticLockModeString ) ) { + optimisticLockMode = Versioning.OPTIMISTIC_LOCK_NONE; + } + else { + throw new MappingException( "Unsupported optimistic-lock style: " + optimisticLockModeString ); + } + + // PERSISTER + Attribute persisterNode = node.attribute( "persister" ); + if ( persisterNode != null ) { + try { + entityPersisterClass = ReflectHelper.classForName( persisterNode.getValue() ); + } + catch (ClassNotFoundException cnfe) { + throw new MappingException( "Could not find persister class: " + + persisterNode.getValue() ); + } + } + + // CUSTOM SQL + customInsert = HbmHelper.getCustomSql( node.element( "sql-insert" ) ); + customDelete = HbmHelper.getCustomSql( node.element( "sql-delete" ) ); + customUpdate = HbmHelper.getCustomSql( node.element( "sql-update" ) ); + + Iterator tables = node.elementIterator( "synchronize" ); + while ( tables.hasNext() ) { + addSynchronizedTable( ( ( Element ) tables.next() ).attributeValue( "table" ) ); + } + + isAbstract = DomHelper.extractBooleanAttributeValue( node, "abstract", false ); + } + public Entity getEntity() { return entity; } @@ -226,6 +295,15 @@ public class EntityBinding { this.selectBeforeUpdate = selectBeforeUpdate; } + public boolean hasSubselectLoadableCollections() { + return hasSubselectLoadableCollections; + } + + /* package-protected */ + void setSubselectLoadableCollections(boolean hasSubselectLoadableCollections) { + this.hasSubselectLoadableCollections = hasSubselectLoadableCollections; + } + public int getOptimisticLockMode() { return optimisticLockMode; } @@ -246,11 +324,7 @@ public class EntityBinding { return isAbstract; } - public void setAbstract(Boolean isAbstract) { - this.isAbstract = isAbstract; - } - - public void addSynchronizedTable(String tablename) { + protected void addSynchronizedTable(String tablename) { if ( synchronizedTableNames == null ) { synchronizedTableNames = new ArrayList(); } @@ -270,31 +344,15 @@ public class EntityBinding { this.loaderName = loaderName; } - private CustomSQL customInsert; - private CustomSQL customUpdate; - private CustomSQL customDelete; - public CustomSQL getCustomInsert() { return customInsert; } - public void setCustomSqlInsert(String sql, boolean callable, ExecuteUpdateResultCheckStyle resultCheckStyle) { - customInsert = new CustomSQL( sql, callable, resultCheckStyle ); - } - public CustomSQL getCustomUpdate() { return customUpdate; } - public void setCustomSqlUpdate(String sql, boolean callable, ExecuteUpdateResultCheckStyle resultCheckStyle) { - customUpdate = new CustomSQL( sql, callable, resultCheckStyle ); - } - public CustomSQL getCustomDelete() { return customDelete; } - - public void setCustomSqlDelete(String sql, boolean callable, ExecuteUpdateResultCheckStyle resultCheckStyle) { - customDelete = new CustomSQL( sql, callable, resultCheckStyle ); - } } diff --git a/hibernate-core/src/main/java/org/hibernate/metamodel/binding/ManyToManyCollectionElement.java b/hibernate-core/src/main/java/org/hibernate/metamodel/binding/ManyToManyCollectionElement.java new file mode 100644 index 0000000000..6bc7b20fbc --- /dev/null +++ b/hibernate-core/src/main/java/org/hibernate/metamodel/binding/ManyToManyCollectionElement.java @@ -0,0 +1,79 @@ +/* + * Hibernate, Relational Persistence for Idiomatic Java + * + * Copyright (c) 2011, Red Hat Inc. or third-party contributors as + * indicated by the @author tags or express copyright attribution + * statements applied by the authors. All third-party contributions are + * distributed under license by Red Hat Inc. + * + * This copyrighted material is made available to anyone wishing to use, modify, + * copy, or redistribute it subject to the terms and conditions of the GNU + * Lesser General Public License, as published by the Free Software Foundation. + * + * 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 Lesser General Public License + * for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this distribution; if not, write to: + * Free Software Foundation, Inc. + * 51 Franklin Street, Fifth Floor + * Boston, MA 02110-1301 USA + */ +package org.hibernate.metamodel.binding; + +import java.util.HashMap; + +import org.dom4j.Element; + +/** + * @author Gail Badner + */ +public class ManyToManyCollectionElement extends CollectionElement { + private final java.util.Map manyToManyFilters = new HashMap(); + private String manyToManyWhere; + private String manyToManyOrderBy; + + + ManyToManyCollectionElement(Element collectionNode, PluralAttributeBinding binding) { + super( binding ); + } + + public void fromHbmXml(Element node){ + /* + + + + + + + + + + + + + + + + + */ + } + + public String getManyToManyWhere() { + return manyToManyWhere; + } + + public void setManyToManyWhere(String manyToManyWhere) { + this.manyToManyWhere = manyToManyWhere; + } + + public String getManyToManyOrderBy() { + return manyToManyOrderBy; + } + + public void setManyToManyOrderBy(String manyToManyOrderBy) { + this.manyToManyOrderBy = manyToManyOrderBy; + } +} diff --git a/hibernate-core/src/main/java/org/hibernate/metamodel/binding/MappingDefaults.java b/hibernate-core/src/main/java/org/hibernate/metamodel/binding/MappingDefaults.java new file mode 100644 index 0000000000..13a4d591db --- /dev/null +++ b/hibernate-core/src/main/java/org/hibernate/metamodel/binding/MappingDefaults.java @@ -0,0 +1,40 @@ +/* + * Hibernate, Relational Persistence for Idiomatic Java + * + * Copyright (c) 2011, Red Hat Inc. or third-party contributors as + * indicated by the @author tags or express copyright attribution + * statements applied by the authors. All third-party contributions are + * distributed under license by Red Hat Inc. + * + * This copyrighted material is made available to anyone wishing to use, modify, + * copy, or redistribute it subject to the terms and conditions of the GNU + * Lesser General Public License, as published by the Free Software Foundation. + * + * 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 Lesser General Public License + * for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this distribution; if not, write to: + * Free Software Foundation, Inc. + * 51 Franklin Street, Fifth Floor + * Boston, MA 02110-1301 USA + */ +package org.hibernate.metamodel.binding; + +import java.util.Map; + +import org.hibernate.mapping.MetaAttribute; + +/** + * @author Gail Badner + */ +public interface MappingDefaults { + Map getMappingMetas(); + String getDefaultSchemaName(); + String getDefaultCatalogName(); + String getDefaultCascade(); + String getDefaultAccess(); + boolean isDefaultLazy(); +} diff --git a/hibernate-core/src/main/java/org/hibernate/metamodel/binding/PluralAttributeBinding.java b/hibernate-core/src/main/java/org/hibernate/metamodel/binding/PluralAttributeBinding.java index 207a40c7de..914d3dcaf3 100644 --- a/hibernate-core/src/main/java/org/hibernate/metamodel/binding/PluralAttributeBinding.java +++ b/hibernate-core/src/main/java/org/hibernate/metamodel/binding/PluralAttributeBinding.java @@ -26,23 +26,37 @@ package org.hibernate.metamodel.binding; import java.util.Comparator; import java.util.HashMap; import java.util.HashSet; +import java.util.Iterator; + +import org.dom4j.Attribute; +import org.dom4j.Element; +import org.jboss.logging.Logger; import org.hibernate.FetchMode; +import org.hibernate.HibernateLogger; +import org.hibernate.MappingException; import org.hibernate.metamodel.relational.Table; +import org.hibernate.metamodel.source.hbm.HbmHelper; +import org.hibernate.metamodel.source.util.DomHelper; /** * TODO : javadoc * * @author Steve Ebersole */ -public abstract class PluralAttributeBinding extends AbstractAttributeBinding implements AttributeBinding { +public abstract class PluralAttributeBinding extends AbstractAttributeBinding { + + private static final HibernateLogger LOG = Logger.getMessageLogger( + HibernateLogger.class, PluralAttributeBinding.class.getName() + ); + private Table collectionTable; private CollectionKey collectionKey; private CollectionElement collectionElement; // private String role; - private boolean lazy; + private FetchMode fetchMode; private boolean extraLazy; private boolean inverse; private boolean mutable = true; @@ -51,23 +65,17 @@ public abstract class PluralAttributeBinding extends AbstractAttributeBinding im private String cacheRegionName; private String orderBy; private String where; - private String manyToManyWhere; - private String manyToManyOrderBy; private String referencedPropertyName; - private String nodeName; - private String elementNodeName; private boolean sorted; private Comparator comparator; private String comparatorClassName; private boolean orphanDelete; private int batchSize = -1; - private FetchMode fetchMode; private boolean embedded = true; private boolean optimisticLocked = true; private Class collectionPersisterClass; private String typeName; private final java.util.Map filters = new HashMap(); - private final java.util.Map manyToManyFilters = new HashMap(); private final java.util.Set synchronizedTables = new HashSet(); private CustomSQL customSQLInsert; @@ -79,6 +87,112 @@ public abstract class PluralAttributeBinding extends AbstractAttributeBinding im protected PluralAttributeBinding(EntityBinding entityBinding) { super( entityBinding ); + collectionElement = new CollectionElement( this ); + } + + public void fromHbmXml(MappingDefaults defaults, Element element, org.hibernate.metamodel.domain.Attribute attribute) { + super.fromHbmXml( defaults, element, attribute ); + inverse = DomHelper.extractBooleanAttributeValue( element, "inverse", false ); + mutable = DomHelper.extractBooleanAttributeValue( element, "mutable", true ); + if ( "subselect".equals( element.attributeValue("fetch") ) ) { + subselectLoadable = true; + getEntityBinding().setSubselectLoadableCollections( true ); + } + orderBy = DomHelper.extractAttributeValue( element, "order-by", null ); + where = DomHelper.extractAttributeValue( element, "where", null ); + batchSize = DomHelper.extractIntAttributeValue( element, "batch-size", 0 ); + embedded = DomHelper.extractBooleanAttributeValue( element, "embed-xml", true ); + try { + collectionPersisterClass = DomHelper.extractClassAttributeValue( element, "persister" ); + } + catch (ClassNotFoundException cnfe) { + throw new MappingException( "Could not find collection persister class: " + + element.attributeValue( "persister" ) ); + } + + //Attribute typeNode = collectionElement.attribute( "collection-type" ); + //if ( typeNode != null ) { + // TODO: implement when typedef binding is implemented + /* + String typeName = typeNode.getValue(); + TypeDef typeDef = mappings.getTypeDef( typeName ); + if ( typeDef != null ) { + collectionBinding.setTypeName( typeDef.getTypeClass() ); + collectionBinding.setTypeParameters( typeDef.getParameters() ); + } + else { + collectionBinding.setTypeName( typeName ); + } + */ + //} + + // SORT + // unsorted, natural, comparator.class.name + String sortString = DomHelper.extractAttributeValue( element, "sort", "unsorted" ); + sorted = ( ! "unsorted".equals( sortString ) ); + if ( sorted && ! "natural".equals( sortString ) ) { + comparatorClassName = sortString; + } + + // ORPHAN DELETE (used for programmer error detection) + String cascadeString = DomHelper.extractAttributeValue( element, "cascade", "none" ); + orphanDelete = ( cascadeString.indexOf( "delete-orphan" ) >= 0 ); + + // CUSTOM SQL + customSQLInsert = HbmHelper.getCustomSql( element.element( "sql-insert" ) ); + customSQLDelete = HbmHelper.getCustomSql( element.element( "sql-delete" ) ); + customSQLUpdate = HbmHelper.getCustomSql( element.element( "sql-update" ) ); + customSQLDeleteAll = HbmHelper.getCustomSql( element.element( "sql-delete-all" ) ); + + // TODO: IMPLEMENT + //Iterator iter = collectionElement.elementIterator( "filter" ); + //while ( iter.hasNext() ) { + // final Element filter = (Element) iter.next(); + // parseFilter( filter, collectionElement, collectionBinding ); + //} + + Iterator tables = element.elementIterator( "synchronize" ); + while ( tables.hasNext() ) { + synchronizedTables.add( ( (Element ) tables.next() ).attributeValue( "table" ) ); + } + + loaderName = DomHelper.extractAttributeValue( element.element( "loader" ), "query-ref" ); + referencedPropertyName = element.element( "key" ).attributeValue( "property-ref" ); + + Element cacheElement = element.element( "cache" ); + if ( cacheElement != null ) { + cacheConcurrencyStrategy = cacheElement.attributeValue( "usage" ); + cacheRegionName = cacheElement.attributeValue( "region" ); + } + + Attribute fetchNode = element.attribute( "fetch" ); + if ( fetchNode != null ) { + fetchMode = "join".equals( fetchNode.getValue() ) ? FetchMode.JOIN : FetchMode.SELECT; + } + else { + Attribute jfNode = element.attribute( "outer-join" ); + String jfNodeValue = ( jfNode == null ? "auto" : jfNode.getValue() ); + if ( "auto".equals( jfNodeValue ) ) { + fetchMode = FetchMode.DEFAULT; + } + else if ( "true".equals( jfNodeValue ) ) { + fetchMode = FetchMode.JOIN; + } + else { + fetchMode = FetchMode.SELECT; + } + } + + String lazyString = DomHelper.extractAttributeValue( element, "lazy" ); + extraLazy = ( "extra".equals( lazyString ) ); + if ( extraLazy && ! isLazy() ) { + // explicitly make lazy + setLazy( true ); + } + } + + protected boolean isLazyDefault(MappingDefaults defaults) { + return defaults.isDefaultLazy(); } @Override @@ -109,127 +223,46 @@ public abstract class PluralAttributeBinding extends AbstractAttributeBinding im public void setCollectionElement(CollectionElement collectionElement) { this.collectionElement = collectionElement; } - - public boolean isLazy() { - return lazy; - } - - public void setLazy(boolean lazy) { - this.lazy = lazy; - } - public boolean isExtraLazy() { return extraLazy; } - public void setExtraLazy(boolean extraLazy) { - this.extraLazy = extraLazy; - } - public boolean isInverse() { return inverse; } - public void setInverse(boolean inverse) { - this.inverse = inverse; - } - public boolean isMutable() { return mutable; } - public void setMutable(boolean mutable) { - this.mutable = mutable; - } - public boolean isSubselectLoadable() { return subselectLoadable; } - public void setSubselectLoadable(boolean subselectLoadable) { - this.subselectLoadable = subselectLoadable; - } - public String getCacheConcurrencyStrategy() { return cacheConcurrencyStrategy; } - public void setCacheConcurrencyStrategy(String cacheConcurrencyStrategy) { - this.cacheConcurrencyStrategy = cacheConcurrencyStrategy; - } - public String getCacheRegionName() { return cacheRegionName; } - public void setCacheRegionName(String cacheRegionName) { - this.cacheRegionName = cacheRegionName; - } - public String getOrderBy() { return orderBy; } - public void setOrderBy(String orderBy) { - this.orderBy = orderBy; - } - public String getWhere() { return where; } - public void setWhere(String where) { - this.where = where; - } - - public String getManyToManyWhere() { - return manyToManyWhere; - } - - public void setManyToManyWhere(String manyToManyWhere) { - this.manyToManyWhere = manyToManyWhere; - } - - public String getManyToManyOrderBy() { - return manyToManyOrderBy; - } - - public void setManyToManyOrderBy(String manyToManyOrderBy) { - this.manyToManyOrderBy = manyToManyOrderBy; - } - public String getReferencedPropertyName() { return referencedPropertyName; } - public void setReferencedPropertyName(String referencedPropertyName) { - this.referencedPropertyName = referencedPropertyName; - } - - public String getNodeName() { - return nodeName; - } - - public void setNodeName(String nodeName) { - this.nodeName = nodeName; - } - - public String getElementNodeName() { - return elementNodeName; - } - - public void setElementNodeName(String elementNodeName) { - this.elementNodeName = elementNodeName; - } - public boolean isSorted() { return sorted; } - public void setSorted(boolean sorted) { - this.sorted = sorted; - } - public Comparator getComparator() { return comparator; } @@ -242,103 +275,56 @@ public abstract class PluralAttributeBinding extends AbstractAttributeBinding im return comparatorClassName; } - public void setComparatorClassName(String comparatorClassName) { - this.comparatorClassName = comparatorClassName; - } - public boolean isOrphanDelete() { return orphanDelete; } - public void setOrphanDelete(boolean orphanDelete) { - this.orphanDelete = orphanDelete; - } - public int getBatchSize() { return batchSize; } - public void setBatchSize(int batchSize) { - this.batchSize = batchSize; - } - - public FetchMode getFetchMode() { - return fetchMode; - } - - public void setFetchMode(FetchMode fetchMode) { - this.fetchMode = fetchMode; - } - + @Override public boolean isEmbedded() { return embedded; } - public void setEmbedded(boolean embedded) { - this.embedded = embedded; - } - public boolean isOptimisticLocked() { return optimisticLocked; } - public void setOptimisticLocked(boolean optimisticLocked) { - this.optimisticLocked = optimisticLocked; - } - public Class getCollectionPersisterClass() { return collectionPersisterClass; } - public void setCollectionPersisterClass(Class collectionPersisterClass) { - this.collectionPersisterClass = collectionPersisterClass; - } - public String getTypeName() { return typeName; } - public void setTypeName(String typeName) { - this.typeName = typeName; + public void addFilter(String name, String condition) { + filters.put( name, condition ); + } + + public java.util.Map getFilterMap() { + return filters; } public CustomSQL getCustomSQLInsert() { return customSQLInsert; } - public void setCustomSQLInsert(CustomSQL customSQLInsert) { - this.customSQLInsert = customSQLInsert; - } - public CustomSQL getCustomSQLUpdate() { return customSQLUpdate; } - public void setCustomSQLUpdate(CustomSQL customSQLUpdate) { - this.customSQLUpdate = customSQLUpdate; - } - public CustomSQL getCustomSQLDelete() { return customSQLDelete; } - public void setCustomSQLDelete(CustomSQL customSQLDelete) { - this.customSQLDelete = customSQLDelete; - } - public CustomSQL getCustomSQLDeleteAll() { return customSQLDeleteAll; } - public void setCustomSQLDeleteAll(CustomSQL customSQLDeleteAll) { - this.customSQLDeleteAll = customSQLDeleteAll; - } - public String getLoaderName() { return loaderName; } - - public void setLoaderName(String loaderName) { - this.loaderName = loaderName; - } } diff --git a/hibernate-core/src/main/java/org/hibernate/metamodel/binding/SimpleAttributeBinding.java b/hibernate-core/src/main/java/org/hibernate/metamodel/binding/SimpleAttributeBinding.java index d1df1dc4e3..b93d533e00 100644 --- a/hibernate-core/src/main/java/org/hibernate/metamodel/binding/SimpleAttributeBinding.java +++ b/hibernate-core/src/main/java/org/hibernate/metamodel/binding/SimpleAttributeBinding.java @@ -23,115 +23,90 @@ */ package org.hibernate.metamodel.binding; +import org.dom4j.Attribute; +import org.dom4j.Element; + +import org.hibernate.MappingException; import org.hibernate.mapping.PropertyGeneration; +import org.hibernate.metamodel.source.hbm.HbmHelper; +import org.hibernate.metamodel.source.util.DomHelper; /** * TODO : javadoc * * @author Steve Ebersole */ -public class SimpleAttributeBinding extends AbstractAttributeBinding implements KeyValueBinding { - private String propertyAccessorName; - private String cascade; +public class SimpleAttributeBinding extends SingularAttributeBinding { private PropertyGeneration generation; - private boolean insertable; - private boolean updateable; - private boolean optimisticLockable; private boolean isLazy; - private boolean keyCasadeDeleteEnabled; - private String unsaveValue; - - // DOM4J specific... - private String nodeName; SimpleAttributeBinding(EntityBinding entityBinding) { super( entityBinding ); } + public void fromHbmXml(MappingDefaults defaults, Element element, org.hibernate.metamodel.domain.Attribute attribute) { + super.fromHbmXml( defaults, element, attribute ); + this.isLazy = DomHelper.extractBooleanAttributeValue( element, "lazy", false ); + this.generation = PropertyGeneration.parse( DomHelper.extractAttributeValue( element, "generated", null ) ); + if ( generation == PropertyGeneration.ALWAYS || generation == PropertyGeneration.INSERT ) { + // generated properties can *never* be insertable... + if ( isInsertable() ) { + final Attribute insertAttribute = element.attribute( "insert" ); + if ( insertAttribute == null ) { + // insertable simply because the user did not specify anything; just override it + setInsertable( false ); + } + else { + // the user specifically supplied insert="true", which constitutes an illegal combo + throw new MappingException( + "cannot specify both insert=\"true\" and generated=\"" + generation.getName() + + "\" for property: " + + getAttribute().getName() + ); + } + } + + // properties generated on update can never be updateable... + if ( isUpdateable() && generation == PropertyGeneration.ALWAYS ) { + final Attribute updateAttribute = element.attribute( "update" ); + if ( updateAttribute == null ) { + // updateable only because the user did not specify + // anything; just override it + setUpdateable( false ); + } + else { + // the user specifically supplied update="true", + // which constitutes an illegal combo + throw new MappingException( + "cannot specify both update=\"true\" and generated=\"" + generation.getName() + + "\" for property: " + + getAttribute().getName() + ); + } + } + } + } + + protected boolean isLazyDefault(MappingDefaults defaults) { + return false; + } + @Override public boolean isSimpleValue() { return true; } - public String getPropertyAccessorName() { - return propertyAccessorName; - } - - public void setPropertyAccessorName(String propertyAccessorName) { - this.propertyAccessorName = propertyAccessorName; - } - - public String getCascade() { - return cascade; - } - - public void setCascade(String cascade) { - this.cascade = cascade; - } - public PropertyGeneration getGeneration() { return generation; } - public void setGeneration(PropertyGeneration generation) { - this.generation = generation; - } - - public boolean isInsertable() { - return insertable; - } - - public void setInsertable(boolean insertable) { - this.insertable = insertable; - } - @Override - public boolean isKeyCasadeDeleteEnabled() { - return keyCasadeDeleteEnabled; - } - - public void setKeyCasadeDeleteEnabled(boolean keyCasadeDeleteEnabled) { - this.keyCasadeDeleteEnabled = keyCasadeDeleteEnabled; - } - - @Override - public String getUnsavedValue() { - return unsaveValue; - } - - public void setUnsaveValue(String unsaveValue) { - this.unsaveValue = unsaveValue; - } - - public boolean isUpdateable() { - return updateable; - } - - public void setUpdateable(boolean updateable) { - this.updateable = updateable; - } - - public boolean isOptimisticLockable() { - return optimisticLockable; - } - - public void setOptimisticLockable(boolean optimisticLockable) { - this.optimisticLockable = optimisticLockable; - } - public boolean isLazy() { return isLazy; } - public void setLazy(boolean lazy) { - isLazy = lazy; - } - - public String getNodeName() { - return nodeName; - } - - public void setNodeName(String nodeName) { - this.nodeName = nodeName; + @Override + public boolean isEmbedded() { + return false; } } diff --git a/hibernate-core/src/main/java/org/hibernate/metamodel/binding/SingularAttributeBinding.java b/hibernate-core/src/main/java/org/hibernate/metamodel/binding/SingularAttributeBinding.java new file mode 100644 index 0000000000..82f2e7aa0d --- /dev/null +++ b/hibernate-core/src/main/java/org/hibernate/metamodel/binding/SingularAttributeBinding.java @@ -0,0 +1,86 @@ +/* + * Hibernate, Relational Persistence for Idiomatic Java + * + * Copyright (c) 2010, Red Hat Inc. or third-party contributors as + * indicated by the @author tags or express copyright attribution + * statements applied by the authors. All third-party contributions are + * distributed under license by Red Hat Inc. + * + * This copyrighted material is made available to anyone wishing to use, modify, + * copy, or redistribute it subject to the terms and conditions of the GNU + * Lesser General Public License, as published by the Free Software Foundation. + * + * 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 Lesser General Public License + * for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this distribution; if not, write to: + * Free Software Foundation, Inc. + * 51 Franklin Street, Fifth Floor + * Boston, MA 02110-1301 USA + */ +package org.hibernate.metamodel.binding; + +import org.dom4j.Element; + +import org.hibernate.metamodel.domain.Attribute; +import org.hibernate.metamodel.source.hbm.HbmHelper; +import org.hibernate.metamodel.source.util.DomHelper; + +/** + * TODO : javadoc + * + * @author Gail Badner + */ +public abstract class SingularAttributeBinding extends AbstractAttributeBinding implements KeyValueBinding { + private boolean insertable; + private boolean updateable; + private boolean keyCasadeDeleteEnabled; + private String unsavedValue; + + SingularAttributeBinding(EntityBinding entityBinding) { + super( entityBinding ); + } + + public void fromHbmXml(MappingDefaults defaults, Element element, Attribute attribute) { + super.fromHbmXml( defaults, element, attribute ); + insertable = DomHelper.extractBooleanAttributeValue( element, "insert", true ); + updateable = DomHelper.extractBooleanAttributeValue( element, "update", true ); + } + + public boolean isInsertable() { + return insertable; + } + + protected void setInsertable(boolean insertable) { + this.insertable = insertable; + } + + public boolean isUpdateable() { + return updateable; + } + + protected void setUpdateable(boolean updateable) { + this.updateable = updateable; + } + + @Override + public boolean isKeyCasadeDeleteEnabled() { + return keyCasadeDeleteEnabled; + } + + public void setKeyCasadeDeleteEnabled(boolean keyCasadeDeleteEnabled) { + this.keyCasadeDeleteEnabled = keyCasadeDeleteEnabled; + } + + @Override + public String getUnsavedValue() { + return unsavedValue; + } + + public void setUnsavedValue(String unsaveValue) { + this.unsavedValue = unsaveValue; + } +} diff --git a/hibernate-core/src/main/java/org/hibernate/metamodel/source/hbm/AbstractEntityBinder.java b/hibernate-core/src/main/java/org/hibernate/metamodel/source/hbm/AbstractEntityBinder.java index 0f6db08301..a50d76d602 100644 --- a/hibernate-core/src/main/java/org/hibernate/metamodel/source/hbm/AbstractEntityBinder.java +++ b/hibernate-core/src/main/java/org/hibernate/metamodel/source/hbm/AbstractEntityBinder.java @@ -32,25 +32,25 @@ import java.util.StringTokenizer; import org.dom4j.Attribute; import org.dom4j.Element; - +import org.jboss.logging.Logger; import org.hibernate.EntityMode; +import org.hibernate.HibernateLogger; import org.hibernate.MappingException; import org.hibernate.cfg.NamingStrategy; import org.hibernate.engine.Versioning; import org.hibernate.internal.util.ReflectHelper; import org.hibernate.internal.util.StringHelper; import org.hibernate.mapping.MetaAttribute; -import org.hibernate.mapping.PropertyGeneration; import org.hibernate.metamodel.binding.AttributeBinding; import org.hibernate.metamodel.binding.BagBinding; +import org.hibernate.metamodel.binding.CollectionElement; +import org.hibernate.metamodel.binding.ElementCollectionElement; import org.hibernate.metamodel.binding.EntityBinding; import org.hibernate.metamodel.binding.PluralAttributeBinding; import org.hibernate.metamodel.binding.SimpleAttributeBinding; import org.hibernate.metamodel.domain.Entity; import org.hibernate.metamodel.domain.Hierarchical; -import org.hibernate.metamodel.domain.PluralAttribute; import org.hibernate.metamodel.domain.PluralAttributeNature; -import org.hibernate.metamodel.domain.SingularAttribute; import org.hibernate.metamodel.relational.Column; import org.hibernate.metamodel.relational.Index; import org.hibernate.metamodel.relational.Schema; @@ -69,16 +69,16 @@ import org.hibernate.metamodel.source.util.DomHelper; * @author Steve Ebersole */ abstract class AbstractEntityBinder { + private static final HibernateLogger LOG = Logger.getMessageLogger( + HibernateLogger.class, AbstractEntityBinder.class.getName() + ); - protected final HibernateMappingBinder hibernateMappingBinder; - protected final Map entityMetas; - protected final Schema.Name schemaName; + private final HibernateMappingBinder hibernateMappingBinder; + private final Schema.Name schemaName; AbstractEntityBinder(HibernateMappingBinder hibernateMappingBinder, Element entityElement) { this.hibernateMappingBinder = hibernateMappingBinder; - entityMetas = HbmHelper.extractMetas( entityElement, true, hibernateMappingBinder.getMappingMetas() ); - final Attribute schemaAttribute = entityElement.attribute( "schema" ); String schemaName = ( schemaAttribute == null ) ? hibernateMappingBinder.getDefaultSchemaName() @@ -92,6 +92,10 @@ abstract class AbstractEntityBinder { this.schemaName = new Schema.Name( schemaName, catalogName ); } + protected HibernateMappingBinder getHibernateMappingBinder() { + return hibernateMappingBinder; + } + protected HibernateXmlBinder getHibernateXmlBinder() { return hibernateMappingBinder.getHibernateXmlBinder(); } @@ -100,94 +104,46 @@ abstract class AbstractEntityBinder { return hibernateMappingBinder.getHibernateXmlBinder().getMetadata(); } + protected Schema.Name getSchemaName() { + return schemaName; + } protected NamingStrategy getNamingStrategy() { return getMetadata().getNamingStrategy(); } protected void basicEntityBinding(Element node, EntityBinding entityBinding, Hierarchical superType) { - entityBinding.setMetaAttributes( entityMetas ); - + entityBinding.fromHbmXml( + hibernateMappingBinder, + node, + new Entity( hibernateMappingBinder.extractEntityName( node ), superType ) + ); + // TODO: move this stuff out // transfer an explicitly defined lazy attribute - Attribute lazyNode = node.attribute( "lazy" ); - boolean lazy = ( lazyNode == null ) - ? hibernateMappingBinder.isDefaultLazy() - : Boolean.valueOf( lazyNode.getValue() ); - // go ahead and set the lazy here, since pojo.proxy can override it. - entityBinding.setLazy( lazy ); - - String entityName = hibernateMappingBinder.extractEntityName( node ); - if ( entityName == null ) { - throw new MappingException( "Unable to determine entity name" ); - } - entityBinding.setEntity( new Entity( entityName, superType ) ); - bindPojoRepresentation( node, entityBinding ); bindDom4jRepresentation( node, entityBinding ); bindMapRepresentation( node, entityBinding ); + final String entityName = entityBinding.getEntity().getName(); Iterator itr = node.elementIterator( "fetch-profile" ); while ( itr.hasNext() ) { final Element profileElement = ( Element ) itr.next(); hibernateMappingBinder.parseFetchProfile( profileElement, entityName ); } - entityBinding.setDiscriminatorValue( DomHelper.extractAttributeValue( node, "discriminator-value", entityName ) ); - entityBinding.setDynamicUpdate( DomHelper.extractBooleanAttributeValue( node, "dynamic-update", false ) ); - entityBinding.setDynamicInsert( DomHelper.extractBooleanAttributeValue( node, "dynamic-insert", false ) ); - getMetadata().addImport( entityName, entityName ); if ( hibernateMappingBinder.isAutoImport() ) { if ( entityName.indexOf( '.' ) > 0 ) { getMetadata().addImport( StringHelper.unqualify( entityName ), entityName ); } } + } - final Attribute batchNode = node.attribute( "batch-size" ); - if ( batchNode != null ) { - entityBinding.setBatchSize( Integer.parseInt( batchNode.getValue() ) ); - } + protected String getDefaultAccess() { + return hibernateMappingBinder.getDefaultAccess(); + } - final Attribute sbuNode = node.attribute( "select-before-update" ); - if ( sbuNode != null ) { - entityBinding.setSelectBeforeUpdate( Boolean.valueOf( sbuNode.getValue() ) ); - } - - // OPTIMISTIC LOCK MODE - Attribute olNode = node.attribute( "optimistic-lock" ); - entityBinding.setOptimisticLockMode( getOptimisticLockMode( olNode ) ); - - - // PERSISTER - Attribute persisterNode = node.attribute( "persister" ); - if ( persisterNode != null ) { - try { - entityBinding.setEntityPersisterClass( - ReflectHelper.classForName( persisterNode.getValue() ) - ); - } - catch (ClassNotFoundException cnfe) { - throw new MappingException( "Could not find persister class: " - + persisterNode.getValue() ); - } - } - - // CUSTOM SQL - handleCustomSQL( node, entityBinding ); - - Iterator tables = node.elementIterator( "synchronize" ); - while ( tables.hasNext() ) { - entityBinding.addSynchronizedTable( ( (Element) tables.next() ).attributeValue( "table" ) ); - } - - Attribute abstractNode = node.attribute( "abstract" ); - Boolean isAbstract = abstractNode == null - ? null - : "true".equals( abstractNode.getValue() ) - ? Boolean.TRUE - : "false".equals( abstractNode.getValue() ) - ? Boolean.FALSE - : null; - entityBinding.setAbstract( isAbstract ); + protected boolean isDefaultLazy() { + return hibernateMappingBinder.isDefaultLazy(); } private void bindPojoRepresentation(Element node, EntityBinding entityBinding) { @@ -271,32 +227,6 @@ abstract class AbstractEntityBinder { } } - private static void handleCustomSQL(Element entityElement, EntityBinding entityBinding) - throws MappingException { - Element element = entityElement.element( "sql-insert" ); - if ( element != null ) { - boolean callable = HbmHelper.isCallable( element ); - entityBinding.setCustomSqlInsert( element.getTextTrim(), callable, HbmHelper.getResultCheckStyle( element, callable ) ); - } - - element = entityElement.element( "sql-delete" ); - if ( element != null ) { - boolean callable = HbmHelper.isCallable( element ); - entityBinding.setCustomSqlDelete( element.getTextTrim(), callable, HbmHelper.getResultCheckStyle( element, callable ) ); - } - - element = entityElement.element( "sql-update" ); - if ( element != null ) { - boolean callable = HbmHelper.isCallable( element ); - entityBinding.setCustomSqlUpdate( element.getTextTrim(), callable, HbmHelper.getResultCheckStyle( element, callable ) ); - } - - element = entityElement.element( "loader" ); - if ( element != null ) { - entityBinding.setLoaderName( element.attributeValue( "query-ref" ) ); - } - } - protected String getClassTableName( Element entityElement, EntityBinding entityBinding, @@ -497,9 +427,11 @@ abstract class AbstractEntityBinder { protected void bindSimpleAttribute(Element propertyElement, SimpleAttributeBinding attributeBinding, EntityBinding entityBinding, String attributeName) { if ( attributeBinding.getAttribute() == null ) { // attribute has not been bound yet - SingularAttribute attribute = entityBinding.getEntity().getOrCreateSingularAttribute( attributeName ); - attributeBinding.setAttribute( attribute ); - basicAttributeBinding( propertyElement, attributeBinding ); + attributeBinding.fromHbmXml( + hibernateMappingBinder, + propertyElement, + entityBinding.getEntity().getOrCreateSingularAttribute( attributeName ) + ); } if ( attributeBinding.getValue() == null ) { @@ -510,25 +442,42 @@ abstract class AbstractEntityBinder { } protected void bindCollection( - Element collectionElement, + Element collectionNode, PluralAttributeBinding collectionBinding, EntityBinding entityBinding, PluralAttributeNature attributeNature, String attributeName) { if ( collectionBinding.getAttribute() == null ) { // domain model has not been bound yet - PluralAttribute attribute = entityBinding.getEntity().getOrCreatePluralAttribute( attributeName, attributeNature ); - collectionBinding.setAttribute( attribute ); - basicCollectionBinding( collectionElement, collectionBinding ); + collectionBinding.fromHbmXml( + hibernateMappingBinder, + collectionNode, + entityBinding.getEntity().getOrCreatePluralAttribute( attributeName, attributeNature ) + ); + bindCollectionElement( collectionNode, collectionBinding ); } - // todo : relational model binding + if ( collectionBinding.getValue() == null ) { + // todo : relational model binding + } } - protected void basicCollectionBinding(Element collectionElement, PluralAttributeBinding collectionBinding) { - // todo : implement + private void bindCollectionElement( + Element collectionNode, + PluralAttributeBinding collectionBinding) { + CollectionElement collectionElement = createCollectionElement( collectionNode, collectionBinding); + collectionElement.fromHbmXml( collectionNode ); + collectionBinding.setCollectionElement( collectionElement ); } + private CollectionElement createCollectionElement(Element collectionNode, PluralAttributeBinding collectionBinding) { + Element element = collectionNode.element( "element" ); + if ( element != null ) { + return new ElementCollectionElement( collectionBinding ); + } + // TODO: implement other types of collection elements + return null; + } // private static Property createProperty( // final Value value, // final String propertyName, @@ -752,94 +701,4 @@ abstract class AbstractEntityBinder { column.setComment( comment.getTextTrim() ); } } - - protected void basicAttributeBinding(Element propertyElement, SimpleAttributeBinding valueBinding) { - Attribute typeAttribute = propertyElement.attribute( "type" ); - if ( typeAttribute != null ) { - valueBinding.getHibernateTypeDescriptor().setTypeName( typeAttribute.getValue() ); - } - - valueBinding.setMetaAttributes( HbmHelper.extractMetas( propertyElement, entityMetas ) ); - - final String propertyName = valueBinding.getAttribute().getName(); - final String explicitNodename = propertyElement.attributeValue( "node" ); - final String nodeName = explicitNodename != null ? explicitNodename : propertyName; - valueBinding.setNodeName( nodeName ); - - final Attribute accessNode = propertyElement.attribute( "access" ); - if ( accessNode != null ) { - valueBinding.setPropertyAccessorName( accessNode.getValue() ); - } - else if ( propertyElement.getName().equals( "properties" ) ) { - valueBinding.setPropertyAccessorName( "embedded" ); - } - else { - valueBinding.setPropertyAccessorName( hibernateMappingBinder.getDefaultAccess() ); - } - - final String explicitCascade = propertyElement.attributeValue( "cascade" ); - final String cascade = StringHelper.isNotEmpty( explicitCascade ) ? explicitCascade : hibernateMappingBinder.getDefaultCascade(); - valueBinding.setCascade( cascade ); - - final Attribute updateAttribute = propertyElement.attribute( "update" ); - valueBinding.setUpdateable( updateAttribute == null || "true".equals( updateAttribute.getValue() ) ); - - final Attribute insertAttribute = propertyElement.attribute( "insert" ); - valueBinding.setInsertable( insertAttribute == null || "true".equals( insertAttribute.getValue() ) ); - - final Attribute optimisticLockAttribute = propertyElement.attribute( "optimistic-lock" ); - valueBinding.setOptimisticLockable( optimisticLockAttribute == null || "true".equals( optimisticLockAttribute.getValue() ) ); - - final Attribute generatedAttribute= propertyElement.attribute( "generated" ); - final String generationName = generatedAttribute == null ? null : generatedAttribute.getValue(); - final PropertyGeneration generation = PropertyGeneration.parse( generationName ); - valueBinding.setGeneration( generation ); - - if ( generation == PropertyGeneration.ALWAYS || generation == PropertyGeneration.INSERT ) { - // generated properties can *never* be insertable... - if ( valueBinding.isInsertable() ) { - if ( insertAttribute == null ) { - // insertable simply because the user did not specify anything; just override it - valueBinding.setInsertable( false ); - } - else { - // the user specifically supplied insert="true", which constitutes an illegal combo - throw new MappingException( - "cannot specify both insert=\"true\" and generated=\"" + generation.getName() + - "\" for property: " + - propertyName - ); - } - } - - // properties generated on update can never be updateable... - if ( valueBinding.isUpdateable() && generation == PropertyGeneration.ALWAYS ) { - if ( updateAttribute == null ) { - // updateable only because the user did not specify - // anything; just override it - valueBinding.setUpdateable( false ); - } - else { - // the user specifically supplied update="true", - // which constitutes an illegal combo - throw new MappingException( - "cannot specify both update=\"true\" and generated=\"" + generation.getName() + - "\" for property: " + - propertyName - ); - } - } - } - - boolean isLazyable = "property".equals( propertyElement.getName() ) - || "component".equals( propertyElement.getName() ) - || "many-to-one".equals( propertyElement.getName() ) - || "one-to-one".equals( propertyElement.getName() ) - || "any".equals( propertyElement.getName() ); - if ( isLazyable ) { - Attribute lazyNode = propertyElement.attribute( "lazy" ); - valueBinding.setLazy( lazyNode != null && "true".equals( lazyNode.getValue() ) ); - } - - } } diff --git a/hibernate-core/src/main/java/org/hibernate/metamodel/source/hbm/HbmHelper.java b/hibernate-core/src/main/java/org/hibernate/metamodel/source/hbm/HbmHelper.java index 8074190450..b6190c6449 100644 --- a/hibernate-core/src/main/java/org/hibernate/metamodel/source/hbm/HbmHelper.java +++ b/hibernate-core/src/main/java/org/hibernate/metamodel/source/hbm/HbmHelper.java @@ -32,7 +32,10 @@ import org.dom4j.Element; import org.hibernate.MappingException; import org.hibernate.engine.ExecuteUpdateResultCheckStyle; +import org.hibernate.internal.util.ReflectHelper; import org.hibernate.mapping.MetaAttribute; +import org.hibernate.metamodel.binding.CustomSQL; +import org.hibernate.metamodel.source.util.DomHelper; /** * TODO : javadoc @@ -124,4 +127,11 @@ public class HbmHelper { return unqualifiedName; } + public static CustomSQL getCustomSql(Element element ) { + if ( element == null ) { + return null; // EARLY EXIT!!! + } + boolean callable = DomHelper.extractBooleanAttributeValue( element, "callable", false ); + return new CustomSQL( element.getTextTrim(), callable, getResultCheckStyle( element, callable ) ); + } } diff --git a/hibernate-core/src/main/java/org/hibernate/metamodel/source/hbm/HibernateMappingBinder.java b/hibernate-core/src/main/java/org/hibernate/metamodel/source/hbm/HibernateMappingBinder.java index cf86d08a25..3ca1de3506 100644 --- a/hibernate-core/src/main/java/org/hibernate/metamodel/source/hbm/HibernateMappingBinder.java +++ b/hibernate-core/src/main/java/org/hibernate/metamodel/source/hbm/HibernateMappingBinder.java @@ -35,12 +35,13 @@ import org.hibernate.internal.util.xml.XmlDocument; import org.hibernate.mapping.FetchProfile; import org.hibernate.mapping.MetaAttribute; import org.hibernate.mapping.MetadataSource; +import org.hibernate.metamodel.binding.MappingDefaults; import org.hibernate.metamodel.source.util.DomHelper; /** * Responsible for performing binding of the {@code } DOM element */ -class HibernateMappingBinder { +class HibernateMappingBinder implements MappingDefaults { private final HibernateXmlBinder hibernateXmlBinder; private final XmlDocument xmlDocument; private final Element hibernateMappingElement; @@ -79,23 +80,23 @@ class HibernateMappingBinder { return xmlDocument; } - String getDefaultSchemaName() { + public String getDefaultSchemaName() { return defaultSchemaName; } - String getDefaultCatalogName() { + public String getDefaultCatalogName() { return defaultCatalogName; } - String getDefaultCascade() { + public String getDefaultCascade() { return defaultCascade; } - String getDefaultAccess() { + public String getDefaultAccess() { return defaultAccess; } - boolean isDefaultLazy() { + public boolean isDefaultLazy() { return defaultLazy; } @@ -107,7 +108,7 @@ class HibernateMappingBinder { return autoImport; } - Map getMappingMetas() { + public Map getMappingMetas() { return mappingMetas; } diff --git a/hibernate-core/src/main/java/org/hibernate/metamodel/source/hbm/RootEntityBinder.java b/hibernate-core/src/main/java/org/hibernate/metamodel/source/hbm/RootEntityBinder.java index 935d6ad72c..ac64f22633 100644 --- a/hibernate-core/src/main/java/org/hibernate/metamodel/source/hbm/RootEntityBinder.java +++ b/hibernate-core/src/main/java/org/hibernate/metamodel/source/hbm/RootEntityBinder.java @@ -33,6 +33,7 @@ import org.hibernate.mapping.RootClass; import org.hibernate.metamodel.binding.Caching; import org.hibernate.metamodel.binding.EntityBinding; import org.hibernate.metamodel.binding.SimpleAttributeBinding; +import org.hibernate.metamodel.domain.Entity; import org.hibernate.metamodel.relational.Column; import org.hibernate.metamodel.relational.Identifier; import org.hibernate.metamodel.relational.InLineView; @@ -52,6 +53,11 @@ class RootEntityBinder extends AbstractEntityBinder { } public void process(Element entityElement) { + String entityName = getHibernateMappingBinder().extractEntityName( entityElement ); + if ( entityName == null ) { + throw new MappingException( "Unable to determine entity name" ); + } + EntityBinding entityBinding = new EntityBinding(); basicEntityBinding( entityElement, entityBinding, null ); basicTableBinding( entityElement, entityBinding ); @@ -88,7 +94,7 @@ class RootEntityBinder extends AbstractEntityBinder { } private void basicTableBinding(Element entityElement, EntityBinding entityBinding) { - final Schema schema = getHibernateXmlBinder().getMetadata().getDatabase().getSchema( schemaName ); + final Schema schema = getHibernateXmlBinder().getMetadata().getDatabase().getSchema( getSchemaName() ); final String subSelect = HbmHelper.getSubselect( entityElement ); if ( subSelect != null ) { @@ -131,7 +137,7 @@ class RootEntityBinder extends AbstractEntityBinder { throw new InvalidMappingException( "Entity [" + entityBinding.getEntity().getName() + "] did not contain identifier mapping", - hibernateMappingBinder.getXmlDocument() + getHibernateMappingBinder().getXmlDocument() ); } @@ -143,7 +149,7 @@ class RootEntityBinder extends AbstractEntityBinder { SimpleAttributeBinding idBinding = entityBinding.makeSimpleAttributeBinding( attributeName ); - basicAttributeBinding( identifierElement, idBinding ); + bindSimpleAttribute( identifierElement, idBinding, entityBinding, attributeName ); // Handle the relational portion of the binding... Value idValue = processValues( identifierElement, entityBinding.getBaseTable(), attributeName ); @@ -253,7 +259,8 @@ class RootEntityBinder extends AbstractEntityBinder { entityBinding.getEntity().getOrCreateSingularAttribute( attributeName ); SimpleAttributeBinding discriminatorBinding = entityBinding.makeSimpleAttributeBinding( attributeName ); - basicAttributeBinding( discriminatorElement, discriminatorBinding ); + + bindSimpleAttribute( discriminatorElement, discriminatorBinding, entityBinding, attributeName ); if ( discriminatorBinding.getHibernateTypeDescriptor().getTypeName() == null ) { discriminatorBinding.getHibernateTypeDescriptor().setTypeName( "string" ); } @@ -291,7 +298,7 @@ class RootEntityBinder extends AbstractEntityBinder { } entityBinding.getEntity().getOrCreateSingularAttribute( explicitName ); SimpleAttributeBinding versionBinding = entityBinding.makeSimpleAttributeBinding( explicitName ); - basicAttributeBinding( versioningElement, versionBinding ); + bindSimpleAttribute( versioningElement, versionBinding, entityBinding, explicitName ); if ( versionBinding.getHibernateTypeDescriptor().getTypeName() == null ) { if ( isVersion ) { diff --git a/hibernate-core/src/main/java/org/hibernate/metamodel/source/util/DomHelper.java b/hibernate-core/src/main/java/org/hibernate/metamodel/source/util/DomHelper.java index 5d36a02260..268a40ec93 100644 --- a/hibernate-core/src/main/java/org/hibernate/metamodel/source/util/DomHelper.java +++ b/hibernate-core/src/main/java/org/hibernate/metamodel/source/util/DomHelper.java @@ -26,6 +26,8 @@ package org.hibernate.metamodel.source.util; import org.dom4j.Attribute; import org.dom4j.Element; +import org.hibernate.internal.util.ReflectHelper; + /** * Helper class for working with DOM documents. * @@ -40,8 +42,8 @@ public class DomHelper { } public static String extractAttributeValue(Element element, String attributeName, String defaultValue) { - Attribute attribute = element.attribute( attributeName ); - return attribute == null ? defaultValue : attribute.getValue(); + String attributeValue = ( element == null ? null : element.attributeValue( attributeName ) ); + return attributeValue == null ? defaultValue : attributeValue; } public static int extractIntAttributeValue(Element element, String attributeName) { @@ -49,8 +51,8 @@ public class DomHelper { } public static int extractIntAttributeValue(Element element, String attributeName, int defaultValue) { - Attribute attribute = element.attribute( attributeName ); - return attribute == null ? defaultValue : Integer.valueOf( attribute.getValue() ); + String attributeValue = ( element == null ? null : element.attributeValue( attributeName ) ); + return attributeValue == null ? defaultValue : Integer.valueOf( attributeValue ); } public static boolean extractBooleanAttributeValue(Element element, String attributeName) { @@ -58,7 +60,19 @@ public class DomHelper { } public static boolean extractBooleanAttributeValue(Element element, String attributeName, boolean defaultValue) { - Attribute attribute = element.attribute( attributeName ); - return attribute == null ? defaultValue : Boolean.valueOf( attribute.getValue() ); + String attributeValue = ( element == null ? null : element.attributeValue( attributeName ) ); + return attributeValue == null ? defaultValue : Boolean.valueOf( attributeValue ); } + + public static Class extractClassAttributeValue(Element element, String attributeName) + throws ClassNotFoundException { + String attributeValue = ( element == null ? null : element.attributeValue( attributeName ) ); + return ( + attributeValue == null ? + null : + ReflectHelper.classForName( attributeValue ) + ); + } + + } diff --git a/hibernate-core/src/test/java/org/hibernate/metamodel/binding/EntityWithCollection.hbm.xml b/hibernate-core/src/test/java/org/hibernate/metamodel/binding/EntityWithCollection.hbm.xml new file mode 100644 index 0000000000..7ae3b1b63e --- /dev/null +++ b/hibernate-core/src/test/java/org/hibernate/metamodel/binding/EntityWithCollection.hbm.xml @@ -0,0 +1,20 @@ + + + + + + + + + + + + + + + + + + diff --git a/hibernate-core/src/test/java/org/hibernate/metamodel/binding/EntityWithCollection.java b/hibernate-core/src/test/java/org/hibernate/metamodel/binding/EntityWithCollection.java new file mode 100644 index 0000000000..9ada02b520 --- /dev/null +++ b/hibernate-core/src/test/java/org/hibernate/metamodel/binding/EntityWithCollection.java @@ -0,0 +1,67 @@ +/* + * Hibernate, Relational Persistence for Idiomatic Java + * + * Copyright (c) 2011, Red Hat Inc. or third-party contributors as + * indicated by the @author tags or express copyright attribution + * statements applied by the authors. All third-party contributions are + * distributed under license by Red Hat Inc. + * + * This copyrighted material is made available to anyone wishing to use, modify, + * copy, or redistribute it subject to the terms and conditions of the GNU + * Lesser General Public License, as published by the Free Software Foundation. + * + * 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 Lesser General Public License + * for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this distribution; if not, write to: + * Free Software Foundation, Inc. + * 51 Franklin Street, Fifth Floor + * Boston, MA 02110-1301 USA + */ +package org.hibernate.metamodel.binding; + +import java.util.HashSet; +import java.util.Set; + +/** + * @author Gail Badner + */ +public class EntityWithCollection { + private Long id; + private String name; + Set otherNames = new HashSet(); + + public EntityWithCollection() { + } + + public EntityWithCollection(String name) { + this.name = name; + } + + public Long getId() { + return id; + } + + public void setId(Long id) { + this.id = id; + } + + public String getName() { + return name; + } + + public void setName(String name) { + this.name = name; + } + + public Set getOtherNames() { + return otherNames; + } + + public void setOtherNames(Set otherNames) { + this.otherNames = otherNames; + } +}