[hibernate-commits] Hibernate SVN: r17871 - in core/trunk: annotations/src/main/java/org/hibernate/cfg/annotations and 1 other directories.

hibernate-commits at lists.jboss.org hibernate-commits at lists.jboss.org
Wed Oct 28 14:14:26 EDT 2009


Author: epbernard
Date: 2009-10-28 14:14:25 -0400 (Wed, 28 Oct 2009)
New Revision: 17871

Added:
   core/trunk/core/src/main/java/org/hibernate/mapping/MappedSuperclass.java
Modified:
   core/trunk/annotations/src/main/java/org/hibernate/cfg/AbstractPropertyHolder.java
   core/trunk/annotations/src/main/java/org/hibernate/cfg/AnnotationBinder.java
   core/trunk/annotations/src/main/java/org/hibernate/cfg/AnnotationConfiguration.java
   core/trunk/annotations/src/main/java/org/hibernate/cfg/ClassPropertyHolder.java
   core/trunk/annotations/src/main/java/org/hibernate/cfg/CollectionPropertyHolder.java
   core/trunk/annotations/src/main/java/org/hibernate/cfg/ComponentPropertyHolder.java
   core/trunk/annotations/src/main/java/org/hibernate/cfg/Ejb3JoinColumn.java
   core/trunk/annotations/src/main/java/org/hibernate/cfg/ExtendedMappings.java
   core/trunk/annotations/src/main/java/org/hibernate/cfg/OneToOneSecondPass.java
   core/trunk/annotations/src/main/java/org/hibernate/cfg/PropertyData.java
   core/trunk/annotations/src/main/java/org/hibernate/cfg/PropertyHolder.java
   core/trunk/annotations/src/main/java/org/hibernate/cfg/PropertyHolderBuilder.java
   core/trunk/annotations/src/main/java/org/hibernate/cfg/PropertyInferredData.java
   core/trunk/annotations/src/main/java/org/hibernate/cfg/PropertyPreloadedData.java
   core/trunk/annotations/src/main/java/org/hibernate/cfg/WrappedInferredData.java
   core/trunk/annotations/src/main/java/org/hibernate/cfg/annotations/CollectionBinder.java
   core/trunk/annotations/src/main/java/org/hibernate/cfg/annotations/IdBagBinder.java
   core/trunk/annotations/src/main/java/org/hibernate/cfg/annotations/ListBinder.java
   core/trunk/annotations/src/main/java/org/hibernate/cfg/annotations/MapBinder.java
   core/trunk/annotations/src/main/java/org/hibernate/cfg/annotations/PropertyBinder.java
   core/trunk/core/src/main/java/org/hibernate/mapping/Join.java
   core/trunk/core/src/main/java/org/hibernate/mapping/PersistentClass.java
   core/trunk/core/src/main/java/org/hibernate/mapping/Subclass.java
Log:
HHH-4533 add representation for @MappedSuperclass in the Hibernate Core metamodel and properly populate this model extension in Hibernate Annotations

Modified: core/trunk/annotations/src/main/java/org/hibernate/cfg/AbstractPropertyHolder.java
===================================================================
--- core/trunk/annotations/src/main/java/org/hibernate/cfg/AbstractPropertyHolder.java	2009-10-28 18:03:10 UTC (rev 17870)
+++ core/trunk/annotations/src/main/java/org/hibernate/cfg/AbstractPropertyHolder.java	2009-10-28 18:14:25 UTC (rev 17871)
@@ -66,6 +66,10 @@
 		return path;
 	}
 
+	protected ExtendedMappings getMappings() {
+		return mappings;
+	}
+
 	/**
 	 * property can be null
 	 */

Modified: core/trunk/annotations/src/main/java/org/hibernate/cfg/AnnotationBinder.java
===================================================================
--- core/trunk/annotations/src/main/java/org/hibernate/cfg/AnnotationBinder.java	2009-10-28 18:03:10 UTC (rev 17870)
+++ core/trunk/annotations/src/main/java/org/hibernate/cfg/AnnotationBinder.java	2009-10-28 18:14:25 UTC (rev 17871)
@@ -457,9 +457,10 @@
 		}
 		XAnnotatedElement annotatedClass = clazzToProcess;
 		log.info( "Binding entity from annotated class: {}", clazzToProcess.getName() );
+		final ReflectionManager reflectionManager = mappings.getReflectionManager();
 		InheritanceState superEntityState =
 				InheritanceState.getSuperEntityInheritanceState(
-						clazzToProcess, inheritanceStatePerClass, mappings.getReflectionManager()
+						clazzToProcess, inheritanceStatePerClass, reflectionManager
 				);
 		PersistentClass superEntity = superEntityState != null ?
 				mappings.getClass(
@@ -627,7 +628,7 @@
 		PropertyHolder propertyHolder = PropertyHolderBuilder.buildPropertyHolder(
 				clazzToProcess,
 				persistentClass,
-				entityBinder, mappings
+				entityBinder, mappings, inheritanceStatePerClass
 		);
 
 		javax.persistence.SecondaryTable secTabAnn = annotatedClass.getAnnotation(
@@ -702,7 +703,7 @@
 		// check properties
 		List<PropertyData> elements =
 				getElementsToProcess(
-						clazzToProcess, inheritanceStatePerClass, propertyHolder, entityBinder, mappings
+						persistentClass, clazzToProcess, inheritanceStatePerClass, propertyHolder, entityBinder, mappings
 				);
 		if ( elements == null ) {
 			throw new AnnotationException( "No identifier specified for entity: " + propertyHolder.getEntityName() );
@@ -724,13 +725,13 @@
 					break;
 				}
 				state = InheritanceState.getSuperclassInheritanceState(
-						current, inheritanceStatePerClass, mappings.getReflectionManager()
+						current, inheritanceStatePerClass, reflectionManager
 				);
 			}
 			while ( state != null );
 		}
 		if ( idClass != null ) {
-			XClass compositeClass = mappings.getReflectionManager().toXClass( idClass.value() );
+			XClass compositeClass = reflectionManager.toXClass( idClass.value() );
 			boolean isComponent = true;
 			boolean propertyAnnotated = entityBinder.isPropertyAnnotated( compositeClass );
 			String propertyAccessor = entityBinder.getPropertyAccessor( compositeClass );
@@ -757,7 +758,7 @@
 					propertyAnnotated,
 					propertyAccessor, entityBinder,
 					true,
-					false, mappings
+					false, mappings, inheritanceStatePerClass
 			);
 			inferredData = new PropertyPreloadedData(
 					propertyAccessor, "_identifierMapper", compositeClass
@@ -770,7 +771,7 @@
 					propertyAccessor, false,
 					entityBinder,
 					true, true,
-					false, mappings
+					false, mappings, inheritanceStatePerClass
 			);
 			entityBinder.setIgnoreIdAnnotations( ignoreIdAnnotations );
 			persistentClass.setIdentifierMapper( mapper );
@@ -800,7 +801,7 @@
 								Nullability.NO_CONSTRAINT,
 						propertyAnnotatedElement.getProperty(),
 						propertyAnnotatedElement, classGenerators, entityBinder,
