HHH-6168 : Create an AttributeBinding for many-to-one and implement DomainState and RelationalState for HBM XML

This commit is contained in:
Gail Badner 2011-04-26 10:37:28 -07:00
parent 000b647e43
commit 997dd00880
23 changed files with 855 additions and 324 deletions

View File

@ -25,14 +25,19 @@ package org.hibernate.metamodel.binding;
import java.util.ArrayList;
import java.util.Collections;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;
import org.hibernate.MappingException;
import org.hibernate.cfg.NamingStrategy;
import org.hibernate.metamodel.domain.Attribute;
import org.hibernate.metamodel.domain.MetaAttribute;
import org.hibernate.metamodel.relational.Column;
import org.hibernate.metamodel.relational.DerivedValue;
import org.hibernate.metamodel.relational.SimpleValue;
import org.hibernate.metamodel.relational.Size;
import org.hibernate.metamodel.relational.TableSpecification;
import org.hibernate.metamodel.relational.Tuple;
import org.hibernate.metamodel.relational.Value;
@ -57,6 +62,8 @@ public abstract class AbstractAttributeBinding implements AttributeBinding {
private final HibernateTypeDescriptor hibernateTypeDescriptor = new HibernateTypeDescriptor();
private final EntityBinding entityBinding;
private final Set<EntityReferencingAttributeBinding> entityReferencingAttributeBindings =
new HashSet<EntityReferencingAttributeBinding>();
private Attribute attribute;
private Value value;
@ -102,6 +109,72 @@ public abstract class AbstractAttributeBinding implements AttributeBinding {
this.attribute = attribute;
}
protected void initializeColumnValue(ColumnRelationalState state, boolean forceNonNullable, boolean forceUnique) {
Column columnValue = createColumn( state, forceNonNullable, forceUnique );
setValue( columnValue );
}
private Column createColumn(ColumnRelationalState state, boolean forceNonNullable, boolean forceUnique) {
final String explicitName = state.getExplicitColumnName();
final String logicalColumnName = state.getNamingStrategy().logicalColumnName( explicitName, getAttribute().getName() );
final TableSpecification table = getEntityBinding().getBaseTable();
final String columnName =
explicitName == null ?
state.getNamingStrategy().propertyToColumnName( getAttribute().getName() ) :
state.getNamingStrategy().columnName( explicitName );
// todo : find out the purpose of these logical bindings
// mappings.addColumnBinding( logicalColumnName, column, table );
Column columnValue = table.createColumn( columnName );
columnValue.getSize().initialize( state.getSize() );
columnValue.setNullable( ! forceNonNullable && state.isNullable() );
columnValue.setUnique( ! forceUnique && state.isUnique() );
columnValue.setCheckCondition( state.getCheckCondition() );
columnValue.setDefaultValue( state.getDefault() );
columnValue.setSqlType( state.getSqlType() );
columnValue.setWriteFragment( state.getCustomWriteFragment() );
columnValue.setReadFragment( state.getCustomReadFragment() );
columnValue.setComment( state.getComment() );
for ( String uniqueKey : state.getUniqueKeys() ) {
table.getOrCreateUniqueKey( uniqueKey ).addColumn( columnValue );
}
for ( String index : state.getIndexes() ) {
table.getOrCreateIndex( index ).addColumn( columnValue );
}
return columnValue;
}
public final <T extends DerivedRelationalState> void initializeDerivedValue(T state) {
value = createDerivedValue( state );
}
private DerivedValue createDerivedValue(DerivedRelationalState state) {
return getEntityBinding().getBaseTable().createDerivedValue( state.getFormula() );
}
public final void initializeSingleValue(SingleValueRelationalState state, boolean forceNonNullable, boolean forceUnique) {
value = createSingleValue( state, forceNonNullable, forceUnique );
}
protected SimpleValue createSingleValue(SingleValueRelationalState state, boolean forceNonNullable, boolean forceUnique) {
if ( state instanceof ColumnRelationalState ) {
return createColumn( ColumnRelationalState.class.cast( state ), forceNonNullable, forceUnique );
}
else if ( state instanceof DerivedRelationalState ) {
return createDerivedValue( DerivedRelationalState.class.cast( state ) );
}
else {
throw new MappingException( "unknown relational state:" + state.getClass().getName() );
}
}
protected final void initializeTupleValue(Set<SingleValueRelationalState> singleValueStates, boolean forceNonNullable, boolean forceUnique) {
Tuple tuple = getEntityBinding().getBaseTable().createTuple( "[" + getAttribute().getName() + "]" );
for ( SingleValueRelationalState singleValueState : singleValueStates ) {
tuple.addValue( createSingleValue( singleValueState, forceNonNullable, forceUnique ) );
}
value = tuple;
}
@Override
public Value getValue() {
return value;
@ -212,4 +285,39 @@ public abstract class AbstractAttributeBinding implements AttributeBinding {
protected void setLazy(boolean isLazy) {
this.isLazy = isLazy;
}
public void addEntityReferencingAttributeBinding(EntityReferencingAttributeBinding referencingAttributeBinding) {
entityReferencingAttributeBindings.add( referencingAttributeBinding );
}
public void validate() {
if ( ! entityReferencingAttributeBindings.isEmpty() ) {
// TODO; validate that this AttributeBinding can be a target of an entity reference
// (e.g., this attribute is the primary key or there is a unique-key)
// can a unique attribute be used as a target? if so, does it need to be non-null?
}
}
public static interface SingleValueRelationalState {}
public static interface ColumnRelationalState extends SimpleAttributeBinding.SingleValueRelationalState {
NamingStrategy getNamingStrategy();
String getExplicitColumnName();
boolean isUnique();
Size getSize();
boolean isNullable();
String getCheckCondition();
String getDefault();
String getSqlType();
String getCustomWriteFragment();
String getCustomReadFragment();
String getComment();
Set<String> getUniqueKeys();
Set<String> getIndexes();
}
public static interface DerivedRelationalState extends SingleValueRelationalState {
String getFormula();
}
}

View File

@ -102,4 +102,8 @@ public interface AttributeBinding {
public boolean[] getColumnInsertability();
public boolean isSimpleValue();
public boolean isLazy();
public void addEntityReferencingAttributeBinding(EntityReferencingAttributeBinding attributeBinding);
public void validate();
}

View File

@ -25,8 +25,11 @@ package org.hibernate.metamodel.binding;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Set;
import org.hibernate.MappingException;
import org.hibernate.engine.Versioning;
@ -41,6 +44,7 @@ import org.hibernate.metamodel.source.hbm.xml.mapping.XMLSqlDeleteElement;
import org.hibernate.metamodel.source.hbm.xml.mapping.XMLSqlInsertElement;
import org.hibernate.metamodel.source.hbm.xml.mapping.XMLSqlUpdateElement;
import org.hibernate.metamodel.source.hbm.xml.mapping.XMLSynchronizeElement;
import org.hibernate.metamodel.source.spi.MetadataImplementor;
import org.hibernate.metamodel.source.util.MappingHelper;
/**
@ -57,6 +61,8 @@ public class EntityBinding {
private TableSpecification baseTable;
private Map<String,AttributeBinding> attributeBindingMap = new HashMap<String, AttributeBinding>();
private Set<EntityReferencingAttributeBinding> entityReferencingAttributeBindings =
new HashSet<EntityReferencingAttributeBinding>();
private Caching caching;
@ -222,6 +228,10 @@ public class EntityBinding {
return attributeBindingMap.get( name );
}
public Iterable<EntityReferencingAttributeBinding> getEntityReferencingAttributeBindings() {
return entityReferencingAttributeBindings;
}
public SimpleAttributeBinding makeSimplePrimaryKeyAttributeBinding(String name) {
final SimpleAttributeBinding binding = makeSimpleAttributeBinding( name, true, true );
getEntityIdentifier().setValueBinding( binding );
@ -250,18 +260,34 @@ public class EntityBinding {
private SimpleAttributeBinding makeSimpleAttributeBinding(String name, boolean forceNonNullable, boolean forceUnique) {
final SimpleAttributeBinding binding = new SimpleAttributeBinding( this, forceNonNullable, forceUnique );
attributeBindingMap.put( name, binding );
registerAttributeBinding( name, binding );
binding.setAttribute( entity.getAttribute( name ) );
return binding;
}
public ManyToOneAttributeBinding makeManyToOneAttributeBinding(String name) {
final ManyToOneAttributeBinding binding = new ManyToOneAttributeBinding( this );
registerAttributeBinding( name, binding );
binding.setAttribute( entity.getAttribute( name ) );
return binding;
}
public BagBinding makeBagAttributeBinding(String name) {
final BagBinding binding = new BagBinding( this );
attributeBindingMap.put( name, binding );
registerAttributeBinding( name, binding );
binding.setAttribute( entity.getAttribute( name ) );
return binding;
}
private void registerAttributeBinding(String name, EntityReferencingAttributeBinding attributeBinding) {
entityReferencingAttributeBindings.add( attributeBinding );
registerAttributeBinding( name, (AttributeBinding) attributeBinding );
}
private void registerAttributeBinding(String name, AttributeBinding attributeBinding) {
attributeBindingMap.put( name, attributeBinding );
}
public Caching getCaching() {
return caching;
}

View File

@ -21,18 +21,19 @@
* 51 Franklin Street, Fifth Floor
* Boston, MA 02110-1301 USA
*/
package org.hibernate.metamodel.source.hbm;
package org.hibernate.metamodel.binding;
import org.hibernate.metamodel.source.Origin;
import org.hibernate.metamodel.source.hbm.xml.mapping.XMLHibernateMapping;
import org.hibernate.metamodel.source.internal.JaxbRoot;
import org.hibernate.metamodel.relational.Value;
/**
* TODO : javadoc
*
* @author Gail Badner
*/
public class HibernateMappingJaxbRoot extends JaxbRoot<XMLHibernateMapping> {
public HibernateMappingJaxbRoot(XMLHibernateMapping root, Origin origin) {
super(root, origin);
}
}
public interface EntityReferencingAttributeBinding extends AttributeBinding {
boolean isReferenceResolved();
String getReferencedEntityName();
String getReferencedAttributeName();
EntityBinding getReferencedEntityBinding();
void resolveReference(AttributeBinding attributeBinding);
}

View File

@ -0,0 +1,167 @@
/*
* 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 java.util.Iterator;
import org.hibernate.MappingException;
import org.hibernate.metamodel.relational.ForeignKey;
import org.hibernate.metamodel.relational.SimpleValue;
import org.hibernate.metamodel.relational.Column;
import org.hibernate.metamodel.source.Metadata;
/**
* TODO : javadoc
*
* @author Gail Badner
*/
public class ManyToOneAttributeBinding extends SingularAttributeBinding implements EntityReferencingAttributeBinding {
private boolean isLogicalOneToOne;
private boolean isPropertyReference;
private String foreignKeyName;
private String referencedAttributeName;
private String referencedEntityName;
private AttributeBinding referencedAttributeBinding;
private boolean ignoreNotFound;
public static interface DomainState extends SingularAttributeBinding.DomainState {
boolean isUnwrapProxy();
String getReferencedAttributeName();
String getReferencedEntityName();
boolean ignoreNotFound();
}
public static interface RelationalState extends SingleValueRelationalState {
boolean isLogicalOneToOne();
String getForeignKeyName();
}
ManyToOneAttributeBinding(EntityBinding entityBinding) {
super( entityBinding, false, false );
}
public final void initialize(DomainState state) {
super.initialize( state );
isPropertyReference = state.getReferencedAttributeName() != null;
referencedAttributeName = state.getReferencedAttributeName();
referencedEntityName = state.getReferencedEntityName();
}
public final void initialize(RelationalState state) {
super.initializeSingleValue( state );
isLogicalOneToOne = state.isLogicalOneToOne();
foreignKeyName = state.getForeignKeyName();
}
public final String getReferencedEntityName() {
return referencedEntityName;
}
public final String getReferencedAttributeName() {
if ( referencedAttributeName == null ) {
throw new IllegalStateException(
"Referenced attribute name is not available."
);
}
return referencedAttributeName;
}
public final boolean isReferenceResolved() {
return referencedAttributeBinding != null;
}
public final EntityBinding getReferencedEntityBinding() {
if ( ! isReferenceResolved() ) {
throw new IllegalStateException( "EntityBinding reference has not be referenced." );
}
// TODO: throw exception if referencedEntityBinding is null?
return referencedAttributeBinding.getEntityBinding();
}
public final void resolveReference(AttributeBinding referencedAttributeBinding) {
if ( ! referencedEntityName.equals( referencedAttributeBinding.getEntityBinding().getEntity().getName() ) ) {
throw new IllegalStateException(
"attempt to set EntityBinding with name: [" +
referencedAttributeBinding.getEntityBinding().getEntity().getName() +
"; entity name should be: " + referencedEntityName
);
}
if ( referencedAttributeName == null ) {
referencedAttributeName = referencedAttributeBinding.getAttribute().getName();
}
else if ( ! referencedAttributeName.equals( referencedAttributeBinding.getAttribute().getName() ) ) {
throw new IllegalStateException(
"Inconsistent attribute name; expected: " + referencedAttributeName +
"actual: " + referencedAttributeBinding.getAttribute().getName()
);
}
this.referencedAttributeBinding = referencedAttributeBinding;
buildForeignKey();
}
private void buildForeignKey() {
// TODO: move this stuff to relational model
ForeignKey foreignKey = getTable().createForeignKey( referencedAttributeBinding.getTable(), foreignKeyName );
Iterator<SimpleValue> referencingValueIterator = getValues().iterator();
Iterator<SimpleValue> targetValueIterator = referencedAttributeBinding.getValues().iterator();
while ( referencingValueIterator.hasNext() ) {
if ( ! targetValueIterator.hasNext() ) {
// TODO: improve this message
throw new MappingException( "number of values in many-to-one reference is greater than number of values in target" );
}
SimpleValue referencingValue = referencingValueIterator.next();
SimpleValue targetValue = targetValueIterator.next();
if ( Column.class.isInstance( referencingValue ) ) {
if ( ! Column.class.isInstance( targetValue ) ) {
// TODO improve this message
throw new MappingException( "referencing value is a column, but target is not a column" );
}
foreignKey.addColumnMapping( Column.class.cast( referencingValue ), Column.class.cast( targetValue ) );
}
else if ( Column.class.isInstance( targetValue ) ) {
// TODO: improve this message
throw new MappingException( "referencing value is not a column, but target is a column." );
}
}
if ( targetValueIterator.hasNext() ) {
throw new MappingException( "target value has more simple values than referencing value" );
}
}
public boolean isSimpleValue() {
return false;
}
public void validate() {
// can't check this until both the domain and relational states are initialized...
if ( getCascade() != null && getCascade().indexOf( "delete-orphan" ) >= 0 ) {
if ( ! isLogicalOneToOne ) {
throw new MappingException(
"many-to-one attribute [" + getAttribute().getName() + "] does not support orphan delete as it is not unique"
);
}
}
//TODO: validate that the entity reference is resolved
}
}

View File

@ -33,6 +33,7 @@ import org.hibernate.metamodel.domain.MetaAttribute;
*/
public interface MappingDefaults {
Map<String, MetaAttribute> getMappingMetas();
String getPackageName();
String getDefaultSchemaName();
String getDefaultCatalogName();
String getDefaultCascade();

View File

@ -67,7 +67,6 @@ public abstract class PluralAttributeBinding extends AbstractAttributeBinding {
boolean isEmbedded();
boolean isOptimisticLocked();
Class getCollectionPersisterClass();
String getTypeName();
java.util.Map getFilters();
java.util.Set getSynchronizedTables();
CustomSQL getCustomSQLInsert();
@ -105,7 +104,6 @@ public abstract class PluralAttributeBinding extends AbstractAttributeBinding {
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.Set<String> synchronizedTables = new HashSet<String>();
@ -145,7 +143,6 @@ public abstract class PluralAttributeBinding extends AbstractAttributeBinding {
embedded = state.isEmbedded();
optimisticLocked = state.isOptimisticLocked();
collectionPersisterClass = state.getCollectionPersisterClass();
typeName = state.getTypeName();
filters.putAll( state.getFilters() );
synchronizedTables.addAll( state.getSynchronizedTables() );
customSQLInsert = state.getCustomSQLInsert();
@ -257,10 +254,6 @@ public abstract class PluralAttributeBinding extends AbstractAttributeBinding {
return collectionPersisterClass;
}
public String getTypeName() {
return typeName;
}
public void addFilter(String name, String condition) {
filters.put( name, condition );
}

View File

@ -26,12 +26,10 @@ package org.hibernate.metamodel.binding;
import java.util.Set;
import org.hibernate.MappingException;
import org.hibernate.cfg.NamingStrategy;
import org.hibernate.mapping.PropertyGeneration;
import org.hibernate.metamodel.relational.Column;
import org.hibernate.metamodel.relational.DerivedValue;
import org.hibernate.metamodel.relational.SimpleValue;
import org.hibernate.metamodel.relational.Size;
import org.hibernate.metamodel.relational.TableSpecification;
import org.hibernate.metamodel.relational.Tuple;
@ -45,45 +43,6 @@ public class SimpleAttributeBinding extends SingularAttributeBinding {
public PropertyGeneration getPropertyGeneration();
}
public static interface SingleValueRelationalState {
}
public static interface ColumnRelationalState extends SingleValueRelationalState {
NamingStrategy getNamingStrategy();
String getExplicitColumnName();
boolean isUnique();
Size getSize();
boolean isNullable();
String getCheckCondition();
String getDefault();
String getSqlType();
String getCustomWriteFragment();
String getCustomReadFragment();
String getComment();
Set<String> getUniqueKeys();
Set<String> getIndexes();
}
public static interface DerivedRelationalState extends SingleValueRelationalState {
String getFormula();
}
public static interface TupleRelationalState {
Set<SingleValueRelationalState> getSingleValueRelationalStates();
}
private PropertyGeneration generation;
SimpleAttributeBinding(EntityBinding entityBinding, boolean forceNonNullable, boolean forceUnique) {
@ -95,80 +54,20 @@ public class SimpleAttributeBinding extends SingularAttributeBinding {
generation = state.getPropertyGeneration();
}
public final void initializeColumnValue(ColumnRelationalState state) {
Column columnValue = createColumn( state );
setValue( columnValue );
}
private Column createColumn(ColumnRelationalState state) {
final String explicitName = state.getExplicitColumnName();
final String logicalColumnName = state.getNamingStrategy()
.logicalColumnName( explicitName, getAttribute().getName() );
final TableSpecification table = getEntityBinding().getBaseTable();
final String columnName =
explicitName == null ?
state.getNamingStrategy().propertyToColumnName( getAttribute().getName() ) :
state.getNamingStrategy().columnName( explicitName );
// todo : find out the purpose of these logical bindings
// mappings.addColumnBinding( logicalColumnName, column, table );
Column columnValue = table.createColumn( columnName );
columnValue.getSize().initialize( state.getSize() );
columnValue.setNullable( !forceNonNullable() && state.isNullable() );
columnValue.setUnique( !forceUnique() && state.isUnique() );
columnValue.setCheckCondition( state.getCheckCondition() );
columnValue.setDefaultValue( state.getDefault() );
columnValue.setSqlType( state.getSqlType() );
columnValue.setWriteFragment( state.getCustomWriteFragment() );
columnValue.setReadFragment( state.getCustomReadFragment() );
columnValue.setComment( state.getComment() );
for ( String uniqueKey : state.getUniqueKeys() ) {
table.getOrCreateUniqueKey( uniqueKey ).addColumn( columnValue );
}
for ( String index : state.getIndexes() ) {
table.getOrCreateIndex( index ).addColumn( columnValue );
}
return columnValue;
}
private boolean isUnique(ColumnRelationalState state) {
return isPrimaryKey() || state.isUnique();
}
public final <T extends DerivedRelationalState> void initializeDerivedValue(T state) {
setValue( createDerivedValue( state ) );
}
private DerivedValue createDerivedValue(DerivedRelationalState state) {
return getEntityBinding().getBaseTable().createDerivedValue( state.getFormula() );
}
public final void initializeTupleValue(TupleRelationalState state) {
if ( state.getSingleValueRelationalStates().size() == 0 ) {
throw new MappingException( "Tuple state does not contain any values." );
}
if ( state.getSingleValueRelationalStates().size() == 1 ) {
setValue( createSingleValue( state.getSingleValueRelationalStates().iterator().next() ) );
initializeSingleValue( state.getSingleValueRelationalStates().iterator().next() );
}
else {
Tuple tuple = getEntityBinding().getBaseTable().createTuple( "[" + getAttribute().getName() + "]" );
for ( SingleValueRelationalState singleValueState : state.getSingleValueRelationalStates() ) {
tuple.addValue( createSingleValue( singleValueState ) );
}
setValue( tuple );
initializeTupleValue( state.getSingleValueRelationalStates() );
}
}
private SimpleValue createSingleValue(SingleValueRelationalState state) {
if ( state instanceof ColumnRelationalState ) {
return createColumn( ColumnRelationalState.class.cast( state ) );
}
else if ( state instanceof DerivedRelationalState ) {
return createDerivedValue( DerivedRelationalState.class.cast( state ) );
}
else {
throw new MappingException( "unknown relational state:" + state.getClass().getName() );
}
private boolean isUnique(ColumnRelationalState state) {
return isPrimaryKey() || state.isUnique();
}
@Override
@ -183,4 +82,8 @@ public class SimpleAttributeBinding extends SingularAttributeBinding {
public PropertyGeneration getGeneration() {
return generation;
}
public static interface TupleRelationalState {
Set<SingleValueRelationalState> getSingleValueRelationalStates();
}
}

View File

@ -23,10 +23,12 @@
*/
package org.hibernate.metamodel.binding;
import org.dom4j.Element;
import java.util.Set;
import org.hibernate.metamodel.domain.Attribute;
import org.hibernate.metamodel.source.util.DomHelper;
import org.hibernate.MappingException;
import org.hibernate.metamodel.relational.DerivedValue;
import org.hibernate.metamodel.relational.SimpleValue;
import org.hibernate.metamodel.relational.Tuple;
/**
* TODO : javadoc
@ -62,6 +64,18 @@ public abstract class SingularAttributeBinding extends AbstractAttributeBinding
unsavedValue = state.getUnsavedValue();
}
public final void initializeColumnValue(ColumnRelationalState state) {
initializeColumnValue( state, forceNonNullable, forceUnique );
}
public final void initializeSingleValue(SingleValueRelationalState state) {
initializeSingleValue( state, forceNonNullable, forceUnique );
}
protected void initializeTupleValue(Set<SingleValueRelationalState> singleValueStates) {
initializeTupleValue( singleValueStates, forceNonNullable, forceUnique );
}
public boolean isInsertable() {
return insertable;
}

View File

@ -23,6 +23,11 @@
*/
package org.hibernate.metamodel.relational;
import java.util.Set;
import org.hibernate.cfg.NamingStrategy;
import org.hibernate.metamodel.binding.SimpleAttributeBinding;
/**
* Models a physical column
*

View File

@ -37,6 +37,7 @@ import org.hibernate.internal.util.StringHelper;
import org.hibernate.metamodel.binding.AttributeBinding;
import org.hibernate.metamodel.binding.BagBinding;
import org.hibernate.metamodel.binding.EntityBinding;
import org.hibernate.metamodel.binding.ManyToOneAttributeBinding;
import org.hibernate.metamodel.binding.PluralAttributeBinding;
import org.hibernate.metamodel.binding.SimpleAttributeBinding;
import org.hibernate.metamodel.domain.Entity;
@ -47,36 +48,13 @@ import org.hibernate.metamodel.relational.Schema;
import org.hibernate.metamodel.relational.Table;
import org.hibernate.metamodel.relational.TableSpecification;
import org.hibernate.metamodel.relational.UniqueKey;
import org.hibernate.metamodel.source.hbm.state.domain.HbmManyToOneAttributeDomainState;
import org.hibernate.metamodel.source.hbm.state.relational.HbmManyToOneRelationalStateContainer;
import org.hibernate.metamodel.source.hbm.xml.mapping.*;
import org.hibernate.metamodel.source.internal.MetadataImpl;
import org.hibernate.metamodel.source.hbm.state.domain.HbmPluralAttributeDomainState;
import org.hibernate.metamodel.source.hbm.state.domain.HbmSimpleAttributeDomainState;
import org.hibernate.metamodel.source.hbm.state.relational.HbmSimpleValueRelationalStateContainer;
import org.hibernate.metamodel.source.hbm.xml.mapping.XMLAnyElement;
import org.hibernate.metamodel.source.hbm.xml.mapping.XMLBagElement;
import org.hibernate.metamodel.source.hbm.xml.mapping.XMLComponentElement;
import org.hibernate.metamodel.source.hbm.xml.mapping.XMLDynamicComponentElement;
import org.hibernate.metamodel.source.hbm.xml.mapping.XMLFilterElement;
import org.hibernate.metamodel.source.hbm.xml.mapping.XMLHibernateMapping.XMLClass;
import org.hibernate.metamodel.source.hbm.xml.mapping.XMLHibernateMapping.XMLClass.XMLDiscriminator;
import org.hibernate.metamodel.source.hbm.xml.mapping.XMLHibernateMapping.XMLClass.XMLId;
import org.hibernate.metamodel.source.hbm.xml.mapping.XMLHibernateMapping.XMLClass.XMLTimestamp;
import org.hibernate.metamodel.source.hbm.xml.mapping.XMLHibernateMapping.XMLClass.XMLVersion;
import org.hibernate.metamodel.source.hbm.xml.mapping.XMLIdbagElement;
import org.hibernate.metamodel.source.hbm.xml.mapping.XMLJoinElement;
import org.hibernate.metamodel.source.hbm.xml.mapping.XMLJoinedSubclassElement;
import org.hibernate.metamodel.source.hbm.xml.mapping.XMLListElement;
import org.hibernate.metamodel.source.hbm.xml.mapping.XMLManyToOneElement;
import org.hibernate.metamodel.source.hbm.xml.mapping.XMLMapElement;
import org.hibernate.metamodel.source.hbm.xml.mapping.XMLOneToOneElement;
import org.hibernate.metamodel.source.hbm.xml.mapping.XMLPropertiesElement;
import org.hibernate.metamodel.source.hbm.xml.mapping.XMLPropertyElement;
import org.hibernate.metamodel.source.hbm.xml.mapping.XMLQueryElement;
import org.hibernate.metamodel.source.hbm.xml.mapping.XMLResultsetElement;
import org.hibernate.metamodel.source.hbm.xml.mapping.XMLSetElement;
import org.hibernate.metamodel.source.hbm.xml.mapping.XMLSqlQueryElement;
import org.hibernate.metamodel.source.hbm.xml.mapping.XMLSubclassElement;
import org.hibernate.metamodel.source.hbm.xml.mapping.XMLTuplizerElement;
import org.hibernate.metamodel.source.hbm.xml.mapping.XMLUnionSubclassElement;
/**
* TODO : javadoc
@ -88,7 +66,7 @@ abstract class AbstractEntityBinder {
private final Schema.Name schemaName;
AbstractEntityBinder(HibernateMappingBinder hibernateMappingBinder,
XMLClass entityClazz) {
XMLHibernateMapping.XMLClass entityClazz) {
this.hibernateMappingBinder = hibernateMappingBinder;
this.schemaName = new Schema.Name(
( entityClazz.getSchema() == null ?
@ -119,7 +97,7 @@ abstract class AbstractEntityBinder {
return getMetadata().getNamingStrategy();
}
protected void basicEntityBinding(XMLClass entityClazz,
protected void basicEntityBinding(XMLHibernateMapping.XMLClass entityClazz,
EntityBinding entityBinding,
Hierarchical superType) {
entityBinding.fromHbmXml(
@ -151,7 +129,7 @@ abstract class AbstractEntityBinder {
return hibernateMappingBinder.getDefaultAccess();
}
private void bindPojoRepresentation(XMLClass entityClazz,
private void bindPojoRepresentation(XMLHibernateMapping.XMLClass entityClazz,
EntityBinding entityBinding) {
String className = hibernateMappingBinder.getClassName( entityClazz.getName() );
String proxyName = hibernateMappingBinder.getClassName( entityClazz.getProxy() );
@ -172,7 +150,7 @@ abstract class AbstractEntityBinder {
}
}
private void bindDom4jRepresentation(XMLClass entityClazz,
private void bindDom4jRepresentation(XMLHibernateMapping.XMLClass entityClazz,
EntityBinding entityBinding) {
String nodeName = entityClazz.getNode();
if ( nodeName == null ) {
@ -186,7 +164,7 @@ abstract class AbstractEntityBinder {
}
}
private void bindMapRepresentation(XMLClass entityClazz,
private void bindMapRepresentation(XMLHibernateMapping.XMLClass entityClazz,
EntityBinding entityBinding) {
XMLTuplizerElement tuplizer = locateTuplizerDefinition( entityClazz, EntityMode.MAP );
if ( tuplizer != null ) {
@ -202,7 +180,7 @@ abstract class AbstractEntityBinder {
*
* @return The tuplizer element, or null.
*/
private static XMLTuplizerElement locateTuplizerDefinition(XMLClass container,
private static XMLTuplizerElement locateTuplizerDefinition(XMLHibernateMapping.XMLClass container,
EntityMode entityMode) {
for ( XMLTuplizerElement tuplizer : container.getTuplizer() ) {
if ( entityMode.toString().equals( tuplizer.getEntityMode() ) ) {
@ -235,7 +213,7 @@ abstract class AbstractEntityBinder {
}
protected String getClassTableName(
XMLClass entityClazz,
XMLHibernateMapping.XMLClass entityClazz,
EntityBinding entityBinding,
Table denormalizedSuperTable) {
final String entityName = entityBinding.getEntity().getName();
@ -254,7 +232,7 @@ abstract class AbstractEntityBinder {
return physicalTableName;
}
protected void buildAttributeBindings(XMLClass entityClazz,
protected void buildAttributeBindings(XMLHibernateMapping.XMLClass entityClazz,
EntityBinding entityBinding) {
// null = UniqueKey (we are not binding a natural-id mapping)
// true = mutable, by default properties are mutable
@ -273,7 +251,7 @@ abstract class AbstractEntityBinder {
* @param nullable
*/
protected void buildAttributeBindings(
XMLClass entityClazz,
XMLHibernateMapping.XMLClass entityClazz,
EntityBinding entityBinding,
UniqueKey uniqueKey,
boolean mutable,
@ -323,6 +301,10 @@ abstract class AbstractEntityBinder {
//hibernateMappingBinder.getHibernateXmlBinder().getMetadata().addCollection( attributeBinding );
}
else if ( XMLManyToOneElement.class.isInstance( attribute ) ) {
XMLManyToOneElement manyToOne = XMLManyToOneElement.class.cast( attribute );
ManyToOneAttributeBinding manyToOneBinding = entityBinding.makeManyToOneAttributeBinding( manyToOne.getName() );
bindManyToOne( manyToOne, manyToOneBinding, entityBinding );
attributeBinding = manyToOneBinding;
// todo : implement
// value = new ManyToOne( mappings, table );
// bindManyToOne( subElement, (ManyToOne) value, propertyName, nullable, mappings );
@ -440,7 +422,7 @@ PrimitiveArray
}
protected void bindSimpleAttribute(XMLId id,
protected void bindSimpleAttribute(XMLHibernateMapping.XMLClass.XMLId id,
SimpleAttributeBinding attributeBinding,
EntityBinding entityBinding,
String attributeName) {
@ -468,7 +450,7 @@ PrimitiveArray
}
}
protected void bindSimpleAttribute(XMLDiscriminator discriminator,
protected void bindSimpleAttribute(XMLHibernateMapping.XMLClass.XMLDiscriminator discriminator,
SimpleAttributeBinding attributeBinding,
EntityBinding entityBinding,
String attributeName) {
@ -496,7 +478,7 @@ PrimitiveArray
}
}
protected void bindSimpleAttribute(XMLVersion version,
protected void bindSimpleAttribute(XMLHibernateMapping.XMLClass.XMLVersion version,
SimpleAttributeBinding attributeBinding,
EntityBinding entityBinding,
String attributeName) {
@ -524,7 +506,7 @@ PrimitiveArray
}
}
protected void bindSimpleAttribute(XMLTimestamp timestamp,
protected void bindSimpleAttribute(XMLHibernateMapping.XMLClass.XMLTimestamp timestamp,
SimpleAttributeBinding attributeBinding,
EntityBinding entityBinding,
String attributeName) {
@ -603,6 +585,33 @@ PrimitiveArray
}
}
private void bindManyToOne(XMLManyToOneElement manyToOne,
ManyToOneAttributeBinding attributeBinding,
EntityBinding entityBinding) {
if ( attributeBinding.getAttribute() == null ) {
attributeBinding.initialize(
new HbmManyToOneAttributeDomainState(
hibernateMappingBinder,
entityBinding.getEntity().getOrCreateSingularAttribute( manyToOne.getName() ),
entityBinding.getMetaAttributes(),
manyToOne
)
);
}
if ( attributeBinding.getValue() == null ) {
// relational model has not been bound yet
// boolean (true here) indicates that by default column names should be guessed
attributeBinding.initialize(
new HbmManyToOneRelationalStateContainer(
getHibernateMappingBinder(),
true,
manyToOne
)
);
}
}
// private static Property createProperty(
// final Value value,
// final String propertyName,

View File

@ -95,8 +95,11 @@ public class HbmHelper {
}
public static String extractEntityName( XMLClass entityClazz, String unqualifiedPackageName) {
String entityName = entityClazz.getEntityName();
return entityName == null ? getClassName( entityClazz.getName(), unqualifiedPackageName ) : entityName;
return extractEntityName( entityClazz.getEntityName(), entityClazz.getName(), unqualifiedPackageName );
}
public static String extractEntityName( String entityName, String entityClassName, String unqualifiedPackageName) {
return entityName == null ? getClassName( entityClassName, unqualifiedPackageName ) : entityName;
}
public static String getClassName(Attribute att, String unqualifiedPackageName) {

View File

@ -119,7 +119,7 @@ class HibernateMappingBinder implements MappingDefaults {
return hibernateXmlBinder.getMetadata().getNamingStrategy();
}
String getPackageName() {
public String getPackageName() {
return packageName;
}

View File

@ -27,17 +27,9 @@ import java.util.Map;
import org.hibernate.metamodel.binding.AbstractAttributeBinding;
import org.hibernate.metamodel.binding.EntityBinding;
import org.hibernate.metamodel.binding.HibernateTypeDescriptor;
import org.hibernate.metamodel.binding.MappingDefaults;
import org.hibernate.metamodel.domain.Attribute;
import org.hibernate.metamodel.domain.MetaAttribute;
import org.hibernate.metamodel.source.hbm.HbmHelper;
import org.hibernate.metamodel.source.hbm.xml.mapping.XMLBagElement;
import org.hibernate.metamodel.source.hbm.xml.mapping.XMLHibernateMapping.XMLClass.XMLDiscriminator;
import org.hibernate.metamodel.source.hbm.xml.mapping.XMLHibernateMapping.XMLClass.XMLId;
import org.hibernate.metamodel.source.hbm.xml.mapping.XMLHibernateMapping.XMLClass.XMLTimestamp;
import org.hibernate.metamodel.source.hbm.xml.mapping.XMLHibernateMapping.XMLClass.XMLVersion;
import org.hibernate.metamodel.source.hbm.xml.mapping.XMLPropertyElement;
import org.hibernate.metamodel.source.util.MappingHelper;
/**
@ -46,120 +38,23 @@ import org.hibernate.metamodel.source.util.MappingHelper;
public abstract class AbstractHbmAttributeDomainState implements AbstractAttributeBinding.DomainState {
private final MappingDefaults defaults;
private final Attribute attribute;
private final HibernateTypeDescriptor hibernateTypeDescriptor;
private final String accessorName;
private final String cascade;
private final boolean isOptimisticLockable;
private final String nodeName;
private final String accessorName;
private final boolean isOptimisticLockable;
private final Map<String, MetaAttribute> metaAttributes;
public AbstractHbmAttributeDomainState(MappingDefaults defaults,
Attribute attribute,
Map<String, MetaAttribute> entityMetaAttributes,
XMLId id) {
String nodeName,
Map<String, MetaAttribute> metaAttributes,
String accessorName,
boolean isOptimisticLockable) {
this.defaults = defaults;
this.attribute = attribute;
this.hibernateTypeDescriptor = new HibernateTypeDescriptor();
this.hibernateTypeDescriptor.setTypeName( id.getTypeAttribute() );
this.accessorName = HbmHelper.getPropertyAccessorName(
id.getAccess(), isEmbedded(), defaults.getDefaultAccess()
);
this.nodeName = MappingHelper.getStringValue( id.getNode(), attribute.getName() );
this.metaAttributes = HbmHelper.extractMetas( id.getMeta(), entityMetaAttributes );
this.cascade = defaults.getDefaultCascade();
this.isOptimisticLockable = true;
}
public AbstractHbmAttributeDomainState(MappingDefaults defaults,
Attribute attribute,
XMLDiscriminator discriminator) {
this.defaults = defaults;
this.attribute = attribute;
this.hibernateTypeDescriptor = new HibernateTypeDescriptor();
this.hibernateTypeDescriptor.setTypeName( discriminator.getType() == null ? "string" : discriminator.getType() );
// the following does not apply to discriminators
this.accessorName = null;
this.nodeName = null;
this.metaAttributes = null;
this.cascade = null;
this.isOptimisticLockable = true;
}
public AbstractHbmAttributeDomainState(MappingDefaults defaults,
Attribute attribute,
Map<String, MetaAttribute> entityMetaAttributes,
XMLVersion version) {
this.defaults = defaults;
this.attribute = attribute;
this.hibernateTypeDescriptor = new HibernateTypeDescriptor();
this.hibernateTypeDescriptor.setTypeName( version.getType() == null ? "integer" : version.getType() );
// the following does not apply to discriminators
this.accessorName = HbmHelper.getPropertyAccessorName(
version.getAccess(), isEmbedded(), defaults.getDefaultAccess()
);
this.nodeName = version.getNode();
this.metaAttributes = HbmHelper.extractMetas( version.getMeta(), entityMetaAttributes );
this.cascade = null;
this.isOptimisticLockable = true;
}
public AbstractHbmAttributeDomainState(MappingDefaults defaults,
Attribute attribute,
Map<String, MetaAttribute> entityMetaAttributes,
XMLTimestamp timestamp) {
this.defaults = defaults;
this.attribute = attribute;
this.hibernateTypeDescriptor = new HibernateTypeDescriptor();
// Timestamp.getType() is not defined
this.hibernateTypeDescriptor.setTypeName( "db".equals( timestamp.getSource() ) ? "dbtimestamp" : "timestamp" );
// the following does not apply to discriminators
this.accessorName = HbmHelper.getPropertyAccessorName(
timestamp.getAccess(), isEmbedded(), defaults.getDefaultAccess()
);
this.nodeName = timestamp.getNode();
this.metaAttributes = HbmHelper.extractMetas( timestamp.getMeta(), entityMetaAttributes );
this.cascade = null;
this.isOptimisticLockable = true;
}
public AbstractHbmAttributeDomainState(MappingDefaults defaults,
Attribute attribute,
Map<String, MetaAttribute> entityMetaAttributes,
XMLPropertyElement property) {
this.defaults = defaults;
this.attribute = attribute;
this.hibernateTypeDescriptor = new HibernateTypeDescriptor();
this.hibernateTypeDescriptor.setTypeName( property.getTypeAttribute() );
this.accessorName = HbmHelper.getPropertyAccessorName(
property.getAccess(), isEmbedded(), defaults.getDefaultAccess()
);
this.nodeName = MappingHelper.getStringValue( property.getNode(), attribute.getName() );
this.metaAttributes = HbmHelper.extractMetas( property.getMeta(), entityMetaAttributes );
this.cascade = defaults.getDefaultCascade();
this.isOptimisticLockable = property.isOptimisticLock();
}
public AbstractHbmAttributeDomainState(MappingDefaults defaults,
Attribute attribute,
Map<String, MetaAttribute> entityMetaAttributes,
XMLBagElement collection) {
this.defaults = defaults;
this.attribute = attribute;
this.hibernateTypeDescriptor = new HibernateTypeDescriptor();
// TODO: is collection.getCollectionType() correct here?
this.hibernateTypeDescriptor.setTypeName( collection.getCollectionType() );
this.accessorName = HbmHelper.getPropertyAccessorName(
collection.getAccess(), isEmbedded(), defaults.getDefaultAccess()
);
this.nodeName = MappingHelper.getStringValue( collection.getNode(), attribute.getName() );
this.metaAttributes = HbmHelper.extractMetas( collection.getMeta(), entityMetaAttributes );
this.cascade = defaults.getDefaultCascade();
this.isOptimisticLockable = collection.isOptimisticLock();
this.nodeName = MappingHelper.getStringValue( nodeName, attribute.getName() );
this.metaAttributes = metaAttributes;
this.accessorName = accessorName;
this.isOptimisticLockable = isOptimisticLockable;
}
protected final MappingDefaults getDefaults() {
@ -168,22 +63,14 @@ public abstract class AbstractHbmAttributeDomainState implements AbstractAttribu
public final Attribute getAttribute() {
return attribute;
}
public final HibernateTypeDescriptor getHibernateTypeDescriptor() {
return hibernateTypeDescriptor;
}
public final String getPropertyAccessorName() {
return accessorName;
}
protected abstract boolean isEmbedded();
public final boolean isAlternateUniqueKey() {
//TODO: implement
return false;
}
public final String getCascade() {
return cascade;
}
public final boolean isOptimisticLockable() {
return isOptimisticLockable;
}

View File

@ -0,0 +1,168 @@
/*
* 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.source.hbm.state.domain;
import java.util.Map;
import org.dom4j.Attribute;
import org.dom4j.Element;
import org.hibernate.FetchMode;
import org.hibernate.MappingException;
import org.hibernate.cfg.HbmBinder;
import org.hibernate.cfg.Mappings;
import org.hibernate.mapping.Fetchable;
import org.hibernate.mapping.OneToOne;
import org.hibernate.mapping.PropertyGeneration;
import org.hibernate.metamodel.binding.EntityBinding;
import org.hibernate.metamodel.binding.HibernateTypeDescriptor;
import org.hibernate.metamodel.binding.ManyToOneAttributeBinding;
import org.hibernate.metamodel.binding.MappingDefaults;
import org.hibernate.metamodel.binding.SimpleAttributeBinding;
import org.hibernate.metamodel.domain.MetaAttribute;
import org.hibernate.metamodel.source.Metadata;
import org.hibernate.metamodel.source.hbm.HbmHelper;
import org.hibernate.metamodel.source.hbm.xml.mapping.XMLManyToOneElement;
import org.hibernate.metamodel.source.util.DomHelper;
import org.hibernate.metamodel.source.util.MappingHelper;
import org.hibernate.tuple.component.Dom4jComponentTuplizer;
/**
* @author Gail Badner
*/
public class HbmManyToOneAttributeDomainState
extends AbstractHbmAttributeDomainState
implements ManyToOneAttributeBinding.DomainState {
private final HibernateTypeDescriptor hibernateTypeDescriptor = new HibernateTypeDescriptor();
private final XMLManyToOneElement manyToOne;
private final String cascade;
public HbmManyToOneAttributeDomainState(MappingDefaults defaults,
org.hibernate.metamodel.domain.Attribute attribute,
Map<String, MetaAttribute> entityMetaAttributes,
XMLManyToOneElement manyToOne) {
super(
defaults,
attribute,
manyToOne.getNode(),
HbmHelper.extractMetas( manyToOne.getMeta(), entityMetaAttributes ),
HbmHelper.getPropertyAccessorName( manyToOne.getAccess(), manyToOne.isEmbedXml(), defaults.getDefaultAccess() ),
manyToOne.isOptimisticLock()
);
this.hibernateTypeDescriptor.setTypeName( getReferencedEntityName() );
this.manyToOne = manyToOne;
this.cascade = MappingHelper.getStringValue( manyToOne.getCascade(), defaults.getDefaultCascade() );
}
// TODO: is this needed???
protected boolean isEmbedded() {
return MappingHelper.getBooleanValue( manyToOne.isEmbedXml(), true );
}
public HibernateTypeDescriptor getHibernateTypeDescriptor() {
return hibernateTypeDescriptor;
}
// same as for plural attributes...
public FetchMode getFetchMode() {
FetchMode fetchMode;
if ( manyToOne.getFetch() != null ) {
fetchMode = "join".equals( manyToOne.getFetch() ) ? FetchMode.JOIN : FetchMode.SELECT;
}
else {
String jfNodeValue = ( manyToOne.getOuterJoin().value() == null ? "auto" : manyToOne.getOuterJoin().value() );
if ( "auto".equals( jfNodeValue ) ) {
fetchMode = FetchMode.DEFAULT;
}
else if ( "true".equals( jfNodeValue ) ) {
fetchMode = FetchMode.JOIN;
}
else {
fetchMode = FetchMode.SELECT;
}
}
return fetchMode;
}
public boolean isLazy() {
return manyToOne.getLazy() == null ||
isUnwrapProxy() ||
manyToOne.getLazy().equals( "proxy" );
//TODO: better to degrade to lazy="false" if uninstrumented
}
public boolean isUnwrapProxy() {
return "no-proxy".equals( manyToOne.getLazy() );
}
public String getReferencedAttributeName() {
return manyToOne.getPropertyRef();
}
public String getReferencedEntityName() {
String entityName = manyToOne.getEntityName();
return entityName == null ?
HbmHelper.getClassName( manyToOne.getClazz(), getDefaults().getPackageName() ) :
entityName.intern();
}
public String getCascade() {
return MappingHelper.getStringValue( manyToOne.getCascade(), getDefaults().getDefaultCascade() );
}
public boolean ignoreNotFound() {
return "ignore".equals( manyToOne.getNotFound() );
}
/*
void junk() {
if( getReferencedPropertyName() != null && ! ignoreNotFound() ) {
mappings.addSecondPass( new ManyToOneSecondPass(manyToOne) );
}
}
*/
public boolean isInsertable() {
return MappingHelper.getBooleanValue( manyToOne.isInsert(), true );
}
public boolean isUpdateable() {
return MappingHelper.getBooleanValue( manyToOne.isUnique(), true );
}
public String getForeignkeyName() {
return manyToOne.getForeignKey();
}
public boolean isKeyCasadeDeleteEnabled() {
//TODO: implement
return false;
}
public String getUnsavedValue() {
//TODO: implement
return null;
}
}

View File

@ -33,6 +33,7 @@ import org.hibernate.MappingException;
import org.hibernate.metamodel.binding.CollectionElement;
import org.hibernate.metamodel.binding.CustomSQL;
import org.hibernate.metamodel.binding.ElementCollectionElement;
import org.hibernate.metamodel.binding.HibernateTypeDescriptor;
import org.hibernate.metamodel.binding.MappingDefaults;
import org.hibernate.metamodel.binding.PluralAttributeBinding;
import org.hibernate.metamodel.domain.Attribute;
@ -53,13 +54,42 @@ import org.hibernate.metamodel.source.util.MappingHelper;
*/
public class HbmPluralAttributeDomainState extends AbstractHbmAttributeDomainState implements PluralAttributeBinding.DomainState {
private final XMLBagElement collection;
private final HibernateTypeDescriptor hibernateTypeDescriptor = new HibernateTypeDescriptor();
private final String cascade;
public HbmPluralAttributeDomainState(MappingDefaults defaults,
XMLBagElement collection,
Map<String, MetaAttribute> entityMetaAttributes,
Attribute attribute) {
super( defaults, attribute, entityMetaAttributes, collection );
super(
defaults,
attribute,
collection.getNode(),
HbmHelper.extractMetas( collection.getMeta(), entityMetaAttributes ),
HbmHelper.getPropertyAccessorName( collection.getAccess(), collection.isEmbedXml(), defaults.getDefaultAccess() ),
collection.isOptimisticLock()
);
this.collection = collection;
// TODO: is collection.getCollectionType() correct here?
this.hibernateTypeDescriptor.setTypeName( collection.getCollectionType() );
this.cascade = MappingHelper.getStringValue( collection.getCascade(), defaults.getDefaultCascade() );
//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 );
}
*/
//}
//TODO: fix this!!!
this.hibernateTypeDescriptor.setTypeName( collection.getCollectionType() );
}
public FetchMode getFetchMode() {
@ -174,24 +204,9 @@ public class HbmPluralAttributeDomainState extends AbstractHbmAttributeDomainSta
+ collection.getPersister() );
}
}
public String getTypeName() {
// TODO: does this go here???
//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 );
}
*/
//}
return null;
public HibernateTypeDescriptor getHibernateTypeDescriptor() {
return hibernateTypeDescriptor;
}
public java.util.Map getFilters() {
@ -257,6 +272,10 @@ public class HbmPluralAttributeDomainState extends AbstractHbmAttributeDomainSta
collection.getLoader().getQueryRef();
}
public String getCascade() {
return cascade;
}
public boolean isKeyCasadeDeleteEnabled() {
//TODO: implement
return false;

View File

@ -27,9 +27,11 @@ import java.util.Map;
import org.hibernate.MappingException;
import org.hibernate.mapping.PropertyGeneration;
import org.hibernate.metamodel.binding.HibernateTypeDescriptor;
import org.hibernate.metamodel.binding.MappingDefaults;
import org.hibernate.metamodel.binding.SimpleAttributeBinding;
import org.hibernate.metamodel.domain.MetaAttribute;
import org.hibernate.metamodel.source.hbm.HbmHelper;
import org.hibernate.metamodel.source.hbm.xml.mapping.XMLHibernateMapping.XMLClass.XMLDiscriminator;
import org.hibernate.metamodel.source.hbm.xml.mapping.XMLHibernateMapping.XMLClass.XMLId;
import org.hibernate.metamodel.source.hbm.xml.mapping.XMLHibernateMapping.XMLClass.XMLTimestamp;
@ -41,6 +43,7 @@ import org.hibernate.metamodel.source.util.MappingHelper;
* @author Gail Badner
*/
public class HbmSimpleAttributeDomainState extends AbstractHbmAttributeDomainState implements SimpleAttributeBinding.DomainState {
private final HibernateTypeDescriptor hibernateTypeDescriptor = new HibernateTypeDescriptor();
private final boolean isLazy;
private final PropertyGeneration propertyGeneration;
private final boolean isInsertable;
@ -50,8 +53,19 @@ public class HbmSimpleAttributeDomainState extends AbstractHbmAttributeDomainSta
org.hibernate.metamodel.domain.Attribute attribute,
Map<String, MetaAttribute> entityMetaAttributes,
XMLId id) {
super( defaults, attribute, entityMetaAttributes, id );
super(
defaults,
attribute,
id.getNode(),
HbmHelper.extractMetas( id.getMeta(), entityMetaAttributes ),
HbmHelper.getPropertyAccessorName( id.getAccess(), false, defaults.getDefaultAccess() ) ,
true
);
this.isLazy = false;
if ( id.getType() != null ) {
this.hibernateTypeDescriptor.setTypeName( id.getType().getName() );
}
// TODO: how should these be set???
this.propertyGeneration = PropertyGeneration.parse( null );
@ -64,7 +78,10 @@ public class HbmSimpleAttributeDomainState extends AbstractHbmAttributeDomainSta
org.hibernate.metamodel.domain.Attribute attribute,
Map<String, MetaAttribute> entityMetaAttributes,
XMLDiscriminator discriminator) {
super( defaults, attribute, discriminator );
super(
defaults, attribute, null, null, null, true
);
this.hibernateTypeDescriptor.setTypeName( discriminator.getType() == null ? "string" : discriminator.getType() );
this.isLazy = false;
this.propertyGeneration = PropertyGeneration.NEVER;
@ -77,7 +94,15 @@ public class HbmSimpleAttributeDomainState extends AbstractHbmAttributeDomainSta
Map<String, MetaAttribute> entityMetaAttributes,
XMLVersion version) {
super( defaults, attribute, entityMetaAttributes, version );
super(
defaults,
attribute,
version.getNode(),
HbmHelper.extractMetas( version.getMeta(), entityMetaAttributes ),
HbmHelper.getPropertyAccessorName( version.getAccess(), false, defaults.getDefaultAccess() ) ,
true
);
this.hibernateTypeDescriptor.setTypeName( version.getType() == null ? "integer" : version.getType() );
this.isLazy = false;
// for version properties marked as being generated, make sure they are "always"
@ -96,7 +121,16 @@ public class HbmSimpleAttributeDomainState extends AbstractHbmAttributeDomainSta
Map<String, MetaAttribute> entityMetaAttributes,
XMLTimestamp timestamp) {
super( defaults, attribute, entityMetaAttributes, timestamp );
super(
defaults,
attribute,
timestamp.getNode(),
HbmHelper.extractMetas( timestamp.getMeta(), entityMetaAttributes ),
HbmHelper.getPropertyAccessorName( timestamp.getAccess(), false, defaults.getDefaultAccess() ),
true
);
// Timestamp.getType() is not defined
this.hibernateTypeDescriptor.setTypeName( "db".equals( timestamp.getSource() ) ? "dbtimestamp" : "timestamp" );
this.isLazy = false;
// for version properties marked as being generated, make sure they are "always"
@ -114,7 +148,14 @@ public class HbmSimpleAttributeDomainState extends AbstractHbmAttributeDomainSta
org.hibernate.metamodel.domain.Attribute attribute,
Map<String, MetaAttribute> entityMetaAttributes,
XMLPropertyElement property) {
super( defaults, attribute, entityMetaAttributes, property );
super(
defaults,
attribute,
property.getNode(),
HbmHelper.extractMetas( property.getMeta(), entityMetaAttributes ),
HbmHelper.getPropertyAccessorName( property.getAccess(), false, defaults.getDefaultAccess() ),
property.isOptimisticLock()
);
this.isLazy = property.isLazy();
this.propertyGeneration = PropertyGeneration.parse( property.getGenerated() );
@ -150,11 +191,14 @@ public class HbmSimpleAttributeDomainState extends AbstractHbmAttributeDomainSta
}
}
@Override
protected boolean isEmbedded() {
return false;
}
public HibernateTypeDescriptor getHibernateTypeDescriptor() {
return hibernateTypeDescriptor;
}
public boolean isLazy() {
return isLazy;
}
@ -168,6 +212,11 @@ public class HbmSimpleAttributeDomainState extends AbstractHbmAttributeDomainSta
public boolean isUpdateable() {
return isUpdateable;
}
public String getCascade() {
return null;
}
public boolean isKeyCasadeDeleteEnabled() {
//TODO: implement
return false;

View File

@ -27,13 +27,14 @@ import java.util.Set;
import org.hibernate.MappingException;
import org.hibernate.cfg.NamingStrategy;
import org.hibernate.metamodel.binding.SimpleAttributeBinding;
import org.hibernate.metamodel.binding.AbstractAttributeBinding;
import org.hibernate.metamodel.relational.Size;
import org.hibernate.metamodel.source.hbm.xml.mapping.XMLColumnElement;
import org.hibernate.metamodel.source.hbm.xml.mapping.XMLHibernateMapping.XMLClass.XMLDiscriminator;
import org.hibernate.metamodel.source.hbm.xml.mapping.XMLHibernateMapping.XMLClass.XMLId;
import org.hibernate.metamodel.source.hbm.xml.mapping.XMLHibernateMapping.XMLClass.XMLTimestamp;
import org.hibernate.metamodel.source.hbm.xml.mapping.XMLHibernateMapping.XMLClass.XMLVersion;
import org.hibernate.metamodel.source.hbm.xml.mapping.XMLManyToOneElement;
import org.hibernate.metamodel.source.hbm.xml.mapping.XMLPropertyElement;
import org.hibernate.metamodel.source.util.MappingHelper;
@ -42,7 +43,7 @@ import org.hibernate.metamodel.source.util.MappingHelper;
/**
* @author Gail Badner
*/
public class HbmColumnRelationalState implements SimpleAttributeBinding.ColumnRelationalState {
public class HbmColumnRelationalState implements AbstractAttributeBinding.ColumnRelationalState {
private final HbmSimpleValueRelationalStateContainer container;
private final String explicitColumnName;
private final Size size;
@ -99,6 +100,25 @@ public class HbmColumnRelationalState implements SimpleAttributeBinding.ColumnRe
this.indexes.addAll( container.getPropertyIndexes() );
}
HbmColumnRelationalState(XMLManyToOneElement manyToOne,
HbmSimpleValueRelationalStateContainer container) {
this.container = container;
this.explicitColumnName = manyToOne.getName();
this.size = new Size();
this.isNullable =! MappingHelper.getBooleanValue( manyToOne.isNotNull(), false );
this.isUnique = manyToOne.isUnique();
this.checkCondition = null;
this.defaultColumnValue = null;
this.sqlType = null;
this.customWrite = null;
this.customRead = null;
this.comment = null;
this.uniqueKeys = MappingHelper.getStringValueTokens( manyToOne.getUniqueKey(), ", " );
this.uniqueKeys.addAll( container.getPropertyUniqueKeys() );
this.indexes = MappingHelper.getStringValueTokens( manyToOne.getIndex(), ", " );
this.indexes.addAll( container.getPropertyIndexes() );
}
HbmColumnRelationalState(XMLId id,
HbmSimpleValueRelationalStateContainer container) {
if ( id.getColumn() != null && ! id.getColumn().isEmpty() ) {
@ -152,7 +172,7 @@ public class HbmColumnRelationalState implements SimpleAttributeBinding.ColumnRe
this.isUnique = false;
this.checkCondition = null;
this.defaultColumnValue = null;
this.sqlType = null; // TODO: figure out the correct setting
this.sqlType = null;
this.customWrite = null;
this.customRead = null;
this.comment = null;
@ -170,7 +190,7 @@ public class HbmColumnRelationalState implements SimpleAttributeBinding.ColumnRe
this.isUnique = true; // well, it should hopefully be unique...
this.checkCondition = null;
this.defaultColumnValue = null;
this.sqlType = null; // TODO: figure out the correct setting
this.sqlType = null;
this.customWrite = null;
this.customRead = null;
this.comment = null;
@ -187,7 +207,7 @@ public class HbmColumnRelationalState implements SimpleAttributeBinding.ColumnRe
public Size getSize() {
return size;
}
private static Size createSize(String length, String scale, String precision) {
protected static Size createSize(String length, String scale, String precision) {
// TODO: should this set defaults if length, scale, precision is not specified?
Size size = new Size();
if ( length != null ) {

View File

@ -23,8 +23,6 @@
*/
package org.hibernate.metamodel.source.hbm.state.relational;
import org.dom4j.Element;
import org.hibernate.metamodel.binding.SimpleAttributeBinding;
/**

View File

@ -0,0 +1,54 @@
/*
* 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.source.hbm.state.relational;
import org.hibernate.metamodel.binding.ManyToOneAttributeBinding;
import org.hibernate.metamodel.binding.MappingDefaults;
import org.hibernate.metamodel.source.hbm.xml.mapping.XMLManyToOneElement;
/**
* @author Gail Badner
*/
public class HbmManyToOneRelationalStateContainer extends HbmSimpleValueRelationalStateContainer
implements ManyToOneAttributeBinding.RelationalState {
private final boolean isLogicalOneToOne;
private final String foreignKeyName;
public HbmManyToOneRelationalStateContainer(MappingDefaults defaults,
boolean autoColumnCreation,
XMLManyToOneElement manyToOne ) {
super( defaults, autoColumnCreation, manyToOne );
this.isLogicalOneToOne = manyToOne.isUnique();
this.foreignKeyName = manyToOne.getForeignKey();
}
public boolean isLogicalOneToOne() {
return isLogicalOneToOne;
}
public String getForeignKeyName() {
return foreignKeyName;
}
}

View File

@ -30,13 +30,16 @@ import java.util.Set;
import org.hibernate.MappingException;
import org.hibernate.cfg.NamingStrategy;
import org.hibernate.metamodel.binding.HibernateTypeDescriptor;
import org.hibernate.metamodel.binding.MappingDefaults;
import org.hibernate.metamodel.binding.SimpleAttributeBinding;
import org.hibernate.metamodel.relational.Size;
import org.hibernate.metamodel.source.hbm.xml.mapping.XMLColumnElement;
import org.hibernate.metamodel.source.hbm.xml.mapping.XMLHibernateMapping.XMLClass.XMLDiscriminator;
import org.hibernate.metamodel.source.hbm.xml.mapping.XMLHibernateMapping.XMLClass.XMLId;
import org.hibernate.metamodel.source.hbm.xml.mapping.XMLHibernateMapping.XMLClass.XMLTimestamp;
import org.hibernate.metamodel.source.hbm.xml.mapping.XMLHibernateMapping.XMLClass.XMLVersion;
import org.hibernate.metamodel.source.hbm.xml.mapping.XMLManyToOneElement;
import org.hibernate.metamodel.source.hbm.xml.mapping.XMLPropertyElement;
/**
@ -47,6 +50,7 @@ public class HbmSimpleValueRelationalStateContainer implements SimpleAttributeBi
private final Set<String> propertyUniqueKeys;
private final Set<String> propertyIndexes;
private final Set<SimpleAttributeBinding.SingleValueRelationalState> singleValueStates;
private final HibernateTypeDescriptor hibernateTypeDescriptor = new HibernateTypeDescriptor();
public NamingStrategy getNamingStrategy() {
return defaults.getNamingStrategy();
@ -67,6 +71,7 @@ public class HbmSimpleValueRelationalStateContainer implements SimpleAttributeBi
else if ( id.getColumn() != null ) {
throw new MappingException( "column attribute may not be used together with <column> subelement" );
}
this.hibernateTypeDescriptor.setTypeName( id.getTypeAttribute() );
}
public HbmSimpleValueRelationalStateContainer(MappingDefaults defaults,
@ -82,6 +87,7 @@ public class HbmSimpleValueRelationalStateContainer implements SimpleAttributeBi
else if ( discriminator.getColumn() != null || discriminator.getFormula() != null) {
throw new MappingException( "column/formula attribute may not be used together with <column>/<formula> subelement" );
}
this.hibernateTypeDescriptor.setTypeName( discriminator.getType() == null ? "string" : discriminator.getType() );
}
public HbmSimpleValueRelationalStateContainer(MappingDefaults defaults,
@ -97,6 +103,7 @@ public class HbmSimpleValueRelationalStateContainer implements SimpleAttributeBi
else if ( version.getColumn() != null ) {
throw new MappingException( "column attribute may not be used together with <column> subelement" );
}
this.hibernateTypeDescriptor.setTypeName( version.getType() == null ? "integer" : version.getType() );
}
public HbmSimpleValueRelationalStateContainer(MappingDefaults defaults,
@ -112,6 +119,7 @@ public class HbmSimpleValueRelationalStateContainer implements SimpleAttributeBi
else if ( timestamp.getColumn() != null ) {
throw new MappingException( "column attribute may not be used together with <column> subelement" );
}
this.hibernateTypeDescriptor.setTypeName( "db".equals( timestamp.getSource() ) ? "dbtimestamp" : "timestamp" );
}
public HbmSimpleValueRelationalStateContainer(MappingDefaults defaults,
@ -127,6 +135,22 @@ public class HbmSimpleValueRelationalStateContainer implements SimpleAttributeBi
else if ( property.getColumn() != null || property.getFormula() != null) {
throw new MappingException( "column/formula attribute may not be used together with <column>/<formula> subelement" );
}
this.hibernateTypeDescriptor.setTypeName( property.getTypeAttribute() );
}
public HbmSimpleValueRelationalStateContainer(MappingDefaults defaults,
boolean autoColumnCreation,
XMLManyToOneElement manyToOne) {
this( defaults, manyToOne.getColumnOrFormula() );
if ( singleValueStates.isEmpty() ) {
if ( manyToOne.getColumn() == null && manyToOne.getFormula() == null && ! autoColumnCreation ) {
throw new MappingException( "No column or formula to map and auto column creation is disabled." );
}
singleValueStates.add( new HbmColumnRelationalState( manyToOne, this ) );
}
else if ( manyToOne.getColumn() != null || manyToOne.getFormula() != null) {
throw new MappingException( "column/formula attribute may not be used together with <column>/<formula> subelement" );
}
}
private HbmSimpleValueRelationalStateContainer(MappingDefaults defaults,

View File

@ -0,0 +1,75 @@
/*
* 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.source.internal;
import org.hibernate.MappingException;
import org.hibernate.metamodel.binding.AttributeBinding;
import org.hibernate.metamodel.binding.EntityBinding;
import org.hibernate.metamodel.binding.EntityReferencingAttributeBinding;
import org.hibernate.metamodel.source.spi.MetadataImplementor;
/**
* @author Gail Badner
*/
class EntityReferenceResolver {
private final MetadataImplementor metadata;
EntityReferenceResolver(MetadataImplementor metadata) {
this.metadata = metadata;
}
void resolve() {
for ( EntityBinding entityBinding : metadata.getEntityBindings() ) {
for ( EntityReferencingAttributeBinding attributeBinding : entityBinding.getEntityReferencingAttributeBindings() ) {
resolve( attributeBinding );
}
}
}
private void resolve(EntityReferencingAttributeBinding attributeBinding) {
if ( attributeBinding.getReferencedEntityName() == null ) {
throw new IllegalArgumentException( "attributeBinding has null entityName: " + attributeBinding.getAttribute().getName() );
}
EntityBinding entityBinding = metadata.getEntityBinding( attributeBinding.getReferencedEntityName() );
if ( entityBinding == null ) {
throw new org.hibernate.MappingException(
"Attribute [" + attributeBinding.getAttribute().getName() +
"] refers to unknown entity: [" + attributeBinding.getReferencedEntityName() + "]" );
}
AttributeBinding referencedAttributeBinding =
attributeBinding.getReferencedAttributeName() == null ?
entityBinding.getEntityIdentifier().getValueBinding() :
entityBinding.getAttributeBinding( attributeBinding.getReferencedAttributeName() );
if ( referencedAttributeBinding == null ) {
// TODO: does attribute name include path w/ entity name?
throw new MappingException(
"Attribute [" + attributeBinding.getAttribute().getName() +
"] refers to unknown attribute: [" + attributeBinding.getReferencedEntityName() + "]"
);
}
attributeBinding.resolveReference( referencedAttributeBinding );
referencedAttributeBinding.addEntityReferencingAttributeBinding( attributeBinding );
}
}

View File

@ -41,6 +41,7 @@ import org.hibernate.cfg.NamingStrategy;
import org.hibernate.internal.CoreMessageLogger;
import org.hibernate.mapping.MetadataSource;
import org.hibernate.metamodel.binding.EntityBinding;
import org.hibernate.metamodel.binding.EntityReferencingAttributeBinding;
import org.hibernate.metamodel.binding.FetchProfile;
import org.hibernate.metamodel.binding.PluralAttributeBinding;
import org.hibernate.metamodel.relational.Database;
@ -88,6 +89,8 @@ public class MetadataImpl implements Metadata, MetadataImplementor, Serializable
applyAnnotationMappings( metadataSources, processedEntityNames );
applyHibernateMappings( metadataSources, processedEntityNames );
}
new EntityReferenceResolver( this ).resolve();
}
private void applyHibernateMappings(MetadataSources metadataSources, List<String> processedEntityNames) {