HHH-4202 - Implement JPA 2.0 metamodel APIs

git-svn-id: https://svn.jboss.org/repos/hibernate/core/trunk@17886 1b8cb986-b30d-0410-93ca-fae66ebed9b2
This commit is contained in:
Steve Ebersole 2009-11-02 16:46:17 +00:00
parent 2dc911855b
commit 255b7076b8
9 changed files with 345 additions and 3 deletions

View File

@ -189,6 +189,10 @@ public abstract class AbstractIdentifiableType<X>
return isVersioned; return isVersioned;
} }
public boolean hasDeclaredVersionAttribute() {
return isVersioned && version != null;
}
/** /**
* {@inheritDoc} * {@inheritDoc}
*/ */
@ -222,6 +226,16 @@ public abstract class AbstractIdentifiableType<X>
return ( SingularAttribute<X, Y> ) version; return ( SingularAttribute<X, Y> ) version;
} }
/**
* For used to retrieve the declared version when populating the static metamodel.
*
* @return The declared
*/
public SingularAttribute<X, ?> getDeclaredVersion() {
checkDeclaredVersion();
return version;
}
/** /**
* Centralized check to ensure the version (if one) is actually declared on the class mapped here, as opposed to a * Centralized check to ensure the version (if one) is actually declared on the class mapped here, as opposed to a
* super class. * super class.

View File

@ -29,16 +29,17 @@ import java.util.Map;
import java.util.Set; import java.util.Set;
import java.util.List; import java.util.List;
import java.util.ArrayList; import java.util.ArrayList;
import java.lang.reflect.Field;
import javax.persistence.metamodel.Attribute; import javax.persistence.metamodel.Attribute;
import javax.persistence.metamodel.SingularAttribute; import javax.persistence.metamodel.SingularAttribute;
import javax.swing.*; import javax.persistence.metamodel.IdentifiableType;
import org.hibernate.mapping.MappedSuperclass; import org.hibernate.mapping.MappedSuperclass;
import org.hibernate.mapping.PersistentClass; import org.hibernate.mapping.PersistentClass;
import org.hibernate.mapping.Property; import org.hibernate.mapping.Property;
import org.hibernate.mapping.Component;
import org.hibernate.engine.SessionFactoryImplementor; import org.hibernate.engine.SessionFactoryImplementor;
import org.hibernate.annotations.common.AssertionFailure; import org.hibernate.annotations.common.AssertionFailure;
import org.hibernate.AnnotationException;
/** /**
* Defines a context for storing information during the building of the {@link MetamodelImpl}. * Defines a context for storing information during the building of the {@link MetamodelImpl}.
@ -163,6 +164,12 @@ class MetadataContext {
Iterator<Property> properties = ( Iterator<Property> ) safeMapping.getDeclaredPropertyIterator(); Iterator<Property> properties = ( Iterator<Property> ) safeMapping.getDeclaredPropertyIterator();
while ( properties.hasNext() ) { while ( properties.hasNext() ) {
final Property property = properties.next(); final Property property = properties.next();
if ( property.getValue() == safeMapping.getIdentifierMapper() ) {
// property represents special handling for id-class mappings but we have already
// accounted for the embedded property mappings in #applyIdMetadata &&
// #buildIdClassAttributes
continue;
}
final Attribute attribute = attributeFactory.buildAttribute( jpa2Mapping, property, true ); final Attribute attribute = attributeFactory.buildAttribute( jpa2Mapping, property, true );
jpa2Mapping.getBuilder().addAttribute( attribute ); jpa2Mapping.getBuilder().addAttribute( attribute );
} }
@ -190,8 +197,13 @@ class MetadataContext {
throw new AssertionFailure( "Unexpected mapping type: " + mapping.getClass() ); throw new AssertionFailure( "Unexpected mapping type: " + mapping.getClass() );
} }
} }
for ( EmbeddableTypeImpl embeddable : embeddables.values() ) {
populateStaticMetamodel( embeddable );
}
} }
private <X> void applyIdMetadata(PersistentClass persistentClass, EntityTypeImpl<X> jpaEntityType) { private <X> void applyIdMetadata(PersistentClass persistentClass, EntityTypeImpl<X> jpaEntityType) {
if ( persistentClass.hasIdentifierProperty() ) { if ( persistentClass.hasIdentifierProperty() ) {
final Property declaredIdentifierProperty = persistentClass.getDeclaredIdentifierProperty(); final Property declaredIdentifierProperty = persistentClass.getDeclaredIdentifierProperty();
@ -289,11 +301,55 @@ class MetadataContext {
private final Set<Class> processedMetamodelClasses = new HashSet<Class>(); private final Set<Class> processedMetamodelClasses = new HashSet<Class>();
private <X> void registerAttributes(Class metamodelClass, AbstractManagedType<X> managedType) { private <X> void registerAttributes(Class metamodelClass, AbstractManagedType<X> managedType) {
if ( processedMetamodelClasses.add( metamodelClass ) ) { if ( ! processedMetamodelClasses.add( metamodelClass ) ) {
return; return;
} }
// push the attributes on to the metamodel class... // push the attributes on to the metamodel class...
for ( Attribute<X, ?> attribute : managedType.getDeclaredAttributes() ) {
registerAttribute( metamodelClass, attribute );
}
if ( IdentifiableType.class.isInstance( managedType ) ) {
final AbstractIdentifiableType<X> entityType = ( AbstractIdentifiableType<X> ) managedType;
// handle version
if ( entityType.hasDeclaredVersionAttribute() ) {
registerAttribute( metamodelClass, entityType.getDeclaredVersion() );
}
// handle id-class mappings specially
if ( ! entityType.hasSingleIdAttribute() ) {
final Set<SingularAttribute<? super X, ?>> attributes = entityType.getIdClassAttributes();
if ( attributes != null ) {
for ( SingularAttribute<? super X, ?> attribute : attributes ) {
registerAttribute( metamodelClass, attribute );
}
}
}
}
}
private <X> void registerAttribute(Class metamodelClass, Attribute<X, ?> attribute) {
final String name = attribute.getName();
try {
Field field = metamodelClass.getDeclaredField( name );
field.setAccessible( true ); // should be public anyway, but to be sure...
field.set( null, attribute );
}
catch ( NoSuchFieldException e ) {
// todo : exception type?
throw new AssertionFailure(
"Unable to locate static metamodel field : " + metamodelClass.getName() + '#' + name
);
}
catch ( IllegalAccessException e ) {
// todo : exception type?
throw new AssertionFailure(
"Unable to inject static metamodel attribute : " + metamodelClass.getName() + '#' + name,
e
);
}
} }
public MappedSuperclassTypeImpl<?> locateMappedSuperclassType(MappedSuperclass mappedSuperclass) { public MappedSuperclassTypeImpl<?> locateMappedSuperclassType(MappedSuperclass mappedSuperclass) {

View File

@ -1,3 +1,26 @@
/*
* Hibernate, Relational Persistence for Idiomatic Java
*
* Copyright (c) 2009 by Red Hat Inc and/or its affiliates or by
* third-party contributors as indicated by either @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.ejb.test.metadata; package org.hibernate.ejb.test.metadata;
import javax.persistence.MappedSuperclass; import javax.persistence.MappedSuperclass;

View File

@ -1,3 +1,26 @@
/*
* Hibernate, Relational Persistence for Idiomatic Java
*
* Copyright (c) 2009 by Red Hat Inc and/or its affiliates or by
* third-party contributors as indicated by either @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.ejb.test.metadata; package org.hibernate.ejb.test.metadata;
import javax.persistence.Entity; import javax.persistence.Entity;

View File

@ -1,3 +1,26 @@
/*
* Hibernate, Relational Persistence for Idiomatic Java
*
* Copyright (c) 2009 by Red Hat Inc and/or its affiliates or by
* third-party contributors as indicated by either @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.ejb.test.metadata; package org.hibernate.ejb.test.metadata;
import javax.persistence.MappedSuperclass; import javax.persistence.MappedSuperclass;

View File

@ -1,3 +1,26 @@
/*
* Hibernate, Relational Persistence for Idiomatic Java
*
* Copyright (c) 2009 by Red Hat Inc and/or its affiliates or by
* third-party contributors as indicated by either @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.ejb.test.metadata; package org.hibernate.ejb.test.metadata;
import javax.persistence.Entity; import javax.persistence.Entity;

View File

@ -1,3 +1,26 @@
/*
* Hibernate, Relational Persistence for Idiomatic Java
*
* Copyright (c) 2009 by Red Hat Inc and/or its affiliates or by
* third-party contributors as indicated by either @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.ejb.test.metadata; package org.hibernate.ejb.test.metadata;
import javax.persistence.Entity; import javax.persistence.Entity;

View File

@ -0,0 +1,134 @@
/*
* Hibernate, Relational Persistence for Idiomatic Java
*
* Copyright (c) 2009 by Red Hat Inc and/or its affiliates or by
* third-party contributors as indicated by either @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.ejb.test.metadata;
import java.util.Set;
import javax.persistence.metamodel.Attribute;
import javax.persistence.metamodel.Bindable;
import javax.persistence.metamodel.EmbeddableType;
import javax.persistence.metamodel.PluralAttribute;
import javax.persistence.metamodel.Type;
import org.hibernate.ejb.test.TestCase;
/**
* @author Steve Ebersole
*/
public class StaticMetadataTest extends TestCase {
public void testInjections() throws Exception {
// Address (embeddable)
assertNotNull( Address_.address1 );
assertNotNull( Address_.address2 );
assertNotNull( Address_.city );
final EmbeddableType<Address> addressType = (EmbeddableType<Address>) House_.address.getType();
assertEquals( addressType.getDeclaredSingularAttribute( "address1" ), Address_.address1 );
assertEquals( addressType.getDeclaredSingularAttribute( "address2" ), Address_.address2 );
assertTrue( Address_.address1.isOptional() );
assertFalse( Address_.address2.isOptional() );
// Animal (mapped superclass)
assertNotNull( Animal_.id );
assertTrue( Animal_.id.isId() );
assertEquals( Long.class, Animal_.id.getJavaType() );
assertNotNull( Animal_.legNbr );
assertEquals( Integer.class, Animal_.legNbr.getJavaType() );
// Cat (hierarchy)
assertNotNull( Cat_.id );
assertNotNull( Cat_.id.isId() );
assertEquals( Animal.class, Cat_.id.getJavaMember().getDeclaringClass() );
assertNotNull( Cat_.nickname );
// FoodItem
assertNotNull( FoodItem_.version );
assertTrue( FoodItem_.version.isVersion() );
// Fridge
assertNotNull( Fridge_.id );
assertTrue( Fridge_.id.isId() );
assertEquals( Long.class, Fridge_.id.getJavaType() );
assertNotNull( Fridge_.temperature );
assertEquals( "temperature", Fridge_.temperature.getName() );
assertEquals( Fridge.class, Fridge_.temperature.getDeclaringType().getJavaType() );
assertEquals( Integer.class, Fridge_.temperature.getJavaType() );
assertEquals( Integer.class, Fridge_.temperature.getBindableJavaType() );
assertEquals( Integer.class, Fridge_.temperature.getType().getJavaType() );
assertEquals( Bindable.BindableType.SINGULAR_ATTRIBUTE, Fridge_.temperature.getBindableType() );
assertEquals( Type.PersistenceType.BASIC, Fridge_.temperature.getType().getPersistenceType() );
assertEquals( Attribute.PersistentAttributeType.BASIC, Fridge_.temperature.getPersistentAttributeType() );
assertFalse( Fridge_.temperature.isId() );
assertFalse( Fridge_.temperature.isOptional() );
assertFalse( Fridge_.temperature.isAssociation() );
assertFalse( Fridge_.temperature.isCollection() );
assertFalse( Fridge_.brand.isOptional() );
// House (embedded id)
assertNotNull( House_.key );
assertTrue( House_.key.isId() );
assertEquals( Attribute.PersistentAttributeType.EMBEDDED, House_.key.getPersistentAttributeType() );
assertNotNull( House_.address );
assertEquals( Attribute.PersistentAttributeType.EMBEDDED, House_.address.getPersistentAttributeType() );
assertFalse( House_.address.isCollection() );
assertFalse( House_.address.isAssociation() );
assertNotNull( House_.rooms );
assertTrue( House_.rooms.isAssociation() );
assertTrue( House_.rooms.isCollection() );
assertEquals( Attribute.PersistentAttributeType.ELEMENT_COLLECTION, House_.rooms.getPersistentAttributeType() );
assertEquals( Room.class, House_.rooms.getBindableJavaType() );
assertEquals( Bindable.BindableType.PLURAL_ATTRIBUTE, House_.rooms.getBindableType() );
assertEquals( Set.class, House_.rooms.getJavaType() );
assertEquals( PluralAttribute.CollectionType.SET, House_.rooms.getCollectionType() );
assertEquals( Type.PersistenceType.EMBEDDABLE, House_.rooms.getElementType().getPersistenceType() );
assertNotNull( House_.roomsByName );
assertEquals( String.class, House_.roomsByName.getKeyJavaType() );
assertEquals( Type.PersistenceType.BASIC, House_.roomsByName.getKeyType().getPersistenceType() );
assertEquals( PluralAttribute.CollectionType.MAP, House_.roomsByName.getCollectionType() );
assertNotNull( House_.roomsBySize );
assertEquals( Type.PersistenceType.EMBEDDABLE, House_.roomsBySize.getElementType().getPersistenceType() );
assertEquals( PluralAttribute.CollectionType.LIST, House_.roomsBySize.getCollectionType() );
// Person (mapped id)
assertNotNull( Person_.firstName );
assertNotNull( Person_.lastName );
assertTrue( Person_.firstName.isId() );
assertTrue( Person_.lastName.isId() );
assertTrue( Person_.lastName.isId() );
}
@Override
public Class[] getAnnotatedClasses() {
return new Class[]{
Fridge.class,
FoodItem.class,
Person.class,
House.class,
Dog.class,
Cat.class,
Cattish.class,
Feline.class
};
}
}

View File

@ -1,3 +1,26 @@
/*
* Hibernate, Relational Persistence for Idiomatic Java
*
* Copyright (c) 2009 by Red Hat Inc and/or its affiliates or by
* third-party contributors as indicated by either @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.ejb.test.metadata; package org.hibernate.ejb.test.metadata;
import javax.persistence.MappedSuperclass; import javax.persistence.MappedSuperclass;