-						false, false, false, mappings
+						false, false, false, mappings, inheritanceStatePerClass
 				);
 			}
 			else {
@@ -845,12 +846,13 @@
 	 * Change EntityBinder by side effect
 	 */
 	private static List<PropertyData> getElementsToProcess(
-			XClass clazzToProcess, Map<XClass, InheritanceState> inheritanceStatePerClass,
+			PersistentClass persistentClass, XClass clazzToProcess,
+			Map<XClass, InheritanceState> inheritanceStatePerClass,
 			PropertyHolder propertyHolder, EntityBinder entityBinder, ExtendedMappings mappings
 	) {
 		InheritanceState inheritanceState = inheritanceStatePerClass.get( clazzToProcess );
-		List<XClass> classesToProcess = orderClassesToBeProcessed(
-				clazzToProcess, inheritanceStatePerClass, inheritanceState, mappings
+		List<XClass> classesToProcess = getMappedSuperclassesTillNextEntityOrdered(
+				persistentClass, clazzToProcess, inheritanceStatePerClass, mappings
 		);
 		List<PropertyData> elements = new ArrayList<PropertyData>();
 		int deep = classesToProcess.size();
@@ -858,7 +860,7 @@
 
 		assert !inheritanceState.isEmbeddableSuperclass;
 		Boolean isExplicitPropertyAnnotated = null;
-		String explicitAccessType = null;
+		String explicitAccessType;
 		if ( inheritanceState.hasParents ) {
 			InheritanceState superEntityState =
 					InheritanceState.getSuperEntityInheritanceState(
@@ -942,14 +944,17 @@
 				null;
 	}
 
-	private static List<XClass> orderClassesToBeProcessed(
-			XClass annotatedClass, Map<XClass, InheritanceState> inheritanceStatePerClass,
-			InheritanceState inheritanceState, ExtendedMappings mappings
+	private static List<XClass> getMappedSuperclassesTillNextEntityOrdered(
+			PersistentClass persistentClass, XClass annotatedClass,
+			Map<XClass, InheritanceState> inheritanceStatePerClass,
+			ExtendedMappings mappings
 	) {
+		
 		//ordered to allow proper messages on properties subclassing
 		List<XClass> classesToProcess = new ArrayList<XClass>();
 		XClass currentClassInHierarchy = annotatedClass;
 		InheritanceState superclassState;
+		final ReflectionManager reflectionManager = mappings.getReflectionManager();
 		do {
 			classesToProcess.add( 0, currentClassInHierarchy );
 			XClass superClass = currentClassInHierarchy;
@@ -957,13 +962,36 @@
 				superClass = superClass.getSuperclass();
 				superclassState = inheritanceStatePerClass.get( superClass );
 			}
-			while ( superClass != null && !mappings.getReflectionManager()
+			while ( superClass != null && !reflectionManager
 					.equals( superClass, Object.class ) && superclassState == null );
 
 			currentClassInHierarchy = superClass;
 		}
 		while ( superclassState != null && superclassState.isEmbeddableSuperclass );
 
+		//add @MappedSuperclass in the metadata
+		// classes from 0 to n-1 are @MappedSuperclass and should be linked
+		org.hibernate.mapping.MappedSuperclass mappedSuperclass = null;
+		final InheritanceState superEntityState =
+				InheritanceState.getSuperEntityInheritanceState(annotatedClass, inheritanceStatePerClass, reflectionManager);
+		PersistentClass superEntity =
+				superEntityState != null ?
+						mappings.getClass( superEntityState.clazz.getName() ) :
+						null;
+		final int lastMappedSuperclass = classesToProcess.size() - 1;
+		for ( int index = 0 ; index < lastMappedSuperclass ; index++ ) {
+			org.hibernate.mapping.MappedSuperclass parentSuperclass = mappedSuperclass;
+			final Class<?> type = mappings.getReflectionManager().toClass( classesToProcess.get( index ) );
+			//add MAppedSuperclass if not already there
+			mappedSuperclass = mappings.getMappedSuperclass( type );
+			if (mappedSuperclass == null) {
+				mappedSuperclass = new org.hibernate.mapping.MappedSuperclass(parentSuperclass, superEntity );
+				mappings.addMappedSuperclass( type, mappedSuperclass );
+			}
+		}
+		if (mappedSuperclass != null) {
+			persistentClass.setSuperMappedSuperclass(mappedSuperclass);
+		}
 		return classesToProcess;
 	}
 	
@@ -1127,7 +1155,7 @@
 								" or set an explicit target attribute (eg @OneToMany(target=) or use an explicit @Type"
 				);
 			}
-			final boolean currentHasIdentifier = addProperty( p, elements, localPropertyAccessor, mappings );
+			final boolean currentHasIdentifier = addProperty( annotatedClass, p, elements, localPropertyAccessor, mappings );
 			hasIdentifier = hasIdentifier || currentHasIdentifier;
 		}
 		return hasIdentifier;
@@ -1173,17 +1201,17 @@
 	}
 
 	private static boolean addProperty(
-			XProperty property, List<PropertyData> annElts,
+			XClass declaringClass, XProperty property, List<PropertyData> annElts,
 			String propertyAccessor, ExtendedMappings mappings
 	) {
 		boolean hasIdentifier = false;
 		PropertyData propertyAnnotatedElement = new PropertyInferredData(
-				property, propertyAccessor,
+				declaringClass, property, propertyAccessor,
 				mappings.getReflectionManager() );
 		if ( !mustBeSkipped( propertyAnnotatedElement.getProperty(), mappings ) ) {
 			/*
 			 * put element annotated by @Id in front
-			 * since it has to be parsed before any assoctation by Hibernate
+			 * since it has to be parsed before any association by Hibernate
 			 */
 			final XAnnotatedElement element = propertyAnnotatedElement.getProperty();
 			if ( element.isAnnotationPresent( Id.class ) || element.isAnnotationPresent( EmbeddedId.class ) ) {
@@ -1212,7 +1240,8 @@
 			PropertyHolder propertyHolder, Nullability nullability, XProperty property,
 			PropertyData inferredData, HashMap<String, IdGenerator> classGenerators,
 			EntityBinder entityBinder, boolean isIdentifierMapper,
-			boolean isComponentEmbedded, boolean inSecondPass, ExtendedMappings mappings
+			boolean isComponentEmbedded, boolean inSecondPass, ExtendedMappings mappings,
+			Map<XClass, InheritanceState> inheritanceStatePerClass
 	)
 			throws MappingException {
 		/**
@@ -1389,7 +1418,9 @@
 					propertyAnnotated,
 					propertyAccessor, entityBinder,
 					false,
-					isIdentifierMapper, mappings
+					isIdentifierMapper,
+					mappings,
+					inheritanceStatePerClass
 			);
 						
 			log.debug(
@@ -1426,7 +1457,7 @@
 			propBinder.setProperty( property );
 			propBinder.setReturnedClass( inferredData.getPropertyClass() );
 			propBinder.setMappings( mappings );
-			
+			propBinder.setDeclaringClass( inferredData.getDeclaringClass() );
 			Property prop = propBinder.bind();
 			propBinder.getSimpleValueBinder().setVersion(true);
 			rootClass.setVersion( prop );
@@ -1791,6 +1822,8 @@
 				collectionBinder.setLocalGenerators( localGenerators );
 
 			}
+			collectionBinder.setInheritanceStatePerClass( inheritanceStatePerClass );
+			collectionBinder.setDeclaringClass( inferredData.getDeclaringClass() );
 			collectionBinder.bind();
 
 		}
@@ -1810,7 +1843,7 @@
 				bindComponent(
 						inferredData, propertyHolder, propertyAnnotated, propertyAccessor, entityBinder,
 						isIdentifierMapper,
-						mappings, isComponentEmbedded
+						mappings, isComponentEmbedded, inheritanceStatePerClass
 				);
 			}
 			else {
@@ -1844,6 +1877,7 @@
 					propBinder.setInsertable( false );
 					propBinder.setUpdatable( false );
 				}
+				propBinder.setDeclaringClass( inferredData.getDeclaringClass() );
 				propBinder.bind();
 			}
 		}
@@ -1955,12 +1989,13 @@
 			boolean propertyAnnotated,
 			String propertyAccessor, EntityBinder entityBinder,
 			boolean isIdentifierMapper,
-			ExtendedMappings mappings, boolean isComponentEmbedded
+			ExtendedMappings mappings, boolean isComponentEmbedded,
+			Map<XClass, InheritanceState> inheritanceStatePerClass
 	) {
 		Component comp = fillComponent(
 				propertyHolder, inferredData, propertyAnnotated, propertyAccessor, true, entityBinder,
 				isComponentEmbedded, isIdentifierMapper,
-				false, mappings
+				false, mappings, inheritanceStatePerClass
 		);
 		XProperty property = inferredData.getProperty();
 		setupComponentTuplizer( property, comp );
@@ -1971,24 +2006,28 @@
 		binder.setProperty( inferredData.getProperty() );
 		binder.setPropertyAccessorName( inferredData.getDefaultAccess() );
 		Property prop = binder.make();
-		propertyHolder.addProperty( prop );
+		propertyHolder.addProperty( prop, inferredData.getDeclaringClass() );
 	}
 
 	public static Component fillComponent(
 			PropertyHolder propertyHolder, PropertyData inferredData,
 			boolean propertyAnnotated, String propertyAccessor, boolean isNullable,
 			EntityBinder entityBinder,
-			boolean isComponentEmbedded, boolean isIdentifierMapper, boolean inSecondPass, ExtendedMappings mappings
+			boolean isComponentEmbedded, boolean isIdentifierMapper, boolean inSecondPass,
+			ExtendedMappings mappings, Map<XClass, InheritanceState> inheritanceStatePerClass
 	) {
 	   
-	   return fillComponent(propertyHolder, inferredData, null, propertyAnnotated, propertyAccessor, isNullable, entityBinder, isComponentEmbedded, isIdentifierMapper, inSecondPass, mappings);
+	   return fillComponent(propertyHolder, inferredData, null, propertyAnnotated, propertyAccessor,
+			   isNullable, entityBinder, isComponentEmbedded, isIdentifierMapper, inSecondPass, mappings,
+			   inheritanceStatePerClass);
 	}
 	
 	public static Component fillComponent(
           PropertyHolder propertyHolder, PropertyData inferredData, PropertyData baseInferredData,
           boolean propertyAnnotated, String propertyAccessor, boolean isNullable,
           EntityBinder entityBinder,
-          boolean isComponentEmbedded, boolean isIdentifierMapper, boolean inSecondPass, ExtendedMappings mappings
+          boolean isComponentEmbedded, boolean isIdentifierMapper, boolean inSecondPass, ExtendedMappings mappings,
+		  Map<XClass, InheritanceState> inheritanceStatePerClass
   ) {
 	
 		/**
@@ -2057,15 +2096,12 @@
 			);
 			superClass = superClass.getSuperclass();
 		}
-		if(baseClassElements != null)
-		{
-		   if(!hasIdClassAnnotations(inferredData.getPropertyClass()))
-		   {
-		      for(int i=0; i < classElements.size(); i++)
-		      {
-		         classElements.set(i, baseClassElements.get(i));  //this works since they are in the same order
-		      }
-		   }
+		if ( baseClassElements != null ) {
+			if ( !hasIdClassAnnotations( inferredData.getPropertyClass() ) ) {
+				for ( int i = 0; i < classElements.size(); i++ ) {
+					classElements.set( i, baseClassElements.get( i ) );  //this works since they are in the same order
+				}
+			}
 		}
 		for (PropertyData propertyAnnotatedElement : classElements) {
 			processElementAnnotations(
@@ -2074,7 +2110,7 @@
 					Nullability.FORCED_NOT_NULL,
 					propertyAnnotatedElement.getProperty(), propertyAnnotatedElement,
 					new HashMap<String, IdGenerator>(), entityBinder, isIdentifierMapper, isComponentEmbedded,
-					inSecondPass, mappings
+					inSecondPass, mappings, inheritanceStatePerClass
 			);
 		}
 		return comp;
@@ -2087,10 +2123,13 @@
 			boolean isComposite,
 			boolean isPropertyAnnotated,
 			String propertyAccessor, EntityBinder entityBinder, boolean isEmbedded,
-			boolean isIdentifierMapper, ExtendedMappings mappings
+			boolean isIdentifierMapper, ExtendedMappings mappings,
+			Map<XClass, InheritanceState> inheritanceStatePerClass
 	) {
 	   
-	   bindId(generatorType, generatorName, inferredData, null, columns, propertyHolder, localGenerators, isComposite, isPropertyAnnotated, propertyAccessor, entityBinder, isEmbedded, isIdentifierMapper, mappings);
+	   bindId(generatorType, generatorName, inferredData, null, columns, propertyHolder,
+			   localGenerators, isComposite, isPropertyAnnotated, propertyAccessor, entityBinder,
+			   isEmbedded, isIdentifierMapper, mappings, inheritanceStatePerClass);
 	}
 	
     private static void bindId(
@@ -2100,7 +2139,8 @@
           boolean isComposite,
           boolean isPropertyAnnotated,
           String propertyAccessor, EntityBinder entityBinder, boolean isEmbedded,
-          boolean isIdentifierMapper, ExtendedMappings mappings
+          boolean isIdentifierMapper, ExtendedMappings mappings,
+		  Map<XClass, InheritanceState> inheritanceStatePerClass
   ) {
      
 		/*
@@ -2121,7 +2161,7 @@
 		if ( isComposite ) {
 			id = fillComponent(
 					propertyHolder, inferredData, baseInferredData, isPropertyAnnotated, propertyAccessor,
-					false, entityBinder, isEmbedded, isIdentifierMapper, false, mappings
+					false, entityBinder, isEmbedded, isIdentifierMapper, false, mappings, inheritanceStatePerClass
 			);
 			Component componentId = (Component) id;
 			componentId.setKey( true );
@@ -2247,7 +2287,7 @@
 		binder.setProperty(inferredData.getProperty());
 		Property prop = binder.make();
 		//composite FK columns are in the same table so its OK
-		propertyHolder.addProperty( prop, columns );
+		propertyHolder.addProperty( prop, columns, inferredData.getDeclaringClass() );
 	}
 
 	protected static void defineFetchingStrategy(ToOne toOne, XProperty property) {
@@ -2397,7 +2437,7 @@
 		binder.setCascade( cascadeStrategy );
 		Property prop = binder.make();
 		//composite FK columns are in the same table so its OK
-		propertyHolder.addProperty( prop, columns );
+		propertyHolder.addProperty( prop, columns, inferredData.getDeclaringClass() );
 	}
 
 	private static String generatorType(GenerationType generatorEnum) {

Modified: core/trunk/annotations/src/main/java/org/hibernate/cfg/AnnotationConfiguration.java
===================================================================
--- core/trunk/annotations/src/main/java/org/hibernate/cfg/AnnotationConfiguration.java	2009-10-28 18:03:10 UTC (rev 17870)
+++ core/trunk/annotations/src/main/java/org/hibernate/cfg/AnnotationConfiguration.java	2009-10-28 18:14:25 UTC (rev 17871)
@@ -135,6 +135,7 @@
 	private transient ReflectionManager reflectionManager;
 	private boolean isDefaultProcessed = false;
 	private boolean isValidatorNotPresentLogged;
+	private Map<Class<?>, org.hibernate.mapping.MappedSuperclass> mappedSuperclasses;
 
 	public AnnotationConfiguration() {
 		super();
@@ -260,6 +261,7 @@
 		namingStrategy = EJB3NamingStrategy.INSTANCE;
 		setEntityResolver( new EJB3DTDEntityResolver() );
 		anyMetaDefs = new HashMap<String, AnyMetaDef>();
+		mappedSuperclasses = new HashMap<Class<?>, org.hibernate.mapping.MappedSuperclass>();
 		reflectionManager = new JavaReflectionManager();
 		( ( MetadataProviderInjector ) reflectionManager ).setMetadataProvider( new JPAMetadataProvider() );
 
@@ -1178,7 +1180,14 @@
 			return inSecondPass;
 		}
 
+		public void addMappedSuperclass(Class<?> type, org.hibernate.mapping.MappedSuperclass mappedSuperclass) {
+			mappedSuperclasses.put( type, mappedSuperclass );
+		}
 
+		public org.hibernate.mapping.MappedSuperclass getMappedSuperclass(Class<?> type) {
+			return mappedSuperclasses.get( type );
+		}
+
 		public IdGenerator getGenerator(String name) {
 			return getGenerator( name, null );
 		}
@@ -1240,6 +1249,7 @@
 			}
 		}
 
+		//FIXME should be private but is part of the ExtendedMapping contract
 		public AnnotatedClassType addClassType(XClass clazz) {
 			AnnotatedClassType type;
 			if ( clazz.isAnnotationPresent( Entity.class ) ) {

Modified: core/trunk/annotations/src/main/java/org/hibernate/cfg/ClassPropertyHolder.java
===================================================================
--- core/trunk/annotations/src/main/java/org/hibernate/cfg/ClassPropertyHolder.java	2009-10-28 18:03:10 UTC (rev 17870)
+++ core/trunk/annotations/src/main/java/org/hibernate/cfg/ClassPropertyHolder.java	2009-10-28 18:14:25 UTC (rev 17871)
@@ -28,6 +28,7 @@
 import javax.persistence.JoinTable;
 
 import org.hibernate.annotations.common.reflection.XClass;
+import org.hibernate.annotations.common.AssertionFailure;
 import org.hibernate.cfg.annotations.EntityBinder;
 import org.hibernate.mapping.Component;
 import org.hibernate.mapping.Join;
@@ -35,6 +36,7 @@
 import org.hibernate.mapping.PersistentClass;
 import org.hibernate.mapping.Property;
 import org.hibernate.mapping.Table;
+import org.hibernate.mapping.MappedSuperclass;
 
 /**
  * @author Emmanuel Bernard
@@ -44,20 +46,23 @@
 	private Map<String, Join> joins;
 	private transient Map<String, Join> joinsPerRealTableName;
 	private EntityBinder entityBinder;
+	private final Map<XClass, InheritanceState> inheritanceStatePerClass;
 
 	public ClassPropertyHolder(
-			PersistentClass persistentClass, XClass clazzToProcess, Map<String, Join> joins, ExtendedMappings mappings
+			PersistentClass persistentClass, XClass clazzToProcess,
+			Map<String, Join> joins, ExtendedMappings mappings, Map<XClass, InheritanceState> inheritanceStatePerClass
 	) {
 		super( persistentClass.getEntityName(), null, clazzToProcess, mappings );
 		this.persistentClass = persistentClass;
 		this.joins = joins;
+		this.inheritanceStatePerClass = inheritanceStatePerClass;
 	}
 
 	public ClassPropertyHolder(
 			PersistentClass persistentClass, XClass clazzToProcess, EntityBinder entityBinder,
-			ExtendedMappings mappings
+			ExtendedMappings mappings, Map<XClass, InheritanceState> inheritanceStatePerClass
 	) {
-		this( persistentClass, clazzToProcess, entityBinder.getSecondaryTables(), mappings );
+		this( persistentClass, clazzToProcess, entityBinder.getSecondaryTables(), mappings, inheritanceStatePerClass );
 		this.entityBinder = entityBinder;
 	}
 
@@ -65,30 +70,53 @@
 		return persistentClass.getEntityName();
 	}
 
-	public void addProperty(Property prop, Ejb3Column[] columns) {
+	public void addProperty(Property prop, Ejb3Column[] columns, XClass declaringClass) {
 		//Ejb3Column.checkPropertyConsistency( ); //already called earlier
 		if ( columns[0].isSecondary() ) {
 			//TODO move the getJoin() code here?
-			columns[0].getJoin().addProperty( prop );
+			final Join join = columns[0].getJoin();
+			addPropertyToJoin( prop, declaringClass, join );
 		}
 		else {
-			addProperty( prop );
+			addProperty( prop, declaringClass );
 		}
 	}
 
+	public void addProperty(Property prop, XClass declaringClass) {
+		if ( prop.getValue() instanceof Component ) {
+			//TODO handle quote and non quote table comparison
+			String tableName = prop.getValue().getTable().getName();
+			if ( getJoinsPerRealTableName().containsKey( tableName ) ) {
+				final Join join = getJoinsPerRealTableName().get( tableName );
+				addPropertyToJoin( prop, declaringClass, join );
+			}
+			else {
+				addPropertyToPersistentClass( prop, declaringClass );
+			}
+		}
+		else {
+			addPropertyToPersistentClass( prop, declaringClass );
+		}
+	}
+
 	public Join addJoin(JoinTable joinTableAnn, boolean noDelayInPkColumnCreation) {
 		Join join = entityBinder.addJoin( joinTableAnn, this, noDelayInPkColumnCreation );
 		this.joins = entityBinder.getSecondaryTables();
 		return join;
 	}
 
-	public void addProperty(Property prop) {
-		if ( prop.getValue() instanceof Component ) {
-			//TODO handle quote and non quote table comparison
-			String tableName = prop.getValue().getTable().getName();
-			if ( getJoinsPerRealTableName().containsKey( tableName ) ) {
-				getJoinsPerRealTableName().get( tableName ).addProperty( prop );
+	private void addPropertyToPersistentClass(Property prop, XClass declaringClass) {
+		if ( declaringClass != null ) {
+			final InheritanceState inheritanceState = inheritanceStatePerClass.get( declaringClass );
+			if ( inheritanceState == null ) {
+				throw new AssertionFailure(
+						"Declaring class is not found in the inheritance state hierarchy: " + declaringClass
+				);
 			}
+			if ( inheritanceState.isEmbeddableSuperclass ) {
+				persistentClass.addMappedsuperclassProperty(prop);
+				addPropertyToMappedSuperclass( prop, declaringClass );
+			}
 			else {
 				persistentClass.addProperty( prop );
 			}
@@ -98,6 +126,34 @@
 		}
 	}
 
+	private void addPropertyToMappedSuperclass(Property prop, XClass declaringClass) {
+		final ExtendedMappings mappings = getMappings();
+		final Class type = mappings.getReflectionManager().toClass( declaringClass );
+		MappedSuperclass superclass = mappings.getMappedSuperclass( type );
+		superclass.addProperty( prop );
+	}
+
+	private void addPropertyToJoin(Property prop, XClass declaringClass, Join join) {
+		if ( declaringClass != null ) {
+			final InheritanceState inheritanceState = inheritanceStatePerClass.get( declaringClass );
+			if ( inheritanceState == null ) {
+				throw new AssertionFailure(
+						"Declaring class is not found in the inheritance state hierarchy: " + declaringClass
+				);
+			}
+			if ( inheritanceState.isEmbeddableSuperclass ) {
+				join.addMappedsuperclassProperty(prop);
+				addPropertyToMappedSuperclass( prop, declaringClass );
+			}
+			else {
+				join.addProperty( prop );
+			}
+		}
+		else {
+			join.addProperty( prop );
+		}
+	}
+
 	/**
 	 * Needed for proper compliance with naming strategy, the property table
 	 * can be overriden if the properties are part of secondary tables

Modified: core/trunk/annotations/src/main/java/org/hibernate/cfg/CollectionPropertyHolder.java
===================================================================
--- core/trunk/annotations/src/main/java/org/hibernate/cfg/CollectionPropertyHolder.java	2009-10-28 18:03:10 UTC (rev 17870)
+++ core/trunk/annotations/src/main/java/org/hibernate/cfg/CollectionPropertyHolder.java	2009-10-28 18:14:25 UTC (rev 17871)
@@ -62,7 +62,7 @@
 		return collection.getCollectionTable();
 	}
 
-	public void addProperty(Property prop) {
+	public void addProperty(Property prop, XClass declaringClass) {
 		throw new AssertionFailure( "Cannot add property to a collection" );
 	}
 
@@ -86,7 +86,7 @@
 		return collection.getOwner().getEntityName();
 	}
 
-	public void addProperty(Property prop, Ejb3Column[] columns) {
+	public void addProperty(Property prop, Ejb3Column[] columns, XClass declaringClass) {
 		//Ejb3Column.checkPropertyConsistency( ); //already called earlier
 		throw new AssertionFailure( "addProperty to a join table of a collection: does it make sense?" );
 	}

Modified: core/trunk/annotations/src/main/java/org/hibernate/cfg/ComponentPropertyHolder.java
===================================================================
--- core/trunk/annotations/src/main/java/org/hibernate/cfg/ComponentPropertyHolder.java	2009-10-28 18:03:10 UTC (rev 17870)
+++ core/trunk/annotations/src/main/java/org/hibernate/cfg/ComponentPropertyHolder.java	2009-10-28 18:14:25 UTC (rev 17871)
@@ -28,6 +28,7 @@
 import javax.persistence.JoinTable;
 
 import org.hibernate.AnnotationException;
+import org.hibernate.annotations.common.reflection.XClass;
 import org.hibernate.mapping.Component;
 import org.hibernate.mapping.Join;
 import org.hibernate.mapping.KeyValue;
@@ -49,7 +50,7 @@
 		return component.getComponentClassName();
 	}
 
-	public void addProperty(Property prop, Ejb3Column[] columns) {
+	public void addProperty(Property prop, Ejb3Column[] columns, XClass declaringClass) {
 		//Ejb3Column.checkPropertyConsistency( ); //already called earlier
 		/*
 		 * Check table matches between the component and the columns
@@ -68,7 +69,7 @@
 				);
 			}
 		}
-		addProperty( prop );
+		addProperty( prop, declaringClass );
 	}
 
 	public Join addJoin(JoinTable joinTableAnn, boolean noDelayInPkColumnCreation) {
@@ -97,7 +98,7 @@
 		return component.getTable();
 	}
 
-	public void addProperty(Property prop) {
+	public void addProperty(Property prop, XClass declaringClass) {
 		component.addProperty( prop );
 	}
 

Modified: core/trunk/annotations/src/main/java/org/hibernate/cfg/Ejb3JoinColumn.java
===================================================================
--- core/trunk/annotations/src/main/java/org/hibernate/cfg/Ejb3JoinColumn.java	2009-10-28 18:03:10 UTC (rev 17870)
+++ core/trunk/annotations/src/main/java/org/hibernate/cfg/Ejb3JoinColumn.java	2009-10-28 18:14:25 UTC (rev 17871)
@@ -36,6 +36,7 @@
 import org.hibernate.annotations.JoinColumnOrFormula;
 import org.hibernate.annotations.JoinColumnsOrFormulas;
 import org.hibernate.annotations.JoinFormula;
+import org.hibernate.annotations.common.reflection.XClass;
 import org.hibernate.mapping.Column;
 import org.hibernate.mapping.Join;
 import org.hibernate.mapping.PersistentClass;
@@ -355,9 +356,11 @@
 	 * Override persistent class on oneToMany Cases for late settings
 	 * Must only be used on second level pass binding
 	 */
-	public void setPersistentClass(PersistentClass persistentClass, Map<String, Join> joins) {
+	public void setPersistentClass(PersistentClass persistentClass,
+								   Map<String, Join> joins,
+								   Map<XClass, InheritanceState> inheritanceStatePerClass) {
 		//FIXME shouldn't we deduce the classname from the persistentclasS?
-		this.propertyHolder = PropertyHolderBuilder.buildPropertyHolder( persistentClass, joins, getMappings() );
+		this.propertyHolder = PropertyHolderBuilder.buildPropertyHolder( persistentClass, joins, getMappings(), inheritanceStatePerClass );
 	}
 
 	public static void checkIfJoinColumn(Object columns, PropertyHolder holder, PropertyData property) {

Modified: core/trunk/annotations/src/main/java/org/hibernate/cfg/ExtendedMappings.java
===================================================================
--- core/trunk/annotations/src/main/java/org/hibernate/cfg/ExtendedMappings.java	2009-10-28 18:03:10 UTC (rev 17870)
+++ core/trunk/annotations/src/main/java/org/hibernate/cfg/ExtendedMappings.java	2009-10-28 18:14:25 UTC (rev 17871)
@@ -27,6 +27,8 @@
 import java.util.Map;
 import java.util.Properties;
 
+import javax.persistence.MappedSuperclass;
+
 import org.hibernate.AnnotationException;
 import org.hibernate.MappingException;
 import org.hibernate.annotations.AnyMetaDef;
@@ -124,6 +126,7 @@
 	public AnnotatedClassType getClassType(XClass clazz);
 
 	/**
+	 * FIXME should be private but will this break things?
 	 * Add a class type.
 	 *
 	 * @param clazz The XClass mapping.
@@ -157,6 +160,15 @@
 
 	public AnyMetaDef getAnyMetaDef(String name);
 	
-	public boolean isInSecondPass(); 
-	
+	public boolean isInSecondPass();
+
+	/**
+	 * add a new MappedSuperclass
+	 */
+	public void addMappedSuperclass(Class<?> type, org.hibernate.mapping.MappedSuperclass mappedSuperclass);
+
+	/**
+	 * Get a MappedSuperclass or null if not mapped
+	 */
+	org.hibernate.mapping.MappedSuperclass getMappedSuperclass(Class<?> type);
 }
\ No newline at end of file

Modified: core/trunk/annotations/src/main/java/org/hibernate/cfg/OneToOneSecondPass.java
===================================================================
--- core/trunk/annotations/src/main/java/org/hibernate/cfg/OneToOneSecondPass.java	2009-10-28 18:03:10 UTC (rev 17870)
+++ core/trunk/annotations/src/main/java/org/hibernate/cfg/OneToOneSecondPass.java	2009-10-28 18:14:25 UTC (rev 17871)
@@ -131,7 +131,7 @@
 						path, mappings
 				) ).doSecondPass( persistentClasses );
 				//no column associated since its a one to one
-				propertyHolder.addProperty( prop );
+				propertyHolder.addProperty( prop, inferredData.getDeclaringClass() );
 			}
 			else {
 				//this is a many to one with Formula
@@ -162,7 +162,7 @@
 				);
 			}
 			if ( otherSideProperty.getValue() instanceof OneToOne ) {
-				propertyHolder.addProperty( prop );
+				propertyHolder.addProperty( prop, inferredData.getDeclaringClass() );
 			}
 			else if ( otherSideProperty.getValue() instanceof ManyToOne ) {
 				Iterator it = otherSide.getJoinIterator();
@@ -208,7 +208,7 @@
 					mappedByJoin.addProperty( prop );
 				}
 				else {
-					propertyHolder.addProperty( prop );
+					propertyHolder.addProperty( prop, inferredData.getDeclaringClass() );
 				}
 
 				value.setReferencedPropertyName( mappedBy );

Modified: core/trunk/annotations/src/main/java/org/hibernate/cfg/PropertyData.java
===================================================================
--- core/trunk/annotations/src/main/java/org/hibernate/cfg/PropertyData.java	2009-10-28 18:03:10 UTC (rev 17870)
+++ core/trunk/annotations/src/main/java/org/hibernate/cfg/PropertyData.java	2009-10-28 18:14:25 UTC (rev 17871)
@@ -33,33 +33,43 @@
 	 * @return default member access (whether field or property)
 	 * @throws MappingException No getter or field found or wrong JavaBean spec usage
 	 */
-	public String getDefaultAccess();
+	String getDefaultAccess();
 
 	/**
 	 * @return property name
 	 * @throws MappingException No getter or field found or wrong JavaBean spec usage
 	 */
-	public String getPropertyName() throws MappingException;
+	String getPropertyName() throws MappingException;
 
 	/**
 	 * Returns the returned class itself or the element type if an array
 	 */
-	public XClass getClassOrElement() throws MappingException;
+	XClass getClassOrElement() throws MappingException;
 
 	/**
 	 * Return the class itself
 	 */
-	public XClass getPropertyClass() throws MappingException;
+	XClass getPropertyClass() throws MappingException;
 
 	/**
 	 * Returns the returned class name itself or the element type if an array
 	 */
-	public String getClassOrElementName() throws MappingException;
+	String getClassOrElementName() throws MappingException;
 
 	/**
 	 * Returns the returned class name itself
 	 */
-	public String getTypeName() throws MappingException;
+	String getTypeName() throws MappingException;
 
-	public XProperty getProperty();
+	/**
+	 * Return the Hibernate mapping property
+	 */
+	XProperty getProperty();
+
+	/**
+	 * Return the Class the property is declared on
+	 * If the property is declared on a @MappedSuperclass,
+	 * this class will be different than the PersistentClass's class
+	 */
+	XClass getDeclaringClass();
 }

