/* * 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 javax.persistence.EntityManagerFactory; import javax.persistence.metamodel.Attribute; import javax.persistence.metamodel.Bindable; import javax.persistence.metamodel.EmbeddableType; import javax.persistence.metamodel.EntityType; import javax.persistence.metamodel.IdentifiableType; import javax.persistence.metamodel.ListAttribute; import javax.persistence.metamodel.MapAttribute; import javax.persistence.metamodel.MappedSuperclassType; import javax.persistence.metamodel.PluralAttribute; import javax.persistence.metamodel.SetAttribute; import javax.persistence.metamodel.SingularAttribute; import javax.persistence.metamodel.Type; import java.util.Set; import org.hibernate.cfg.Configuration; import org.hibernate.ejb.metamodel.MetamodelImpl; import org.hibernate.ejb.test.BaseEntityManagerFunctionalTestCase; import org.hibernate.engine.spi.SessionFactoryImplementor; import org.junit.Test; import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertFalse; import static org.junit.Assert.assertNotNull; import static org.junit.Assert.assertNull; import static org.junit.Assert.assertSame; import static org.junit.Assert.assertTrue; import static org.junit.Assert.fail; /** * @author Emmanuel Bernard */ public class MetadataTest extends BaseEntityManagerFunctionalTestCase { @Test public void testBaseOfService() throws Exception { EntityManagerFactory emf = entityManagerFactory(); assertNotNull( emf.getMetamodel() ); final EntityType<Fridge> entityType = emf.getMetamodel().entity( Fridge.class ); assertNotNull( entityType ); } @Test @SuppressWarnings({ "unchecked" }) public void testBuildingMetamodelWithParameterizedCollection() { Configuration cfg = new Configuration( ); // configure( cfg ); cfg.addAnnotatedClass( WithGenericCollection.class ); cfg.buildMappings(); SessionFactoryImplementor sfi = (SessionFactoryImplementor) cfg.buildSessionFactory( serviceRegistry() ); MetamodelImpl.buildMetamodel( cfg.getClassMappings(), sfi ); } @Test public void testLogicalManyToOne() throws Exception { final EntityType<JoinedManyToOneOwner> entityType = entityManagerFactory().getMetamodel().entity( JoinedManyToOneOwner.class ); final SingularAttribute attr = entityType.getDeclaredSingularAttribute( "house" ); assertEquals( Attribute.PersistentAttributeType.MANY_TO_ONE, attr.getPersistentAttributeType() ); assertEquals( House.class, attr.getBindableJavaType() ); final EntityType<House> houseType = entityManagerFactory().getMetamodel().entity( House.class ); assertEquals( houseType.getBindableJavaType(), attr.getBindableJavaType() ); } @Test public void testEntity() throws Exception { final EntityType<Fridge> fridgeType = entityManagerFactory().getMetamodel().entity( Fridge.class ); assertEquals( Fridge.class, fridgeType.getBindableJavaType() ); assertEquals( Bindable.BindableType.ENTITY_TYPE, fridgeType.getBindableType() ); SingularAttribute<Fridge,Integer> wrapped = fridgeType.getDeclaredSingularAttribute( "temperature", Integer.class ); assertNotNull( wrapped ); SingularAttribute<Fridge,Integer> primitive = fridgeType.getDeclaredSingularAttribute( "temperature", int.class ); assertNotNull( primitive ); assertNotNull( fridgeType.getDeclaredSingularAttribute( "temperature" ) ); assertNotNull( fridgeType.getDeclaredAttribute( "temperature" ) ); final SingularAttribute<Fridge, Long> id = fridgeType.getDeclaredId( Long.class ); assertNotNull( id ); assertTrue( id.isId() ); try { fridgeType.getDeclaredId( java.util.Date.class ); fail( "expecting failure" ); } catch ( IllegalArgumentException ignore ) { // expected result } final SingularAttribute<? super Fridge, Long> id2 = fridgeType.getId( Long.class ); assertNotNull( id2 ); assertEquals( "Fridge", fridgeType.getName() ); assertEquals( Long.class, fridgeType.getIdType().getJavaType() ); assertTrue( fridgeType.hasSingleIdAttribute() ); assertFalse( fridgeType.hasVersionAttribute() ); assertEquals( Type.PersistenceType.ENTITY, fridgeType.getPersistenceType() ); assertEquals( 3, fridgeType.getDeclaredAttributes().size() ); final EntityType<House> houseType = entityManagerFactory().getMetamodel().entity( House.class ); assertEquals( "org.hibernate.ejb.test.metadata.House", houseType.getName() ); assertTrue( houseType.hasSingleIdAttribute() ); final SingularAttribute<House, House.Key> houseId = houseType.getDeclaredId( House.Key.class ); assertNotNull( houseId ); assertTrue( houseId.isId() ); assertEquals( Attribute.PersistentAttributeType.EMBEDDED, houseId.getPersistentAttributeType() ); final EntityType<Person> personType = entityManagerFactory().getMetamodel().entity( Person.class ); assertEquals( "Homo", personType.getName() ); assertFalse( personType.hasSingleIdAttribute() ); final Set<SingularAttribute<? super Person,?>> ids = personType.getIdClassAttributes(); assertNotNull( ids ); assertEquals( 2, ids.size() ); for (SingularAttribute<? super Person,?> localId : ids) { assertTrue( localId.isId() ); assertSame( personType, localId.getDeclaringType() ); assertSame( localId, personType.getDeclaredAttribute( localId.getName() ) ); assertSame( localId, personType.getDeclaredSingularAttribute( localId.getName() ) ); assertSame( localId, personType.getAttribute( localId.getName() ) ); assertSame( localId, personType.getSingularAttribute( localId.getName() ) ); assertTrue( personType.getAttributes().contains( localId ) ); } final EntityType<Giant> giantType = entityManagerFactory().getMetamodel().entity( Giant.class ); assertEquals( "HomoGigantus", giantType.getName() ); assertFalse( giantType.hasSingleIdAttribute() ); final Set<SingularAttribute<? super Giant,?>> giantIds = giantType.getIdClassAttributes(); assertNotNull( giantIds ); assertEquals( 2, giantIds.size() ); assertEquals( personType.getIdClassAttributes(), giantIds ); for (SingularAttribute<? super Giant,?> localGiantId : giantIds) { assertTrue( localGiantId.isId() ); try { giantType.getDeclaredAttribute( localGiantId.getName() ); fail( localGiantId.getName() + " is a declared attribute, but shouldn't be"); } catch ( IllegalArgumentException ex) { // expected } try { giantType.getDeclaredSingularAttribute( localGiantId.getName() ); fail( localGiantId.getName() + " is a declared singular attribute, but shouldn't be"); } catch ( IllegalArgumentException ex) { // expected } assertSame( localGiantId, giantType.getAttribute( localGiantId.getName() ) ); assertTrue( giantType.getAttributes().contains( localGiantId ) ); } final EntityType<FoodItem> foodType = entityManagerFactory().getMetamodel().entity( FoodItem.class ); assertTrue( foodType.hasVersionAttribute() ); final SingularAttribute<? super FoodItem, Long> version = foodType.getVersion( Long.class ); assertNotNull( version ); assertTrue( version.isVersion() ); assertEquals( 3, foodType.getDeclaredAttributes().size() ); } @Test public void testBasic() throws Exception { final EntityType<Fridge> entityType = entityManagerFactory().getMetamodel().entity( Fridge.class ); final SingularAttribute<? super Fridge,Integer> singularAttribute = entityType.getDeclaredSingularAttribute( "temperature", Integer.class ); // assertEquals( Integer.class, singularAttribute.getBindableJavaType() ); // assertEquals( Integer.class, singularAttribute.getType().getJavaType() ); assertEquals( int.class, singularAttribute.getBindableJavaType() ); assertEquals( int.class, singularAttribute.getType().getJavaType() ); assertEquals( Bindable.BindableType.SINGULAR_ATTRIBUTE, singularAttribute.getBindableType() ); assertFalse( singularAttribute.isId() ); assertFalse( singularAttribute.isOptional() ); assertFalse( entityType.getDeclaredSingularAttribute( "brand", String.class ).isOptional() ); assertEquals( Type.PersistenceType.BASIC, singularAttribute.getType().getPersistenceType() ); final Attribute<? super Fridge, ?> attribute = entityType.getDeclaredAttribute( "temperature" ); assertNotNull( attribute ); assertEquals( "temperature", attribute.getName() ); assertEquals( Fridge.class, attribute.getDeclaringType().getJavaType() ); assertEquals( Attribute.PersistentAttributeType.BASIC, attribute.getPersistentAttributeType() ); // assertEquals( Integer.class, attribute.getJavaType() ); assertEquals( int.class, attribute.getJavaType() ); assertFalse( attribute.isAssociation() ); assertFalse( attribute.isCollection() ); boolean found = false; for (Attribute<Fridge, ?> attr : entityType.getDeclaredAttributes() ) { if ("temperature".equals( attr.getName() ) ) { found = true; break; } } assertTrue( found ); } @Test public void testEmbeddable() throws Exception { final EntityType<House> entityType = entityManagerFactory().getMetamodel().entity( House.class ); final SingularAttribute<? super House,Address> address = entityType.getDeclaredSingularAttribute( "address", Address.class ); assertNotNull( address ); assertEquals( Attribute.PersistentAttributeType.EMBEDDED, address.getPersistentAttributeType() ); assertFalse( address.isCollection() ); assertFalse( address.isAssociation() ); final EmbeddableType<Address> addressType = (EmbeddableType<Address>) address.getType(); assertEquals( Type.PersistenceType.EMBEDDABLE, addressType.getPersistenceType() ); assertEquals( 3, addressType.getDeclaredAttributes().size() ); assertTrue( addressType.getDeclaredSingularAttribute( "address1" ).isOptional() ); assertFalse( addressType.getDeclaredSingularAttribute( "address2" ).isOptional() ); final EmbeddableType<Address> directType = entityManagerFactory().getMetamodel().embeddable( Address.class ); assertNotNull( directType ); assertEquals( Type.PersistenceType.EMBEDDABLE, directType.getPersistenceType() ); } @Test public void testCollection() throws Exception { final EntityType<Garden> entiytype = entityManagerFactory().getMetamodel().entity( Garden.class ); final Set<PluralAttribute<? super Garden, ?, ?>> attributes = entiytype.getPluralAttributes(); assertEquals( 1, attributes.size() ); PluralAttribute<? super Garden, ?, ?> flowers = attributes.iterator().next(); assertTrue( flowers instanceof ListAttribute ); } @Test public void testElementCollection() throws Exception { final EntityType<House> entityType = entityManagerFactory().getMetamodel().entity( House.class ); final SetAttribute<House,Room> rooms = entityType.getDeclaredSet( "rooms", Room.class ); assertNotNull( rooms ); assertTrue( rooms.isAssociation() ); assertTrue( rooms.isCollection() ); assertEquals( Attribute.PersistentAttributeType.ELEMENT_COLLECTION, rooms.getPersistentAttributeType() ); assertEquals( Room.class, rooms.getBindableJavaType() ); assertEquals( Bindable.BindableType.PLURAL_ATTRIBUTE, rooms.getBindableType() ); assertEquals( Set.class, rooms.getJavaType() ); assertEquals( PluralAttribute.CollectionType.SET, rooms.getCollectionType() ); assertEquals( 3, entityType.getDeclaredPluralAttributes().size() ); assertEquals( Type.PersistenceType.EMBEDDABLE, rooms.getElementType().getPersistenceType() ); final MapAttribute<House,String,Room> roomsByName = entityType.getDeclaredMap( "roomsByName", String.class, Room.class ); assertNotNull( roomsByName ); assertEquals( String.class, roomsByName.getKeyJavaType() ); assertEquals( Type.PersistenceType.BASIC, roomsByName.getKeyType().getPersistenceType() ); assertEquals( PluralAttribute.CollectionType.MAP, roomsByName.getCollectionType() ); final ListAttribute<House,Room> roomsBySize = entityType.getDeclaredList( "roomsBySize", Room.class ); assertNotNull( roomsBySize ); assertEquals( Type.PersistenceType.EMBEDDABLE, roomsBySize.getElementType().getPersistenceType() ); assertEquals( PluralAttribute.CollectionType.LIST, roomsBySize.getCollectionType() ); } @Test public void testHierarchy() { final EntityType<Cat> cat = entityManagerFactory().getMetamodel().entity( Cat.class ); assertNotNull( cat ); assertEquals( 7, cat.getAttributes().size() ); assertEquals( 1, cat.getDeclaredAttributes().size() ); ensureProperMember(cat.getDeclaredAttributes()); assertTrue( cat.hasVersionAttribute() ); assertEquals( "version", cat.getVersion(Long.class).getName() ); verifyDeclaredVersionNotPresent( cat ); verifyDeclaredIdNotPresentAndIdPresent(cat); assertEquals( Type.PersistenceType.MAPPED_SUPERCLASS, cat.getSupertype().getPersistenceType() ); MappedSuperclassType<Cattish> cattish = (MappedSuperclassType<Cattish>) cat.getSupertype(); assertEquals( 6, cattish.getAttributes().size() ); assertEquals( 1, cattish.getDeclaredAttributes().size() ); ensureProperMember(cattish.getDeclaredAttributes()); assertTrue( cattish.hasVersionAttribute() ); assertEquals( "version", cattish.getVersion(Long.class).getName() ); verifyDeclaredVersionNotPresent( cattish ); verifyDeclaredIdNotPresentAndIdPresent(cattish); assertEquals( Type.PersistenceType.ENTITY, cattish.getSupertype().getPersistenceType() ); EntityType<Feline> feline = (EntityType<Feline>) cattish.getSupertype(); assertEquals( 5, feline.getAttributes().size() ); assertEquals( 1, feline.getDeclaredAttributes().size() ); ensureProperMember(feline.getDeclaredAttributes()); assertTrue( feline.hasVersionAttribute() ); assertEquals( "version", feline.getVersion(Long.class).getName() ); verifyDeclaredVersionNotPresent( feline ); verifyDeclaredIdNotPresentAndIdPresent(feline); assertEquals( Type.PersistenceType.MAPPED_SUPERCLASS, feline.getSupertype().getPersistenceType() ); MappedSuperclassType<Animal> animal = (MappedSuperclassType<Animal>) feline.getSupertype(); assertEquals( 4, animal.getAttributes().size() ); assertEquals( 2, animal.getDeclaredAttributes().size() ); ensureProperMember(animal.getDeclaredAttributes()); assertTrue( animal.hasVersionAttribute() ); assertEquals( "version", animal.getVersion(Long.class).getName() ); verifyDeclaredVersionNotPresent( animal ); assertEquals( "id", animal.getId(Long.class).getName() ); final SingularAttribute<Animal, Long> id = animal.getDeclaredId( Long.class ); assertEquals( "id", id.getName() ); assertNotNull( id.getJavaMember() ); assertEquals( Type.PersistenceType.MAPPED_SUPERCLASS, animal.getSupertype().getPersistenceType() ); MappedSuperclassType<Thing> thing = (MappedSuperclassType<Thing>) animal.getSupertype(); assertEquals( 2, thing.getAttributes().size() ); assertEquals( 2, thing.getDeclaredAttributes().size() ); ensureProperMember(thing.getDeclaredAttributes()); final SingularAttribute<Thing, Double> weight = thing.getDeclaredSingularAttribute( "weight", Double.class ); assertEquals( Double.class, weight.getJavaType() ); assertEquals( "version", thing.getVersion(Long.class).getName() ); final SingularAttribute<Thing, Long> version = thing.getDeclaredVersion( Long.class ); assertEquals( "version", version.getName() ); assertNotNull( version.getJavaMember() ); assertNull( thing.getId( Long.class ) ); assertNull( thing.getSupertype() ); } @Test public void testBackrefAndGenerics() throws Exception { final EntityType<Parent> parent = entityManagerFactory().getMetamodel().entity( Parent.class ); assertNotNull( parent ); final SetAttribute<? super Parent, ?> children = parent.getSet( "children" ); assertNotNull( children ); assertEquals( 1, parent.getPluralAttributes().size() ); assertEquals( 4, parent.getAttributes().size() ); final EntityType<Child> child = entityManagerFactory().getMetamodel().entity( Child.class ); assertNotNull( child ); assertEquals( 2, child.getAttributes().size() ); final SingularAttribute<? super Parent, Parent.Relatives> attribute = parent.getSingularAttribute( "siblings", Parent.Relatives.class ); final EmbeddableType<Parent.Relatives> siblings = (EmbeddableType<Parent.Relatives>) attribute.getType(); assertNotNull(siblings); final SetAttribute<? super Parent.Relatives, ?> siblingsCollection = siblings.getSet( "siblings" ); assertNotNull( siblingsCollection ); final Type<?> collectionElement = siblingsCollection.getElementType(); assertNotNull( collectionElement ); assertEquals( collectionElement, child ); } private void ensureProperMember(Set<?> attributes) { //we do not update the set so we are safe @SuppressWarnings( "unchecked" ) final Set<Attribute<?, ?>> safeAttributes = ( Set<Attribute<?, ?>> ) attributes; for (Attribute<?,?> attribute : safeAttributes ) { final String name = attribute.getJavaMember().getName(); assertNotNull( attribute.getJavaMember() ); assertTrue( name.toLowerCase().endsWith( attribute.getName().toLowerCase() ) ); } } private void verifyDeclaredIdNotPresentAndIdPresent(IdentifiableType<?> type) { assertEquals( "id", type.getId(Long.class).getName() ); try { type.getDeclaredId(Long.class); fail("Should not have a declared id"); } catch (IllegalArgumentException e) { //success } } private void verifyDeclaredVersionNotPresent(IdentifiableType<?> type) { try { type.getDeclaredVersion(Long.class); fail("Should not have a declared version"); } catch (IllegalArgumentException e) { //success } } //todo test plural @Override public Class[] getAnnotatedClasses() { return new Class[]{ Fridge.class, FoodItem.class, Person.class, Giant.class, House.class, Dog.class, Cat.class, Cattish.class, Feline.class, Garden.class, Flower.class, JoinedManyToOneOwner.class, Parent.class, Child.class }; } }