Modified: core/trunk/annotations/src/main/java/org/hibernate/cfg/PropertyHolder.java
===================================================================
--- core/trunk/annotations/src/main/java/org/hibernate/cfg/PropertyHolder.java	2009-10-28 18:03:10 UTC (rev 17870)
+++ core/trunk/annotations/src/main/java/org/hibernate/cfg/PropertyHolder.java	2009-10-28 18:14:25 UTC (rev 17871)
@@ -32,6 +32,7 @@
 import org.hibernate.mapping.PersistentClass;
 import org.hibernate.mapping.Property;
 import org.hibernate.mapping.Table;
+import org.hibernate.annotations.common.reflection.XClass;
 
 /**
  * Property holder abstract property containers from their direct implementation
@@ -45,8 +46,10 @@
 
 	Table getTable();
 
-	void addProperty(Property prop);
+	void addProperty(Property prop, XClass declaringClass);
 
+	void addProperty(Property prop, Ejb3Column[] columns, XClass declaringClass);
+
 	KeyValue getIdentifier();
 
 	PersistentClass getPersistentClass();
@@ -71,7 +74,5 @@
 
 	String getEntityName();
 
-	void addProperty(Property prop, Ejb3Column[] columns);
-
 	Join addJoin(JoinTable joinTableAnn, boolean noDelayInPkColumnCreation);
 }

Modified: core/trunk/annotations/src/main/java/org/hibernate/cfg/PropertyHolderBuilder.java
===================================================================
--- core/trunk/annotations/src/main/java/org/hibernate/cfg/PropertyHolderBuilder.java	2009-10-28 18:03:10 UTC (rev 17870)
+++ core/trunk/annotations/src/main/java/org/hibernate/cfg/PropertyHolderBuilder.java	2009-10-28 18:14:25 UTC (rev 17871)
@@ -47,9 +47,10 @@
 			PersistentClass persistentClass,
 			EntityBinder entityBinder,
 			//Map<String, Join> joins,
-			ExtendedMappings mappings
+			ExtendedMappings mappings,
+			Map<XClass, InheritanceState> inheritanceStatePerClass
 	) {
-		return new ClassPropertyHolder( persistentClass, clazzToProcess, entityBinder, mappings );
+		return new ClassPropertyHolder( persistentClass, clazzToProcess, entityBinder, mappings, inheritanceStatePerClass );
 	}
 
 	/**
@@ -82,8 +83,9 @@
 	 */
 	public static PropertyHolder buildPropertyHolder(
 			PersistentClass persistentClass, Map<String, Join> joins,
-			ExtendedMappings mappings
+			ExtendedMappings mappings,
+			Map<XClass, InheritanceState> inheritanceStatePerClass
 	) {
-		return new ClassPropertyHolder( persistentClass, null, joins, mappings );
+		return new ClassPropertyHolder( persistentClass, null, joins, mappings, inheritanceStatePerClass );
 	}
 }

Modified: core/trunk/annotations/src/main/java/org/hibernate/cfg/PropertyInferredData.java
===================================================================
--- core/trunk/annotations/src/main/java/org/hibernate/cfg/PropertyInferredData.java	2009-10-28 18:03:10 UTC (rev 17870)
+++ core/trunk/annotations/src/main/java/org/hibernate/cfg/PropertyInferredData.java	2009-10-28 18:14:25 UTC (rev 17871)
@@ -41,11 +41,14 @@
 
 	private final XProperty property;
 	private final ReflectionManager reflectionManager;
+	private final XClass declaringClass;
 
+
 	/**
 	 * Take the annoted element for lazy process
 	 */
-	public PropertyInferredData(XProperty property, String propertyAccessor, ReflectionManager reflectionManager) {
+	public PropertyInferredData(XClass declaringClass, XProperty property, String propertyAccessor, ReflectionManager reflectionManager) {
+		this.declaringClass = declaringClass;
 		this.property = property;
 		this.defaultAccess = propertyAccessor;
 		this.reflectionManager = reflectionManager;
@@ -91,4 +94,8 @@
 	public XProperty getProperty() {
 		return property;
 	}
+
+	public XClass getDeclaringClass() {
+		return declaringClass;
+	}
 }

Modified: core/trunk/annotations/src/main/java/org/hibernate/cfg/PropertyPreloadedData.java
===================================================================
--- core/trunk/annotations/src/main/java/org/hibernate/cfg/PropertyPreloadedData.java	2009-10-28 18:03:10 UTC (rev 17870)
+++ core/trunk/annotations/src/main/java/org/hibernate/cfg/PropertyPreloadedData.java	2009-10-28 18:14:25 UTC (rev 17871)
@@ -67,4 +67,10 @@
 	public XProperty getProperty() {
 		return null; //instead of UnsupportedOperationException
 	}
+
+	public XClass getDeclaringClass() {
+		//Preloaded properties are artificial wrapper for colleciton element accesses
+		//and idClass creation, ignore.
+		return null;
+	}
 }

Modified: core/trunk/annotations/src/main/java/org/hibernate/cfg/WrappedInferredData.java
===================================================================
--- core/trunk/annotations/src/main/java/org/hibernate/cfg/WrappedInferredData.java	2009-10-28 18:03:10 UTC (rev 17870)
+++ core/trunk/annotations/src/main/java/org/hibernate/cfg/WrappedInferredData.java	2009-10-28 18:14:25 UTC (rev 17871)
@@ -51,6 +51,10 @@
 		return wrappedInferredData.getProperty();
 	}
 
+	public XClass getDeclaringClass() {
+		return wrappedInferredData.getDeclaringClass();
+	}
+
 	public XClass getPropertyClass() throws MappingException {
 		return wrappedInferredData.getPropertyClass();
 	}

Modified: core/trunk/annotations/src/main/java/org/hibernate/cfg/annotations/CollectionBinder.java
===================================================================
--- core/trunk/annotations/src/main/java/org/hibernate/cfg/annotations/CollectionBinder.java	2009-10-28 18:03:10 UTC (rev 17870)
+++ core/trunk/annotations/src/main/java/org/hibernate/cfg/annotations/CollectionBinder.java	2009-10-28 18:14:25 UTC (rev 17871)
@@ -32,17 +32,19 @@
 import java.util.StringTokenizer;
 import javax.persistence.AttributeOverride;
 import javax.persistence.AttributeOverrides;
+import javax.persistence.ElementCollection;
 import javax.persistence.Embeddable;
 import javax.persistence.FetchType;
 import javax.persistence.JoinTable;
 import javax.persistence.ManyToMany;
 import javax.persistence.MapKey;
+import javax.persistence.MapKeyColumn;
 import javax.persistence.OneToMany;
-import javax.persistence.ElementCollection;
-import javax.persistence.MapKeyColumn;
 
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
 import org.hibernate.AnnotationException;
-import org.hibernate.AssertionFailure;
 import org.hibernate.FetchMode;
 import org.hibernate.MappingException;
 import org.hibernate.annotations.BatchSize;
@@ -71,6 +73,7 @@
 import org.hibernate.annotations.SortType;
 import org.hibernate.annotations.Where;
 import org.hibernate.annotations.WhereJoinTable;
+import org.hibernate.annotations.common.AssertionFailure;
 import org.hibernate.annotations.common.reflection.XClass;
 import org.hibernate.annotations.common.reflection.XProperty;
 import org.hibernate.cfg.AnnotatedClassType;
@@ -81,6 +84,7 @@
 import org.hibernate.cfg.Ejb3JoinColumn;
 import org.hibernate.cfg.ExtendedMappings;
 import org.hibernate.cfg.IndexColumn;
+import org.hibernate.cfg.InheritanceState;
 import org.hibernate.cfg.PropertyData;
 import org.hibernate.cfg.PropertyHolder;
 import org.hibernate.cfg.PropertyHolderBuilder;
@@ -105,8 +109,6 @@
 import org.hibernate.mapping.SingleTableSubclass;
 import org.hibernate.mapping.Table;
 import org.hibernate.util.StringHelper;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
 
 /**
  * Base class for binding different types of collections to Hibernate configuration objects.
@@ -152,11 +154,18 @@
 	private Ejb3Column[] mapKeyColumns;
 	private Ejb3JoinColumn[] mapKeyManyToManyColumns;
 	protected HashMap<String, IdGenerator> localGenerators;
+	protected Map<XClass, InheritanceState> inheritanceStatePerClass;
+	private XClass declaringClass;
+	private boolean declaringClassSet;
 
 	public void setUpdatable(boolean updatable) {
 		this.updatable = updatable;
 	}
 
+	public void setInheritanceStatePerClass(Map<XClass, InheritanceState> inheritanceStatePerClass) {
+		this.inheritanceStatePerClass = inheritanceStatePerClass;
+	}
+
 	public void setInsertable(boolean insertable) {
 		this.insertable = insertable;
 	}
@@ -333,6 +342,11 @@
 		this.propertyName = propertyName;
 	}
 
+	public void setDeclaringClass(XClass declaringClass) {
+		this.declaringClass = declaringClass;
+		this.declaringClassSet = true;
+	}
+
 	public void bind() {
 		this.collection = createCollection( propertyHolder.getPersistentClass() );
 		log.debug( "Collection role: {}", StringHelper.qualify( propertyHolder.getPath(), propertyName ) );
@@ -443,6 +457,7 @@
 		}
 		//TODO reducce tableBinder != null and oneToMany
 		XClass collectionType = getCollectionType();
+		if ( inheritanceStatePerClass == null) throw new AssertionFailure( "inheritanceStatePerClass not set" );
 		SecondPass sp = getSecondPass(
 				fkJoinColumns,
 				joinColumns,
@@ -482,7 +497,8 @@
 		binder.setUpdatable( updatable );
 		Property prop = binder.make();
 		//we don't care about the join stuffs because the column is on the association table.
-		propertyHolder.addProperty( prop );
+		if (! declaringClassSet) throw new AssertionFailure( "DeclaringClass is not set in CollectionBinder while binding" );
+		propertyHolder.addProperty( prop, declaringClass );
 	}
 
 	private void defineFetchingStrategy() {
@@ -569,7 +585,6 @@
 			final boolean ignoreNotFound, final boolean unique,
 			final TableBinder assocTableBinder, final ExtendedMappings mappings
 	) {
-
 		return new CollectionSecondPass( mappings, collection ) {
 
 			public void secondPass(java.util.Map persistentClasses, java.util.Map inheritedMetas)
@@ -591,7 +606,8 @@
 			Ejb3JoinColumn[] keyColumns, Ejb3JoinColumn[] inverseColumns, Ejb3Column[] elementColumns,
 			boolean isEmbedded,
 			XProperty property, boolean unique,
-			TableBinder associationTableBinder, boolean ignoreNotFound, ExtendedMappings mappings
+			TableBinder associationTableBinder,
+			boolean ignoreNotFound, ExtendedMappings mappings
 	) {
 		PersistentClass persistentClass = (PersistentClass) persistentClasses.get( collType.getName() );
 		boolean reversePropertyInJoin = false;
@@ -627,7 +643,8 @@
 					collType,
 					cascadeDeleteEnabled,
 					ignoreNotFound, hqlOrderBy,
-					mappings
+					mappings,
+					inheritanceStatePerClass
 			);
 			return true;
 		}
@@ -651,7 +668,8 @@
 	protected void bindOneToManySecondPass(
 			Collection collection, Map persistentClasses, Ejb3JoinColumn[] fkJoinColumns,
 			XClass collectionType,
-			boolean cascadeDeleteEnabled, boolean ignoreNotFound, String hqlOrderBy, ExtendedMappings extendedMappings
+			boolean cascadeDeleteEnabled, boolean ignoreNotFound, String hqlOrderBy, ExtendedMappings extendedMappings,
+			Map<XClass, InheritanceState> inheritanceStatePerClass
 	) {
 
 		log.debug("Binding a OneToMany: {}.{} through a foreign key", propertyHolder.getEntityName(), propertyName);
@@ -677,7 +695,7 @@
 		}
 		oneToMany.setAssociatedClass( associatedClass );
 		for (Ejb3JoinColumn column : fkJoinColumns) {
-			column.setPersistentClass( associatedClass, joins );
+			column.setPersistentClass( associatedClass, joins, inheritanceStatePerClass );
 			column.setJoins( joins );
 			collection.setCollectionTable( column.getTable() );
 		}
@@ -1221,7 +1239,7 @@
 		else if ( anyAnn != null ) {
 			//@ManyToAny
 			//Make sure that collTyp is never used during the @ManyToAny branch: it will be set to void.class
-			PropertyData inferredData = new PropertyInferredData( property, "unsupported", mappings.getReflectionManager() );
+			PropertyData inferredData = new PropertyInferredData(null, property, "unsupported", mappings.getReflectionManager() );
 			//override the table
 			for (Ejb3Column column : inverseJoinColumns) {
 				column.setTable( collValue.getCollectionTable() );
@@ -1284,7 +1302,7 @@
 				Component component = AnnotationBinder.fillComponent(
 						holder, inferredData, isPropertyAnnotated, isPropertyAnnotated ? "property" : "field", true,
 						entityBinder, false, false,
-						true, mappings
+						true, mappings, inheritanceStatePerClass
 				);
 
 				collValue.setElement( component );

Modified: core/trunk/annotations/src/main/java/org/hibernate/cfg/annotations/IdBagBinder.java
===================================================================
--- core/trunk/annotations/src/main/java/org/hibernate/cfg/annotations/IdBagBinder.java	2009-10-28 18:03:10 UTC (rev 17870)
+++ core/trunk/annotations/src/main/java/org/hibernate/cfg/annotations/IdBagBinder.java	2009-10-28 18:14:25 UTC (rev 17871)
@@ -68,7 +68,7 @@
 			SimpleValueBinder simpleValue = new SimpleValueBinder();
 
 			PropertyData propertyData = new WrappedInferredData(
-					new PropertyInferredData( property, null, //default access should not be useful
+					new PropertyInferredData( null, property, null, //default access should not be useful
 							mappings.getReflectionManager() ),
 					"id" );
 			Ejb3Column[] idColumns = Ejb3Column.buildColumnFromAnnotation(

Modified: core/trunk/annotations/src/main/java/org/hibernate/cfg/annotations/ListBinder.java
===================================================================
--- core/trunk/annotations/src/main/java/org/hibernate/cfg/annotations/ListBinder.java	2009-10-28 18:03:10 UTC (rev 17870)
+++ core/trunk/annotations/src/main/java/org/hibernate/cfg/annotations/ListBinder.java	2009-10-28 18:14:25 UTC (rev 17871)
@@ -25,13 +25,15 @@
 
 import java.util.Map;
 
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
 import org.hibernate.AnnotationException;
 import org.hibernate.MappingException;
 import org.hibernate.annotations.OrderBy;
 import org.hibernate.annotations.Sort;
 import org.hibernate.annotations.common.reflection.XClass;
 import org.hibernate.annotations.common.reflection.XProperty;
-import org.hibernate.util.StringHelper;
 import org.hibernate.cfg.CollectionSecondPass;
 import org.hibernate.cfg.Ejb3Column;
 import org.hibernate.cfg.Ejb3JoinColumn;
@@ -45,8 +47,7 @@
 import org.hibernate.mapping.OneToMany;
 import org.hibernate.mapping.PersistentClass;
 import org.hibernate.mapping.SimpleValue;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
+import org.hibernate.util.StringHelper;
 
 /**
  * Bind a list to the underlying Hibernate configuration

Modified: core/trunk/annotations/src/main/java/org/hibernate/cfg/annotations/MapBinder.java
===================================================================
--- core/trunk/annotations/src/main/java/org/hibernate/cfg/annotations/MapBinder.java	2009-10-28 18:03:10 UTC (rev 17870)
+++ core/trunk/annotations/src/main/java/org/hibernate/cfg/annotations/MapBinder.java	2009-10-28 18:14:25 UTC (rev 17871)
@@ -35,8 +35,8 @@
 import org.hibernate.AssertionFailure;
 import org.hibernate.FetchMode;
 import org.hibernate.MappingException;
+import org.hibernate.annotations.MapKey;
 import org.hibernate.annotations.MapKeyManyToMany;
-import org.hibernate.annotations.MapKey;
 import org.hibernate.annotations.common.reflection.XClass;
 import org.hibernate.annotations.common.reflection.XProperty;
 import org.hibernate.cfg.AnnotatedClassType;
@@ -232,7 +232,7 @@
 					Component component = AnnotationBinder.fillComponent(
 							holder, inferredData, isPropertyAnnotated, isPropertyAnnotated ? "property" : "field", true,
 							entityBinder, false, false,
-							true, mappings
+							true, mappings, inheritanceStatePerClass
 					);
 					mapValue.setIndex( component );
 				}

Modified: core/trunk/annotations/src/main/java/org/hibernate/cfg/annotations/PropertyBinder.java
===================================================================
--- core/trunk/annotations/src/main/java/org/hibernate/cfg/annotations/PropertyBinder.java	2009-10-28 18:03:10 UTC (rev 17870)
+++ core/trunk/annotations/src/main/java/org/hibernate/cfg/annotations/PropertyBinder.java	2009-10-28 18:14:25 UTC (rev 17871)
@@ -34,6 +34,7 @@
 import org.hibernate.annotations.OptimisticLock;
 import org.hibernate.annotations.common.reflection.XClass;
 import org.hibernate.annotations.common.reflection.XProperty;
+import org.hibernate.annotations.common.AssertionFailure;
 import org.hibernate.cfg.Ejb3Column;
 import org.hibernate.cfg.ExtendedMappings;
 import org.hibernate.cfg.PropertyHolder;
@@ -62,6 +63,8 @@
 	private boolean updatable = true;
 	private String cascade;
 	private SimpleValueBinder simpleValueBinder;
+	private XClass declaringClass;
+	private boolean declaringClassSet;
 	
 	/*
 	 * property can be null
@@ -118,11 +121,19 @@
 		this.mappings = mappings;
 	}
 
+	public void setDeclaringClass(XClass declaringClass) {
+		this.declaringClass = declaringClass;
+		this.declaringClassSet = true;
+	}
+
 	private void validateBind() {
 		if (property.isAnnotationPresent(Immutable.class)) {
 			throw new AnnotationException("@Immutable on property not allowed. " +
 					"Only allowed on entity level or on a collection.");
-		}	
+		}
+		if ( !declaringClassSet ) {
+			throw new AssertionFailure( "declaringClass has not been set before a bind");
+		}
 	}
 
 	private void validateMake() {
@@ -146,7 +157,7 @@
 		SimpleValue propertyValue = simpleValueBinder.make();
 		setValue( propertyValue );
 		Property prop = make();
-		holder.addProperty( prop, columns );
+		holder.addProperty( prop, columns, declaringClass );
 		return prop;
 	}
 

Modified: core/trunk/core/src/main/java/org/hibernate/mapping/Join.java
===================================================================
--- core/trunk/core/src/main/java/org/hibernate/mapping/Join.java	2009-10-28 18:03:10 UTC (rev 17870)
+++ core/trunk/core/src/main/java/org/hibernate/mapping/Join.java	2009-10-28 18:14:25 UTC (rev 17871)
@@ -39,6 +39,7 @@
 	private static final Alias PK_ALIAS = new Alias(15, "PK");
 
 	private ArrayList properties = new ArrayList();
+	private ArrayList declaredProperties = new ArrayList();
 	private Table table;
 	private KeyValue key;
 	private PersistentClass persistentClass;
@@ -59,8 +60,18 @@
 
 	public void addProperty(Property prop) {
 		properties.add(prop);
+		declaredProperties.add(prop);
 		prop.setPersistentClass( getPersistentClass() );
 	}
+	public void addMappedsuperclassProperty(Property prop) {
+		properties.add(prop);
+		prop.setPersistentClass( getPersistentClass() );
+	}
+
+	public Iterator getDeclaredPropertyIterator() {
+		return declaredProperties.iterator();
+	}
+
 	public boolean containsProperty(Property prop) {
 		return properties.contains(prop);
 	}

Added: core/trunk/core/src/main/java/org/hibernate/mapping/MappedSuperclass.java
===================================================================
--- core/trunk/core/src/main/java/org/hibernate/mapping/MappedSuperclass.java	                        (rev 0)
+++ core/trunk/core/src/main/java/org/hibernate/mapping/MappedSuperclass.java	2009-10-28 18:14:25 UTC (rev 17871)
@@ -0,0 +1,67 @@
+package org.hibernate.mapping;
+
+import java.util.*;
+import java.util.List;
+
+/**
+ * Represents a @MappedSuperclass.
+ * A @MappedSuperclass can be a superclass of an @Entity (root or not)
+ *
+ * This class primary goal is to give a representation to @MappedSuperclass
+ * in the metamodel in order to reflect them in the JPA 2 metamodel.
+ *
+ * Do not use outside this use case.
+ *
+ * A proper redesign will be evluated in Hibernate 4
+ *
+ * @author Emmanuel Bernard
+ */
+public class MappedSuperclass {
+	private final MappedSuperclass superMappedSuperclass;
+	private final PersistentClass superPersistentClass;
+	private final List properties;
+
+	public MappedSuperclass(MappedSuperclass superMappedSuperclass, PersistentClass superPersistentClass) {
+		this.superMappedSuperclass = superMappedSuperclass;
+		this.superPersistentClass = superPersistentClass;
+		this.properties = new ArrayList();
+	}
+
+	/**
+	 * Returns the first superclass marked as @MappedSuperclass or null if:
+	 *  - none exists
+	 *  - or the first persistent superclass found is an @Entity
+	 *
+	 * @return the super MappedSuperclass
+	 */
+	public MappedSuperclass getSuperMappedSuperclass() {
+		return superMappedSuperclass;
+	}
+
+	/**
+	 * Returns the PersistentClass of the first superclass marked as @Entity
+	 * or null if none exists
+	 *
+	 * @return the PersistentClass of the superclass
+	 */
+	public PersistentClass getSuperPersistentClass() {
+		return superPersistentClass;
+	}
+
+	public Iterator getPropertyIterator() {
+		return properties.iterator();
+	}
+
+	public void addProperty(Property p) {
+		//Do not add duplicate properties
+		//TODO is it efficient enough?
+		String name = p.getName();
+		Iterator it = properties.iterator();
+		while (it.hasNext()) {
+			if ( name.equals( ((Property)it.next()).getName() ) ) {
+				return;
+			}
+		}
+		properties.add(p);
+	}
+}

Modified: core/trunk/core/src/main/java/org/hibernate/mapping/PersistentClass.java
===================================================================
--- core/trunk/core/src/main/java/org/hibernate/mapping/PersistentClass.java	2009-10-28 18:03:10 UTC (rev 17870)
+++ core/trunk/core/src/main/java/org/hibernate/mapping/PersistentClass.java	2009-10-28 18:14:25 UTC (rev 17871)
@@ -62,6 +62,7 @@
 	private String discriminatorValue;
 	private boolean lazy;
 	private ArrayList properties = new ArrayList();
+	private ArrayList declaredProperties = new ArrayList();
 	private final ArrayList subclasses = new ArrayList();
 	private final ArrayList subclassProperties = new ArrayList();
 	private final ArrayList subclassTables = new ArrayList();
@@ -96,6 +97,7 @@
 	private java.util.Map tuplizerImpls;
 
 	protected int optimisticLockMode;
+	private MappedSuperclass superMappedSuperclass;
 
 	public String getClassName() {
 		return className;
@@ -221,6 +223,7 @@
 
 	public void addProperty(Property p) {
 		properties.add(p);
+		declaredProperties.add(p);
 		p.setPersistentClass(this);
 	}
 
@@ -811,4 +814,31 @@
 	}
 
 	public abstract boolean isLazyPropertiesCacheable();
+
+	// The following methods are added to support @MappedSuperclass in the metamodel
+	public Iterator getDeclaredPropertyIterator() {
+		ArrayList iterators = new ArrayList();
+		iterators.add( declaredProperties.iterator() );
+		for ( int i = 0; i < joins.size(); i++ ) {
+			Join join = ( Join ) joins.get( i );
+			iterators.add( join.getDeclaredPropertyIterator() );
+		}
+		return new JoinedIterator( iterators );
+	}
+
+	public void addMappedsuperclassProperty(Property p) {
+		properties.add(p);
+		p.setPersistentClass(this);
+	}
+
+	public MappedSuperclass getSuperMappedSuperclass() {
+		return superMappedSuperclass;
+	}
+
+	public void setSuperMappedSuperclass(MappedSuperclass superMappedSuperclass) {
+		this.superMappedSuperclass = superMappedSuperclass;
+	}
+
+	// End of @Mappedsuperclass support
+
 }
\ No newline at end of file

Modified: core/trunk/core/src/main/java/org/hibernate/mapping/Subclass.java
===================================================================
--- core/trunk/core/src/main/java/org/hibernate/mapping/Subclass.java	2009-10-28 18:03:10 UTC (rev 17870)
+++ core/trunk/core/src/main/java/org/hibernate/mapping/Subclass.java	2009-10-28 18:14:25 UTC (rev 17871)
@@ -93,6 +93,12 @@
 		super.addProperty(p);
 		getSuperclass().addSubclassProperty(p);
 	}
+
+	public void addMappedsuperClassProperty(Property p) {
+		super.addMappedsuperclassProperty( p );
+		getSuperclass().addSubclassProperty(p);
+	}
+
 	public void addJoin(Join j) {
 		super.addJoin(j);
 		getSuperclass().addSubclassJoin(j);



More information about the hibernate-commits mailing list