From b687bbeb9b26acffa6aaa5a25ab4554c116f7395 Mon Sep 17 00:00:00 2001 From: Steve Ebersole Date: Mon, 26 Oct 2009 05:23:40 +0000 Subject: [PATCH] HHH-4202 - Implement JPA 2.0 metamodel APIs git-svn-id: https://svn.jboss.org/repos/hibernate/core/trunk@17836 1b8cb986-b30d-0410-93ca-fae66ebed9b2 --- .../ejb/metamodel/AbstractAttribute.java | 142 +++++ .../metamodel/AbstractIdentifiableType.java | 243 +++++++++ .../ejb/metamodel/AbstractManagedType.java | 494 ++++++++++++++++++ .../hibernate/ejb/metamodel/AbstractType.java | 44 ++ ...odelFactory.java => AttributeFactory.java} | 309 +++++------ .../ejb/metamodel/AttributeImplementor.java | 34 ++ .../ejb/metamodel/EmbeddableTypeImpl.java | 9 +- .../ejb/metamodel/EntityTypeDelegator.java | 217 -------- .../ejb/metamodel/EntityTypeImpl.java | 162 +----- .../ejb/metamodel/ManagedTypeImpl.java | 309 ----------- .../ejb/metamodel/MetadataContext.java | 145 ++++- .../ejb/metamodel/MetamodelImpl.java | 57 +- .../ejb/metamodel/PluralAttributeImpl.java | 123 +++-- .../ejb/metamodel/SingularAttributeImpl.java | 174 +++--- 14 files changed, 1434 insertions(+), 1028 deletions(-) create mode 100644 entitymanager/src/main/java/org/hibernate/ejb/metamodel/AbstractAttribute.java create mode 100644 entitymanager/src/main/java/org/hibernate/ejb/metamodel/AbstractIdentifiableType.java create mode 100644 entitymanager/src/main/java/org/hibernate/ejb/metamodel/AbstractManagedType.java create mode 100644 entitymanager/src/main/java/org/hibernate/ejb/metamodel/AbstractType.java rename entitymanager/src/main/java/org/hibernate/ejb/metamodel/{MetamodelFactory.java => AttributeFactory.java} (51%) create mode 100644 entitymanager/src/main/java/org/hibernate/ejb/metamodel/AttributeImplementor.java delete mode 100644 entitymanager/src/main/java/org/hibernate/ejb/metamodel/EntityTypeDelegator.java delete mode 100644 entitymanager/src/main/java/org/hibernate/ejb/metamodel/ManagedTypeImpl.java diff --git a/entitymanager/src/main/java/org/hibernate/ejb/metamodel/AbstractAttribute.java b/entitymanager/src/main/java/org/hibernate/ejb/metamodel/AbstractAttribute.java new file mode 100644 index 0000000000..ef48c39713 --- /dev/null +++ b/entitymanager/src/main/java/org/hibernate/ejb/metamodel/AbstractAttribute.java @@ -0,0 +1,142 @@ +/* + * 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.metamodel; + +import java.lang.reflect.Member; +import java.lang.reflect.Method; +import java.io.ObjectInputStream; +import java.io.IOException; +import java.io.ObjectOutputStream; +import java.io.Serializable; +import javax.persistence.metamodel.Attribute; +import javax.persistence.metamodel.ManagedType; + +import org.hibernate.util.ReflectHelper; + +/** + * Models the commonality of the JPA {@link Attribute} hierarchy. + * + * @author Steve Ebersole + */ +public abstract class AbstractAttribute + implements Attribute, AttributeImplementor, Serializable { + private final String name; + private final Class javaType; + private final AbstractManagedType declaringType; + private transient Member member; + private final PersistentAttributeType persistentAttributeType; + + public AbstractAttribute( + String name, + Class javaType, + AbstractManagedType declaringType, + Member member, + PersistentAttributeType persistentAttributeType) { + this.name = name; + this.javaType = javaType; + this.declaringType = declaringType; + this.member = member; + this.persistentAttributeType = persistentAttributeType; + } + + /** + * {@inheritDoc} + */ + public String getName() { + return name; + } + + /** + * {@inheritDoc} + */ + public ManagedType getDeclaringType() { + return declaringType; + } + + /** + * {@inheritDoc} + */ + public Class getJavaType() { + return javaType; + } + + /** + * {@inheritDoc} + */ + public Member getJavaMember() { + return member; + } + + /** + * {@inheritDoc} + */ + public PersistentAttributeType getPersistentAttributeType() { + return persistentAttributeType; + } + + /** + * Used by JDK serialization... + * + * @param ois The input stream from which we are being read... + * @throws java.io.IOException Indicates a general IO stream exception + * @throws ClassNotFoundException Indicates a class resolution issue + */ + protected void readObject(ObjectInputStream ois) throws IOException, ClassNotFoundException { + ois.defaultReadObject(); + final String memberDeclaringClassName = ( String ) ois.readObject(); + final String memberName = ( String ) ois.readObject(); + final String memberType = ( String ) ois.readObject(); + + final Class memberDeclaringClass = Class.forName( + memberDeclaringClassName, + false, + declaringType.getJavaType().getClassLoader() + ); + try { + this.member = "method".equals( memberType ) + ? memberDeclaringClass.getMethod( memberName, ReflectHelper.NO_PARAM_SIGNATURE ) + : memberDeclaringClass.getField( memberName ); + } + catch ( Exception e ) { + throw new IllegalStateException( + "Unable to locate member [" + memberDeclaringClassName + "#" + + memberName + "]" + ); + } + } + + /** + * Used by JDK serialization... + * + * @param oos The output stream to which we are being written... + * @throws IOException Indicates a general IO stream exception + */ + protected void writeObject(ObjectOutputStream oos) throws IOException { + oos.defaultWriteObject(); + oos.writeObject( getJavaMember().getDeclaringClass().getName() ); + oos.writeObject( getJavaMember().getName() ); + // should only ever be a field or the getter-method... + oos.writeObject( Method.class.isInstance( getJavaMember() ) ? "method" : "field" ); + } +} diff --git a/entitymanager/src/main/java/org/hibernate/ejb/metamodel/AbstractIdentifiableType.java b/entitymanager/src/main/java/org/hibernate/ejb/metamodel/AbstractIdentifiableType.java new file mode 100644 index 0000000000..f093fdeeae --- /dev/null +++ b/entitymanager/src/main/java/org/hibernate/ejb/metamodel/AbstractIdentifiableType.java @@ -0,0 +1,243 @@ +/* + * 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.metamodel; + +import java.io.Serializable; +import java.util.Set; +import javax.persistence.metamodel.IdentifiableType; +import javax.persistence.metamodel.SingularAttribute; +import javax.persistence.metamodel.Type; +import javax.persistence.metamodel.Attribute; + +/** + * Defines commonality for the JPA {@link IdentifiableType} types. JPA defines + * identifiable types as entities or mapped-superclasses. Basically things to which an + * identifier can be attached. + *

+ * NOTE : Currently we only really have support for direct entities in the Hibernate metamodel + * as the information for them is consumed into the closest actual entity subclass(es) in the + * internal Hibernate mapping-metamodel. + * + * @author Steve Ebersole + */ +public abstract class AbstractIdentifiableType + extends AbstractManagedType + implements IdentifiableType, Serializable { + + private final boolean hasIdentifierProperty; + private final boolean isVersioned; + + private SingularAttributeImpl id; + private SingularAttributeImpl version; + private Set> idClassAttributes; + + public AbstractIdentifiableType( + Class javaType, + AbstractIdentifiableType superType, + boolean hasIdentifierProperty, + boolean versioned) { + super( javaType, superType ); + this.hasIdentifierProperty = hasIdentifierProperty; + isVersioned = versioned; + } + + /** + * {@inheritDoc} + */ + public AbstractIdentifiableType getSupertype() { + return ( AbstractIdentifiableType ) super.getSupertype(); + } + + protected AbstractIdentifiableType requireSupertype() { + if ( getSupertype() == null ) { + throw new IllegalStateException( "No supertype found" ); + } + return getSupertype(); + } + + /** + * {@inheritDoc} + */ + public boolean hasSingleIdAttribute() { + return hasIdentifierProperty; + } + + /** + * {@inheritDoc} + */ + @SuppressWarnings({ "unchecked" }) + public SingularAttribute getId(Class type) { + final SingularAttribute id_; + if ( id != null ) { + checkSimpleId(); + id_ = ( SingularAttribute ) id; + } + else { + id_ = requireSupertype().getId( type ); + } + // TODO : check that type and id_.getJavaType() are related + return id_; + } + + /** + * Centralized check to ensure the id for this hierarchy is a simple one (i.e., does not use + * an id-class). + * + * @see #checkIdClass() + */ + protected void checkSimpleId() { + if ( ! hasIdentifierProperty ) { + throw new IllegalStateException( "This class uses an @IdClass" ); + } + } + + + /** + * {@inheritDoc} + */ + @SuppressWarnings({ "unchecked" }) + public SingularAttribute getDeclaredId(Class yClass) { + checkDeclaredId(); + checkSimpleId(); + // TODO : check that type and id.getJavaType() are related + return (SingularAttribute) id; + } + + /** + * Centralized check to ensure the id is actually declared on the class mapped here, as opposed to a + * super class. + */ + protected void checkDeclaredId() { + if ( id == null ) { + throw new IllegalArgumentException( "The id attribute is not declared on this type" ); + } + } + + /** + * {@inheritDoc} + */ + public Type getIdType() { + if ( id != null ) { + checkSimpleId(); + return id.getType(); + } + else { + return requireSupertype().getIdType(); + } + } + + /** + * {@inheritDoc} + */ + public Set> getIdClassAttributes() { + checkIdClass(); + return idClassAttributes; + } + + /** + * Centralized check to ensure the id for this hierarchy uses an id-class. + * + * @see #checkSimpleId() + */ + private void checkIdClass() { + if ( hasIdentifierProperty ) { + throw new IllegalArgumentException( "This class does not use @IdClass" ); + } + } + + /** + * {@inheritDoc} + */ + public boolean hasVersionAttribute() { + return isVersioned; + } + + /** + * {@inheritDoc} + */ + @SuppressWarnings({ "unchecked" }) + public SingularAttribute getVersion(Class type) { + if ( ! hasVersionAttribute() ) { + return null; + } + final SingularAttribute version_; + if ( version != null ) { + version_ = ( SingularAttribute ) version; + } + else { + version_ = requireSupertype().getVersion( type ); + } + // TODO : check that type and version_.getJavaType() are related + return version_; + } + + /** + * {@inheritDoc} + */ + @SuppressWarnings({ "unchecked" }) + public SingularAttribute getDeclaredVersion(Class yClass) { + checkDeclaredVersion(); + // TODO : check that type and version_.getJavaType() are related + return ( SingularAttribute ) version; + } + + /** + * Centralized check to ensure the version (if one) is actually declared on the class mapped here, as opposed to a + * super class. + */ + protected void checkDeclaredVersion() { + if ( version == null ) { + if ( getSupertype() != null && getSupertype().hasVersionAttribute() ) { + throw new IllegalArgumentException( "The version attribute is not declared on this type" ); + } + } + } + + public Builder getBuilder() { + final AbstractManagedType.Builder managedBuilder = super.getBuilder(); + return new Builder() { + public void applyIdAttribute(SingularAttributeImpl idAttribute) { + AbstractIdentifiableType.this.id = idAttribute; + } + + public void applyIdClassAttributes(Set> idClassAttributes) { + AbstractIdentifiableType.this.idClassAttributes = idClassAttributes; + } + + public void applyVersionAttribute(SingularAttributeImpl versionAttribute) { + AbstractIdentifiableType.this.version = versionAttribute; + } + + public void addAttribute(Attribute attribute) { + managedBuilder.addAttribute( attribute ); + } + }; + } + + public static interface Builder extends AbstractManagedType.Builder { + public void applyIdAttribute(SingularAttributeImpl idAttribute); + public void applyIdClassAttributes(Set> idClassAttributes); + public void applyVersionAttribute(SingularAttributeImpl versionAttribute); + } +} diff --git a/entitymanager/src/main/java/org/hibernate/ejb/metamodel/AbstractManagedType.java b/entitymanager/src/main/java/org/hibernate/ejb/metamodel/AbstractManagedType.java new file mode 100644 index 0000000000..5577d9c301 --- /dev/null +++ b/entitymanager/src/main/java/org/hibernate/ejb/metamodel/AbstractManagedType.java @@ -0,0 +1,494 @@ +/* + * 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.metamodel; + +import java.io.Serializable; +import java.util.Map; +import java.util.HashMap; +import java.util.Set; +import java.util.HashSet; +import javax.persistence.metamodel.ManagedType; +import javax.persistence.metamodel.Attribute; +import javax.persistence.metamodel.SingularAttribute; +import javax.persistence.metamodel.PluralAttribute; +import javax.persistence.metamodel.Bindable; +import javax.persistence.metamodel.CollectionAttribute; +import javax.persistence.metamodel.SetAttribute; +import javax.persistence.metamodel.ListAttribute; +import javax.persistence.metamodel.MapAttribute; + +import org.hibernate.annotations.common.AssertionFailure; + +/** + * Defines commonality for the JPA {@link ManagedType} hierarchy of interfaces. + * + * @author Steve Ebersole + */ +public abstract class AbstractManagedType + extends AbstractType + implements ManagedType, Serializable { + + private final AbstractManagedType superType; + + private final Map> declaredAttributes + = new HashMap>(); + private final Map> declaredSingularAttributes + = new HashMap>(); + private final Map> declaredPluralAttributes + = new HashMap>(); + + protected AbstractManagedType(Class javaType, AbstractManagedType superType) { + super( javaType ); + this.superType = superType; + } + + protected AbstractManagedType getSupertype() { + return superType; + } + + private boolean locked = false; + + public Builder getBuilder() { + if ( locked ) { + throw new IllegalStateException( "Type has been locked" ); + } + return new Builder() { + public void addAttribute(Attribute attribute) { + declaredAttributes.put( attribute.getName(), attribute ); + final Bindable.BindableType bindableType = ( ( Bindable ) attribute ).getBindableType(); + switch ( bindableType ) { + case SINGULAR_ATTRIBUTE : { + declaredSingularAttributes.put( attribute.getName(), (SingularAttribute) attribute ); + break; + } + case PLURAL_ATTRIBUTE : { + declaredPluralAttributes.put(attribute.getName(), (PluralAttribute) attribute ); + break; + } + default : { + throw new AssertionFailure( "unknown bindable type: " + bindableType ); + } + } + } + }; + } + + public void lock() { + locked = true; + } + + public static interface Builder { + public void addAttribute(Attribute attribute); + } + + + /** + * {@inheritDoc} + */ + @SuppressWarnings({ "unchecked" }) + public Set> getAttributes() { + HashSet attributes = new HashSet>( declaredAttributes.values() ); + if ( getSupertype() != null ) { + attributes.addAll( getSupertype().getAttributes() ); + } + return attributes; + } + + /** + * {@inheritDoc} + */ + public Set> getDeclaredAttributes() { + return new HashSet>( declaredAttributes.values() ); + } + + /** + * {@inheritDoc} + */ + @SuppressWarnings({ "unchecked" }) + public Attribute getAttribute(String name) { + Attribute attribute = declaredAttributes.get( name ); + if ( attribute == null && getSupertype() != null ) { + attribute = getSupertype().getAttribute( name ); + } + return attribute; + } + + /** + * {@inheritDoc} + */ + public Attribute getDeclaredAttribute(String name) { + final Attribute attr = declaredSingularAttributes.get( name ); + checkNotNull( "Attribute ", attr, name ); + return attr; + } + + private void checkNotNull(String attributeType, Attribute attribute, String name) { + if ( attribute == null ) { + throw new IllegalArgumentException( attributeType + " named " + name + " is not present" ); + } + } + + /** + * {@inheritDoc} + */ + @SuppressWarnings({ "unchecked" }) + public Set> getSingularAttributes() { + HashSet attributes = new HashSet>( declaredSingularAttributes.values() ); + if ( getSupertype() != null ) { + attributes.addAll( getSupertype().getSingularAttributes() ); + } + return attributes; + } + + /** + * {@inheritDoc} + */ + public Set> getDeclaredSingularAttributes() { + return new HashSet>( declaredSingularAttributes.values() ); + } + + /** + * {@inheritDoc} + */ + @SuppressWarnings({ "unchecked" }) + public SingularAttribute getSingularAttribute(String name) { + SingularAttribute attribute = declaredSingularAttributes.get( name ); + if ( attribute == null && getSupertype() != null ) { + attribute = getSupertype().getSingularAttribute( name ); + } + return attribute; + } + + /** + * {@inheritDoc} + */ + public SingularAttribute getDeclaredSingularAttribute(String name) { + final SingularAttribute attr = declaredSingularAttributes.get( name ); + checkNotNull( "SingularAttribute ", attr, name ); + return attr; + } + + /** + * {@inheritDoc} + */ + @SuppressWarnings({ "unchecked" }) + public SingularAttribute getSingularAttribute(String name, Class type) { + SingularAttribute attribute = declaredSingularAttributes.get( name ); + if ( attribute == null && getSupertype() != null ) { + attribute = getSupertype().getSingularAttribute( name ); + } + checkTypeForSingleAttribute( "SingularAttribute ", attribute, name, type ); + return ( SingularAttribute ) attribute; + } + + /** + * {@inheritDoc} + */ + @SuppressWarnings( "unchecked") + public SingularAttribute getDeclaredSingularAttribute(String name, Class javaType) { + final SingularAttribute attr = declaredSingularAttributes.get( name ); + checkTypeForSingleAttribute( "SingularAttribute ", attr, name, javaType ); + return ( SingularAttribute ) attr; + } + + private void checkTypeForSingleAttribute( + String attributeType, + SingularAttribute attribute, + String name, + Class javaType) { + if ( attribute == null || ( javaType != null && !attribute.getBindableJavaType().equals( javaType ) ) ) { + throw new IllegalArgumentException( + attributeType + " named " + name + + ( javaType != null ? " and of type " + javaType.getName() : "" ) + + " is not present" + ); + } + } + + /** + * {@inheritDoc} + */ + @SuppressWarnings({ "unchecked" }) + public Set> getPluralAttributes() { + HashSet attributes = new HashSet>( declaredPluralAttributes.values() ); + if ( getSupertype() != null ) { + attributes.addAll( getSupertype().getPluralAttributes() ); + } + return attributes; + } + + /** + * {@inheritDoc} + */ + public Set> getDeclaredPluralAttributes() { + return new HashSet>( declaredPluralAttributes.values() ); + } + + /** + * {@inheritDoc} + */ + @SuppressWarnings({ "unchecked" }) + public CollectionAttribute getCollection(String name) { + PluralAttribute attribute = getPluralAttribute( name ); + if ( attribute == null && getSupertype() != null ) { + attribute = getSupertype().getPluralAttribute( name ); + } + basicCollectionCheck( attribute, name ); + return ( CollectionAttribute ) attribute; + } + + private PluralAttribute getPluralAttribute(String name) { + return declaredPluralAttributes.get( name ); + } + + private void basicCollectionCheck(PluralAttribute attribute, String name) { + checkNotNull( "CollectionAttribute", attribute, name ); + if ( ! CollectionAttribute.class.isAssignableFrom( attribute.getClass() ) ) { + throw new IllegalArgumentException( name + " is not a CollectionAttribute: " + attribute.getClass() ); + } + } + + /** + * {@inheritDoc} + */ + @SuppressWarnings( "unchecked") + public CollectionAttribute getDeclaredCollection(String name) { + final PluralAttribute attribute = declaredPluralAttributes.get( name ); + basicCollectionCheck( attribute, name ); + return ( CollectionAttribute ) attribute; + } + + /** + * {@inheritDoc} + */ + @SuppressWarnings({ "unchecked" }) + public SetAttribute getSet(String name) { + PluralAttribute attribute = getPluralAttribute( name ); + if ( attribute == null && getSupertype() != null ) { + attribute = getSupertype().getPluralAttribute( name ); + } + basicSetCheck( attribute, name ); + return (SetAttribute) attribute; + } + + private void basicSetCheck(PluralAttribute attribute, String name) { + checkNotNull( "SetAttribute", attribute, name ); + if ( ! SetAttribute.class.isAssignableFrom( attribute.getClass() ) ) { + throw new IllegalArgumentException( name + " is not a SetAttribute: " + attribute.getClass() ); + } + } + + /** + * {@inheritDoc} + */ + @SuppressWarnings( "unchecked") + public SetAttribute getDeclaredSet(String name) { + final PluralAttribute attribute = declaredPluralAttributes.get( name ); + basicSetCheck( attribute, name ); + return ( SetAttribute ) attribute; + } + + /** + * {@inheritDoc} + */ + @SuppressWarnings({ "unchecked" }) + public ListAttribute getList(String name) { + PluralAttribute attribute = getPluralAttribute( name ); + if ( attribute == null && getSupertype() != null ) { + attribute = getSupertype().getPluralAttribute( name ); + } + basicListCheck( attribute, name ); + return (ListAttribute) attribute; + } + + private void basicListCheck(PluralAttribute attribute, String name) { + checkNotNull( "ListAttribute", attribute, name ); + if ( ! ListAttribute.class.isAssignableFrom( attribute.getClass() ) ) { + throw new IllegalArgumentException( name + " is not a ListAttribute: " + attribute.getClass() ); + } + } + + /** + * {@inheritDoc} + */ + public ListAttribute getDeclaredList(String name) { + final PluralAttribute attribute = declaredPluralAttributes.get( name ); + basicListCheck( attribute, name ); + return ( ListAttribute ) attribute; + } + + /** + * {@inheritDoc} + */ + @SuppressWarnings({ "unchecked" }) + public MapAttribute getMap(String name) { + PluralAttribute attribute = getPluralAttribute( name ); + if ( attribute == null && getSupertype() != null ) { + attribute = getSupertype().getPluralAttribute( name ); + } + basicMapCheck( attribute, name ); + return (MapAttribute) attribute; + } + + private void basicMapCheck(PluralAttribute attribute, String name) { + checkNotNull( "MapAttribute", attribute, name ); + if ( ! MapAttribute.class.isAssignableFrom( attribute.getClass() ) ) { + throw new IllegalArgumentException( name + " is not a MapAttribute: " + attribute.getClass() ); + } + } + + /** + * {@inheritDoc} + */ + public MapAttribute getDeclaredMap(String name) { + final PluralAttribute attribute = declaredPluralAttributes.get( name ); + basicMapCheck( attribute, name ); + return ( MapAttribute ) attribute; + } + + /** + * {@inheritDoc} + */ + @SuppressWarnings({ "unchecked" }) + public CollectionAttribute getCollection(String name, Class elementType) { + PluralAttribute attribute = declaredPluralAttributes.get( name ); + if ( attribute == null && getSupertype() != null ) { + attribute = getSupertype().getPluralAttribute( name ); + } + checkCollectionElementType( attribute, name, elementType ); + return ( CollectionAttribute ) attribute; + } + + /** + * {@inheritDoc} + */ + public CollectionAttribute getDeclaredCollection(String name, Class elementType) { + final PluralAttribute attribute = declaredPluralAttributes.get( name ); + checkCollectionElementType( attribute, name, elementType ); + return ( CollectionAttribute ) attribute; + } + + private void checkCollectionElementType(PluralAttribute attribute, String name, Class elementType) { + checkTypeForPluralAttributes( "CollectionAttribute", attribute, name, elementType, PluralAttribute.CollectionType.COLLECTION ); + } + + private void checkTypeForPluralAttributes( + String attributeType, + PluralAttribute attribute, + String name, + Class elementType, + PluralAttribute.CollectionType collectionType) { + if ( attribute == null + || ( elementType != null && !attribute.getBindableJavaType().equals( elementType ) ) + || attribute.getCollectionType() != collectionType ) { + throw new IllegalArgumentException( + attributeType + " named " + name + + ( elementType != null ? " and of element type " + elementType : "" ) + + " is not present" + ); + } + } + + /** + * {@inheritDoc} + */ + @SuppressWarnings({ "unchecked" }) + public SetAttribute getSet(String name, Class elementType) { + PluralAttribute attribute = declaredPluralAttributes.get( name ); + if ( attribute == null && getSupertype() != null ) { + attribute = getSupertype().getPluralAttribute( name ); + } + checkSetElementType( attribute, name, elementType ); + return ( SetAttribute ) attribute; + } + + private void checkSetElementType(PluralAttribute attribute, String name, Class elementType) { + checkTypeForPluralAttributes( "SetAttribute", attribute, name, elementType, PluralAttribute.CollectionType.SET ); + } + + /** + * {@inheritDoc} + */ + public SetAttribute getDeclaredSet(String name, Class elementType) { + final PluralAttribute attribute = declaredPluralAttributes.get( name ); + checkSetElementType( attribute, name, elementType ); + return ( SetAttribute ) attribute; + } + + /** + * {@inheritDoc} + */ + @SuppressWarnings({ "unchecked" }) + public ListAttribute getList(String name, Class elementType) { + PluralAttribute attribute = declaredPluralAttributes.get( name ); + if ( attribute == null && getSupertype() != null ) { + attribute = getSupertype().getPluralAttribute( name ); + } + checkListElementType( attribute, name, elementType ); + return ( ListAttribute ) attribute; + } + + private void checkListElementType(PluralAttribute attribute, String name, Class elementType) { + checkTypeForPluralAttributes( "ListAttribute", attribute, name, elementType, PluralAttribute.CollectionType.LIST ); + } + + /** + * {@inheritDoc} + */ + public ListAttribute getDeclaredList(String name, Class elementType) { + final PluralAttribute attribute = declaredPluralAttributes.get( name ); + checkListElementType( attribute, name, elementType ); + return ( ListAttribute ) attribute; + } + + @SuppressWarnings({ "unchecked" }) + public MapAttribute getMap(String name, Class keyType, Class valueType) { + PluralAttribute attribute = getPluralAttribute( name ); + if ( attribute == null && getSupertype() != null ) { + attribute = getSupertype().getPluralAttribute( name ); + } + checkMapValueType( attribute, name, valueType ); + final MapAttribute mapAttribute = ( MapAttribute ) attribute; + checkMapKeyType( mapAttribute, name, keyType ); + return mapAttribute; + } + + private void checkMapValueType(PluralAttribute attribute, String name, Class valueType) { + checkTypeForPluralAttributes( "MapAttribute", attribute, name, valueType, PluralAttribute.CollectionType.MAP); + } + + private void checkMapKeyType(MapAttribute mapAttribute, String name, Class keyType) { + if ( mapAttribute.getKeyJavaType() != keyType ) { + throw new IllegalArgumentException( "MapAttribute named " + name + " does not support a key of type " + keyType ); + } + } + + public MapAttribute getDeclaredMap(String name, Class keyType, Class valueType) { + final PluralAttribute attribute = declaredPluralAttributes.get( name ); + checkMapValueType( attribute, name, valueType ); + final MapAttribute mapAttribute = ( MapAttribute ) attribute; + checkMapKeyType( mapAttribute, name, keyType ); + return mapAttribute; + } +} diff --git a/entitymanager/src/main/java/org/hibernate/ejb/metamodel/AbstractType.java b/entitymanager/src/main/java/org/hibernate/ejb/metamodel/AbstractType.java new file mode 100644 index 0000000000..a76b0fd039 --- /dev/null +++ b/entitymanager/src/main/java/org/hibernate/ejb/metamodel/AbstractType.java @@ -0,0 +1,44 @@ +/* + * 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.metamodel; + +import java.io.Serializable; +import javax.persistence.metamodel.Type; + +/** + * Defines commonality for the JPA {@link Type} hierarchy of interfaces. + * + * @author Steve Ebersole + */ +public abstract class AbstractType implements Type, Serializable { + private final Class javaType; + + public AbstractType(Class javaType) { + this.javaType = javaType; + } + + public Class getJavaType() { + return javaType; + } +} diff --git a/entitymanager/src/main/java/org/hibernate/ejb/metamodel/MetamodelFactory.java b/entitymanager/src/main/java/org/hibernate/ejb/metamodel/AttributeFactory.java similarity index 51% rename from entitymanager/src/main/java/org/hibernate/ejb/metamodel/MetamodelFactory.java rename to entitymanager/src/main/java/org/hibernate/ejb/metamodel/AttributeFactory.java index b108e2906b..44cad06014 100644 --- a/entitymanager/src/main/java/org/hibernate/ejb/metamodel/MetamodelFactory.java +++ b/entitymanager/src/main/java/org/hibernate/ejb/metamodel/AttributeFactory.java @@ -1,8 +1,10 @@ /* - * Copyright (c) 2009, Red Hat Middleware LLC or third-party contributors as - * indicated by the @author tags or express copyright attribution - * statements applied by the authors. All third-party contributions are - * distributed under license by Red Hat Middleware LLC. + * 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 @@ -22,78 +24,156 @@ package org.hibernate.ejb.metamodel; import java.util.Iterator; +import java.lang.reflect.Member; import javax.persistence.metamodel.Attribute; -import javax.persistence.metamodel.ManagedType; import javax.persistence.metamodel.Type; -import javax.persistence.metamodel.EmbeddableType; -import org.hibernate.annotations.common.AssertionFailure; -import org.hibernate.mapping.Collection; -import org.hibernate.mapping.Component; -import org.hibernate.mapping.Map; -import org.hibernate.mapping.OneToMany; import org.hibernate.mapping.Property; import org.hibernate.mapping.Value; +import org.hibernate.mapping.Collection; +import org.hibernate.mapping.Map; +import org.hibernate.mapping.Component; +import org.hibernate.mapping.OneToMany; +import org.hibernate.annotations.common.AssertionFailure; /** + * TODO : javadoc + * + * @author Steve Ebersole * @author Emmanuel Bernard */ -class MetamodelFactory { +public class AttributeFactory { + private final MetadataContext context; - static Attribute getAttribute(ManagedType ownerType, Property property, MetadataContext metadataContext) { - return getAttribute( ownerType, property, metadataContext, false ); + public AttributeFactory(MetadataContext context) { + this.context = context; } - static Attribute getAttribute(ManagedType ownerType, Property property, MetadataContext metadataContext, boolean isId) { + @SuppressWarnings({ "unchecked" }) + public AttributeImplementor buildAttribute(AbstractManagedType ownerType, Property property) { AttributeContext attrContext = getAttributeContext( property ); - final Attribute attribute; + final AttributeImplementor attribute; if ( attrContext.isCollection() ) { - final Type attrType = getType( attrContext.getElementTypeStatus(), attrContext.getElementValue(), metadataContext ); - @SuppressWarnings( "unchecked" ) - final Class collectionClass = (Class) attrContext.getCollectionClass(); - if ( java.util.Map.class.isAssignableFrom( collectionClass ) ) { - final Type keyType = getType( attrContext.getKeyTypeStatus(), attrContext.getKeyValue(), metadataContext ); - attribute = PluralAttributeImpl.create( ownerType, attrType, collectionClass, keyType ) - // .member( ); //TODO member - .property( property ) - .persistentAttributeType( attrContext.getElementAttributeType() ) - .build(); - } - else { - attribute = PluralAttributeImpl.create( ownerType, attrType, collectionClass, null ) - // .member( ); //TODO member - .property( property ) - .persistentAttributeType( attrContext.getElementAttributeType() ) - .build(); - } + attribute = buildPluralAttribute( ownerType, property, attrContext ); } else { - final Type attrType = getType( attrContext.getElementTypeStatus(), attrContext.getElementValue(), metadataContext ); - final SingularAttributeImpl.Builder xyBuilder = SingularAttributeImpl.create( ownerType, attrType ) - // .member( ); //TODO member - .property( property ) - .persistentAttributeType( attrContext.getElementAttributeType() ); - if (isId) xyBuilder.id(); - attribute = xyBuilder.build(); + final Type attrType = getType( attrContext.getElementTypeStatus(), attrContext.getElementValue() ); + attribute = new SingularAttributeImpl( + property.getName(), + property.getType().getReturnedClass(), + ownerType, + determineJavaMember( property ), + false, + false, + property.isOptional(), + attrType, + attrContext.getElementAttributeType() + ); } return attribute; } - private static Type getType(AttributeContext.TypeStatus elementTypeStatus, Value value, MetadataContext metadataContext) { + @SuppressWarnings( "unchecked" ) + private AttributeImplementor buildPluralAttribute(AbstractManagedType ownerType, Property property, AttributeContext attrContext) { + AttributeImplementor attribute; + final Type attrType = getType( attrContext.getElementTypeStatus(), attrContext.getElementValue() ); + final Class collectionClass = (Class) attrContext.getCollectionClass(); + if ( java.util.Map.class.isAssignableFrom( collectionClass ) ) { + final Type keyType = getType( attrContext.getKeyTypeStatus(), attrContext.getKeyValue() ); + attribute = PluralAttributeImpl.create( ownerType, attrType, collectionClass, keyType ) + .member( determineJavaMember( property ) ) + .property( property ) + .persistentAttributeType( attrContext.getElementAttributeType() ) + .build(); + } + else { + attribute = PluralAttributeImpl.create( ownerType, attrType, collectionClass, null ) + .member( determineJavaMember( property ) ) + .property( property ) + .persistentAttributeType( attrContext.getElementAttributeType() ) + .build(); + } + return attribute; + } + + private Type getType(AttributeContext.TypeStatus elementTypeStatus, Value value) { final org.hibernate.type.Type type = value.getType(); switch ( elementTypeStatus ) { case BASIC: return buildBasicType( type ); case EMBEDDABLE: - return buildEmbeddableType( value, type, metadataContext ); + return buildEmbeddableType( value, type ); case ENTITY: - return buildEntityType( type, metadataContext ); + return buildEntityType( type ); default: throw new AssertionFailure( "Unknown AttributeContext.TypeStatus: " + elementTypeStatus ); } } + @SuppressWarnings( "unchecked" ) + private Type buildBasicType(org.hibernate.type.Type type) { + final Class clazz = type.getReturnedClass(); + return new BasicTypeImpl( clazz, Type.PersistenceType.BASIC ); + } + + @SuppressWarnings( "unchecked" ) + private Type buildEntityType(org.hibernate.type.Type type) { + String entityName = ( (org.hibernate.type.EntityType) type ).getAssociatedEntityName(); + return ( Type ) context.locateEntityType( entityName ); + } + + @SuppressWarnings( "unchecked" ) + private Type buildEmbeddableType(Value value, org.hibernate.type.Type type) { + //build embedable type + final Class clazz = type.getReturnedClass(); + final EmbeddableTypeImpl embeddableType = new EmbeddableTypeImpl( clazz ); + context.registerEmbeddedableType( embeddableType ); + final Component component = (Component) value; + final Iterator subProperties = component.getPropertyIterator(); + while ( subProperties.hasNext() ) { + final Property property = subProperties.next(); + embeddableType.getBuilder().addAttribute( buildAttribute( embeddableType, property ) ); + } + embeddableType.lock(); + return embeddableType; + } + + @SuppressWarnings({ "unchecked" }) + public SingularAttributeImpl buildIdAttribute(AbstractManagedType ownerType, Property property) { + final AttributeContext attrContext = getAttributeContext( property ); + final Type attrType = getType( attrContext.getElementTypeStatus(), attrContext.getElementValue() ); + final Class idJavaType = property.getType().getReturnedClass(); + return new SingularAttributeImpl.Identifier( + property.getName(), + idJavaType, + ownerType, + determineJavaMember( property ), + attrType, + attrContext.getElementAttributeType() + ); + } + + @SuppressWarnings({ "UnusedDeclaration" }) + private Member determineJavaMember(Property property) { + return null; + } + + @SuppressWarnings({ "unchecked" }) + public SingularAttributeImpl buildVerisonAttribute(AbstractManagedType ownerType, Property property) { + final AttributeContext attrContext = getAttributeContext( property ); + final Class javaType = property.getType().getReturnedClass(); + final Type attrType = getType( attrContext.getElementTypeStatus(), attrContext.getElementValue() ); + return new SingularAttributeImpl.Version( + property.getName(), + javaType, + ownerType, + determineJavaMember( property ), + attrType, + attrContext.getElementAttributeType() + ); + } + private static class AttributeContext { private final Value elementValue; private final TypeStatus typeStatus; @@ -108,12 +188,13 @@ class MetamodelFactory { BASIC } - AttributeContext(Value elementValue, - TypeStatus elementTypeStatus, - Attribute.PersistentAttributeType elementPAT, - Class collectionClass, - Value keyValue, - TypeStatus keyTypeStatus) { + private AttributeContext( + Value elementValue, + TypeStatus elementTypeStatus, + Attribute.PersistentAttributeType elementPAT, + Class collectionClass, + Value keyValue, + TypeStatus keyTypeStatus) { this.elementValue = elementValue; this.typeStatus = elementTypeStatus; this.collectionClass = collectionClass; @@ -151,14 +232,13 @@ class MetamodelFactory { } } - - //FIXME the logical level for *To* is different from the Hibernate physical model. - //ie a @ManyToOne @AssocTable is a many-to-many for hibernate - //and a @OneToMany @AssocTable is a many-to-many for hibernate - //FIXME so basically Attribute.PersistentAttributeType is crap at the moment private static AttributeContext getAttributeContext(Property property) { + // FIXME the logical level for *To* is different from the Hibernate physical model. + // ie a @ManyToOne @AssocTable is a many-to-many for hibernate + // and a @OneToMany @AssocTable is a many-to-many for hibernate + // FIXME so basically Attribute.PersistentAttributeType is crap at the moment final Value value = property.getValue(); - org.hibernate.type.Type type = value.getType(); + final org.hibernate.type.Type type = value.getType(); if ( type.isAnyType() ) { throw new UnsupportedOperationException( "any not supported yet" ); } @@ -167,7 +247,7 @@ class MetamodelFactory { if ( type.isCollectionType() ) { //do collection if ( value instanceof Collection ) { - final Collection collValue = (Collection) value; + final Collection collValue = ( Collection ) value; final Value elementValue = collValue.getElement(); final org.hibernate.type.Type elementType = elementValue.getType(); final AttributeContext.TypeStatus elementTypeStatus; @@ -179,7 +259,7 @@ class MetamodelFactory { final org.hibernate.type.Type keyType; final AttributeContext.TypeStatus keyTypeStatus; if ( value instanceof Map ) { - keyValue = ( (Map) value).getIndex(); + keyValue = ( ( Map ) value ).getIndex(); keyType = keyValue.getType(); if ( keyValue instanceof Component ) { keyTypeStatus = AttributeContext.TypeStatus.EMBEDDABLE; @@ -218,13 +298,13 @@ class MetamodelFactory { elementPAT = Attribute.PersistentAttributeType.ELEMENT_COLLECTION; } return new AttributeContext( - elementValue, - elementTypeStatus, - elementPAT, - collectionClass, - keyValue, - keyTypeStatus - ); + elementValue, + elementTypeStatus, + elementPAT, + collectionClass, + keyValue, + keyTypeStatus + ); } else if ( value instanceof OneToMany ) { //one to many with FK => entity @@ -232,7 +312,8 @@ class MetamodelFactory { value, AttributeContext.TypeStatus.ENTITY, Attribute.PersistentAttributeType.ONE_TO_MANY, - null, null, null ); + null, null, null + ); } } @@ -241,8 +322,12 @@ class MetamodelFactory { return new AttributeContext( value, AttributeContext.TypeStatus.ENTITY, - Attribute.PersistentAttributeType.MANY_TO_MANY, //FIXME how to differentiate the logical many to one from the one to one (not physical level) - null, null, null); + Attribute.PersistentAttributeType.MANY_TO_MANY, + //FIXME how to differentiate the logical many to one from the one to one (not physical level) + null, + null, + null + ); } } else if ( property.isComposite() ) { @@ -251,7 +336,8 @@ class MetamodelFactory { value, AttributeContext.TypeStatus.EMBEDDABLE, Attribute.PersistentAttributeType.EMBEDDED, - null, null, null); + null, null, null + ); } else { @@ -260,90 +346,11 @@ class MetamodelFactory { value, AttributeContext.TypeStatus.BASIC, Attribute.PersistentAttributeType.BASIC, - null, null, null); + null, null, null + ); } - throw new UnsupportedOperationException("oops, we are missing something: " + property.toString() ); + throw new UnsupportedOperationException( "oops, we are missing something: " + property.toString() ); } - - static Type getType(Property property, MetadataContext context) { - final Value value = property.getValue(); - org.hibernate.type.Type type = value.getType(); - if ( type.isAnyType() ) { - throw new UnsupportedOperationException( "any not supported yet" ); - } - else if ( type.isAssociationType() ) { - //collection or entity - if ( type.isCollectionType() ) { - //do collection - if ( value instanceof Collection ) { - Collection collValue = (Collection) value; - collValue.getCollectionType(); - Value elementValue = collValue.getElement(); - final org.hibernate.type.Type elementType = elementValue.getType(); - if ( elementValue instanceof Component ) { - //colelction of components - return buildEmbeddableType( elementValue, elementType, context ); - } - else if ( elementType.isAnyType() ) { - throw new UnsupportedOperationException( "collection of any not supported yet" ); - } - else if ( elementType.isAssociationType() ) { - //collection of entity - return buildEntityType( elementType, context); - } - else { - //collection of basic type - buildBasicType( elementType ); - } - } - else if ( value instanceof OneToMany ) { - //one to many with FK => entity - return buildEntityType( value.getType(), context ); - } - - } - else { - //ToOne association - return buildEntityType( type, context ); - } - } - else if ( property.isComposite() ) { - //embeddable - return buildEmbeddableType( value, type, context ); - - } - else { - //basic type - return buildBasicType( type ); - } - throw new UnsupportedOperationException("oops, we are missing something: " + property.toString() ); - } - - private static Type buildBasicType(org.hibernate.type.Type type) { - @SuppressWarnings( "unchecked" ) - final Class clazz = type.getReturnedClass(); - return new BasicTypeImpl( clazz, Type.PersistenceType.BASIC ); - } - - private static Type buildEntityType(org.hibernate.type.Type type, MetadataContext context) { - @SuppressWarnings( "unchecked" ) - final Class clazz = type.getReturnedClass(); - final EntityTypeDelegator entityTypeDelegator = new EntityTypeDelegator(); - context.addDelegator( entityTypeDelegator, clazz ); - return entityTypeDelegator; - } - - private static Type buildEmbeddableType(Value value, org.hibernate.type.Type type, MetadataContext context) { - //build embedable type - @SuppressWarnings( "unchecked" ) - final Class clazz = type.getReturnedClass(); - Component component = (Component) value; - @SuppressWarnings( "unchecked") - final Iterator subProperties = component.getPropertyIterator(); - final EmbeddableType embeddableType = new EmbeddableTypeImpl( clazz, subProperties, context ); - context.addEmbeddableType( clazz, embeddableType ); - return embeddableType; - } } diff --git a/entitymanager/src/main/java/org/hibernate/ejb/metamodel/AttributeImplementor.java b/entitymanager/src/main/java/org/hibernate/ejb/metamodel/AttributeImplementor.java new file mode 100644 index 0000000000..ebfb76998b --- /dev/null +++ b/entitymanager/src/main/java/org/hibernate/ejb/metamodel/AttributeImplementor.java @@ -0,0 +1,34 @@ +/* + * 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.metamodel; + +import javax.persistence.metamodel.Attribute; + +/** + * TODO : javadoc + * + * @author Steve Ebersole + */ +public interface AttributeImplementor extends Attribute { +} diff --git a/entitymanager/src/main/java/org/hibernate/ejb/metamodel/EmbeddableTypeImpl.java b/entitymanager/src/main/java/org/hibernate/ejb/metamodel/EmbeddableTypeImpl.java index 63f715ea05..afc0d486ec 100644 --- a/entitymanager/src/main/java/org/hibernate/ejb/metamodel/EmbeddableTypeImpl.java +++ b/entitymanager/src/main/java/org/hibernate/ejb/metamodel/EmbeddableTypeImpl.java @@ -30,9 +30,12 @@ import org.hibernate.mapping.Property; /** * @author Emmanuel Bernard */ -public class EmbeddableTypeImpl extends ManagedTypeImpl implements EmbeddableType, Serializable { - EmbeddableTypeImpl(Class clazz, Iterator properties, MetadataContext context) { - super(clazz, properties, context); +public class EmbeddableTypeImpl + extends AbstractManagedType + implements EmbeddableType, Serializable { + + public EmbeddableTypeImpl(Class javaType) { + super( javaType, null ); } public PersistenceType getPersistenceType() { diff --git a/entitymanager/src/main/java/org/hibernate/ejb/metamodel/EntityTypeDelegator.java b/entitymanager/src/main/java/org/hibernate/ejb/metamodel/EntityTypeDelegator.java deleted file mode 100644 index 612d24a326..0000000000 --- a/entitymanager/src/main/java/org/hibernate/ejb/metamodel/EntityTypeDelegator.java +++ /dev/null @@ -1,217 +0,0 @@ -/* - * Copyright (c) 2009, Red Hat Middleware LLC or third-party contributors as - * indicated by the @author tags or express copyright attribution - * statements applied by the authors. All third-party contributions are - * distributed under license by Red Hat Middleware LLC. - * - * 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.metamodel; - -import java.util.Set; -import java.io.Serializable; -import javax.persistence.metamodel.Attribute; -import javax.persistence.metamodel.CollectionAttribute; -import javax.persistence.metamodel.EntityType; -import javax.persistence.metamodel.IdentifiableType; -import javax.persistence.metamodel.ListAttribute; -import javax.persistence.metamodel.MapAttribute; -import javax.persistence.metamodel.PluralAttribute; -import javax.persistence.metamodel.SetAttribute; -import javax.persistence.metamodel.SingularAttribute; -import javax.persistence.metamodel.Type; - -/** - * Delegate to an other EntityType - * Helps break infinite loops when creating entity metamodel related to each other - * - * @author Emmanuel Bernard - */ -public class EntityTypeDelegator implements EntityType, Serializable { - private volatile EntityType delegate; - - void setDelegate(EntityType delegate) { - this.delegate = delegate; - } - - public String getName() { - return delegate.getName(); - } - - public SingularAttribute getId(Class type) { - return delegate.getId( type ); - } - - public SingularAttribute getVersion(Class type) { - return delegate.getVersion( type ); - } - - public SingularAttribute getDeclaredId(Class type) { - return delegate.getDeclaredId( type ); - } - - public SingularAttribute getDeclaredVersion(Class type) { - return delegate.getDeclaredVersion( type ); - } - - public IdentifiableType getSupertype() { - return delegate.getSupertype(); - } - - public boolean hasSingleIdAttribute() { - return delegate.hasSingleIdAttribute(); - } - - public boolean hasVersionAttribute() { - return delegate.hasVersionAttribute(); - } - - public Set> getIdClassAttributes() { - return delegate.getIdClassAttributes(); - } - - public Type getIdType() { - return delegate.getIdType(); - } - - public Set> getAttributes() { - return delegate.getAttributes(); - } - - public Set> getDeclaredAttributes() { - return delegate.getDeclaredAttributes(); - } - - public SingularAttribute getSingularAttribute(String name, Class type) { - return delegate.getSingularAttribute( name, type ); - } - - public SingularAttribute getDeclaredSingularAttribute(String name, Class type) { - return delegate.getDeclaredSingularAttribute( name, type ); - } - - public Set> getSingularAttributes() { - return delegate.getSingularAttributes(); - } - - public Set> getDeclaredSingularAttributes() { - return delegate.getDeclaredSingularAttributes(); - } - - public CollectionAttribute getCollection(String name, Class elementType) { - return delegate.getCollection( name, elementType ); - } - - public SetAttribute getSet(String name, Class elementType) { - return delegate.getSet( name, elementType ); - } - - public ListAttribute getList(String name, Class elementType) { - return delegate.getList( name, elementType ); - } - - public MapAttribute getMap(String name, Class keyType, Class valueType) { - return delegate.getMap( name, keyType, valueType ); - } - - public CollectionAttribute getDeclaredCollection(String name, Class elementType) { - return delegate.getDeclaredCollection( name, elementType ); - } - - public SetAttribute getDeclaredSet(String name, Class elementType) { - return delegate.getDeclaredSet( name, elementType ); - } - - public ListAttribute getDeclaredList(String name, Class elementType) { - return delegate.getDeclaredList( name, elementType ); - } - - public MapAttribute getDeclaredMap(String name, Class keyType, Class valueType) { - return delegate.getDeclaredMap( name, keyType, valueType ); - } - - public Set> getPluralAttributes() { - return delegate.getPluralAttributes(); - } - - public Set> getDeclaredPluralAttributes() { - return delegate.getDeclaredPluralAttributes(); - } - - public Attribute getAttribute(String name) { - return delegate.getAttribute( name ); - } - - public Attribute getDeclaredAttribute(String name) { - return delegate.getDeclaredAttribute( name ); - } - - public SingularAttribute getSingularAttribute(String name) { - return delegate.getSingularAttribute( name ); - } - - public SingularAttribute getDeclaredSingularAttribute(String name) { - return delegate.getDeclaredSingularAttribute( name ); - } - - public CollectionAttribute getCollection(String name) { - return delegate.getCollection( name ); - } - - public SetAttribute getSet(String name) { - return delegate.getSet( name ); - } - - public ListAttribute getList(String name) { - return delegate.getList( name ); - } - - public MapAttribute getMap(String name) { - return delegate.getMap( name ); - } - - public CollectionAttribute getDeclaredCollection(String name) { - return delegate.getDeclaredCollection( name ); - } - - public SetAttribute getDeclaredSet(String name) { - return delegate.getDeclaredSet( name ); - } - - public ListAttribute getDeclaredList(String name) { - return delegate.getDeclaredList( name ); - } - - public MapAttribute getDeclaredMap(String name) { - return delegate.getDeclaredMap( name ); - } - - public PersistenceType getPersistenceType() { - return delegate.getPersistenceType(); - } - - public Class getJavaType() { - return delegate.getJavaType(); - } - - public BindableType getBindableType() { - return delegate.getBindableType(); - } - - public Class getBindableJavaType() { - return delegate.getBindableJavaType(); - } -} diff --git a/entitymanager/src/main/java/org/hibernate/ejb/metamodel/EntityTypeImpl.java b/entitymanager/src/main/java/org/hibernate/ejb/metamodel/EntityTypeImpl.java index 429b7bdab7..3abe1e6bf2 100644 --- a/entitymanager/src/main/java/org/hibernate/ejb/metamodel/EntityTypeImpl.java +++ b/entitymanager/src/main/java/org/hibernate/ejb/metamodel/EntityTypeImpl.java @@ -21,168 +21,34 @@ */ package org.hibernate.ejb.metamodel; -import java.util.Collections; -import java.util.HashSet; -import java.util.Iterator; -import java.util.Set; import java.io.Serializable; import javax.persistence.metamodel.EntityType; -import javax.persistence.metamodel.IdentifiableType; -import javax.persistence.metamodel.SingularAttribute; -import javax.persistence.metamodel.Type; - -import org.hibernate.mapping.PersistentClass; -import org.hibernate.mapping.Property; /** + * Defines the Hibernate implementation of the JPA {@link EntityType} contract. + * + * @author Steve Ebersole * @author Emmanuel Bernard */ -public class EntityTypeImpl extends ManagedTypeImpl implements EntityType, Serializable { - - private final SingularAttribute id; - private final SingularAttribute version; +public class EntityTypeImpl + extends AbstractIdentifiableType + implements EntityType, Serializable { private final String className; - private final boolean hasIdentifierProperty; - private final boolean isVersioned; - private final Set> idClassAttributes; - private final IdentifiableType supertype; - public EntityTypeImpl(Class clazz, PersistentClass persistentClass, MetadataContext context) { - super(clazz, (Iterator) persistentClass.getPropertyIterator(), context ); - this.className = persistentClass.getClassName(); - this.hasIdentifierProperty = persistentClass.hasIdentifierProperty(); - this.isVersioned = persistentClass.isVersioned(); - id = buildIdAttribute( persistentClass ); - version = buildVersionAttribute( persistentClass ); - final Set> attributes = buildIdClassAttributes( persistentClass, context ); - this.idClassAttributes = attributes != null ? Collections.unmodifiableSet( attributes ) : null; - - PersistentClass superPersistentClass = persistentClass.getSuperclass(); - if ( superPersistentClass == null ) { - supertype = null; - } - else { - final Class superclass = superPersistentClass.getMappedClass(); - final EntityTypeDelegator entityTypeDelegator = new EntityTypeDelegator(); - context.addDelegator( entityTypeDelegator, superclass ); - supertype = entityTypeDelegator; - } - } - - private SingularAttribute buildIdAttribute(PersistentClass persistentClass) { - if ( hasIdentifierProperty ) { - final Property identifierProperty = persistentClass.getIdentifierProperty(); - @SuppressWarnings( "unchecked" ) - Class idClass = identifierProperty.getType().getReturnedClass(); - final Type attrType = new BasicTypeImpl( idClass, - identifierProperty.isComposite() ? - PersistenceType.EMBEDDABLE : - PersistenceType.BASIC); - return SingularAttributeImpl.create(this, attrType ) - .property(identifierProperty) - //.member( null ) //TODO member - .id() - .build(); - } - else { - return null; - } - } - - private SingularAttribute buildVersionAttribute(PersistentClass persistentClass) { - if ( persistentClass.isVersioned() ) { - @SuppressWarnings( "unchecked" ) - Class versionClass = persistentClass.getVersion().getType().getReturnedClass(); - Property property = persistentClass.getVersion(); - final Type attrType = new BasicTypeImpl( versionClass, PersistenceType.BASIC); - return SingularAttributeImpl.create(this, attrType ) - .property(property) - //.member( null ) //TODO member - .version() - .build(); - } - else { - return null; - } - } - - private Set> buildIdClassAttributes(PersistentClass persistentClass, MetadataContext context) { - if ( hasSingleIdAttribute() ) { - return null; - } - @SuppressWarnings( "unchecked") - Iterator properties = persistentClass.getIdentifierMapper().getPropertyIterator(); - Set> attributes = new HashSet>(); - while ( properties.hasNext() ) { - attributes.add( - (SingularAttribute) MetamodelFactory.getAttribute( this, properties.next(), context, true ) - ); - } - return attributes; + public EntityTypeImpl( + Class javaType, + AbstractIdentifiableType superType, + String className, + boolean hasIdentifierProperty, + boolean isVersioned) { + super( javaType, superType, hasIdentifierProperty, isVersioned ); + this.className = className; } public String getName() { return className; } - public SingularAttribute getId(Class type) { - //TODO check that type and id.getJavaType() are related - checkId(); - @SuppressWarnings( "unchecked") - final SingularAttribute result = ( SingularAttribute ) id; - return result; - } - - private void checkId() { - if ( ! hasSingleIdAttribute() ) throw new IllegalArgumentException("This is an @IdClass"); - } - - public SingularAttribute getVersion(Class type) { - //TODO check that type and version.getJavaType() are related - @SuppressWarnings( "unchecked") - final SingularAttribute result = ( SingularAttribute ) version; - return result; - } - - public SingularAttribute getDeclaredId(Class type) { - checkId(); - //TODO check that type and id.getJavaType() are related - @SuppressWarnings("unchecked") - final SingularAttribute result = ( SingularAttribute ) id; - return result; - } - - public SingularAttribute getDeclaredVersion(Class type) { - //TODO check that type and version.getJavaType() are related - @SuppressWarnings("unchecked") - final SingularAttribute result = ( SingularAttribute ) version; - return result; - } - - public IdentifiableType getSupertype() { - return supertype; - } - - public boolean hasSingleIdAttribute() { - return hasIdentifierProperty; - } - - public boolean hasVersionAttribute() { - return isVersioned; - } - - public Set> getIdClassAttributes() { - if ( hasSingleIdAttribute() ) { - throw new IllegalArgumentException( "This class does not use @IdClass: " + getName() ); - } - return idClassAttributes; - } - - public Type getIdType() { - checkId(); - return id.getType(); - } - public BindableType getBindableType() { return BindableType.ENTITY_TYPE; } diff --git a/entitymanager/src/main/java/org/hibernate/ejb/metamodel/ManagedTypeImpl.java b/entitymanager/src/main/java/org/hibernate/ejb/metamodel/ManagedTypeImpl.java deleted file mode 100644 index 299718c4fa..0000000000 --- a/entitymanager/src/main/java/org/hibernate/ejb/metamodel/ManagedTypeImpl.java +++ /dev/null @@ -1,309 +0,0 @@ -/* - * 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.metamodel; - -import java.util.Iterator; -import java.util.Set; -import java.util.HashSet; -import java.util.Collections; -import java.util.Map; -import java.util.HashMap; -import java.io.Serializable; - -import javax.persistence.metamodel.ManagedType; -import javax.persistence.metamodel.Attribute; -import javax.persistence.metamodel.SingularAttribute; -import javax.persistence.metamodel.CollectionAttribute; -import javax.persistence.metamodel.SetAttribute; -import javax.persistence.metamodel.ListAttribute; -import javax.persistence.metamodel.MapAttribute; -import javax.persistence.metamodel.PluralAttribute; -import javax.persistence.metamodel.Bindable; - -import org.hibernate.mapping.Property; -import org.hibernate.annotations.common.AssertionFailure; - -/** - * @author Emmanuel Bernard - */ -public abstract class ManagedTypeImpl implements ManagedType, Serializable { - private final Class javaClass; - private final Map> declaredAttributes; - private final Map> declaredSingularAttributes; - private final Map> declaredCollections; - - - - ManagedTypeImpl(Class clazz, Iterator properties, MetadataContext context) { - this.javaClass = clazz; - Map> localDeclAttr = new HashMap>(); - Map> localDeclSingAttr = new HashMap>(); - Map> localDeclPlurAttr = new HashMap>(); - - while ( properties.hasNext() ) { - Property property = properties.next(); - addProperty( property, context, localDeclAttr, localDeclSingAttr, localDeclPlurAttr ); - } - declaredAttributes = Collections.unmodifiableMap( localDeclAttr ); - declaredSingularAttributes = Collections.unmodifiableMap( localDeclSingAttr ); - declaredCollections = Collections.unmodifiableMap( localDeclPlurAttr ); - } - - private void addProperty(Property property, - MetadataContext context, - Map> localDeclAttr, - Map> localDeclSingAttr, - Map> localDeclPlurAttr) { - final Attribute attribute = MetamodelFactory.getAttribute( this, property, context ); - localDeclAttr.put(attribute.getName(), attribute ); - final Bindable.BindableType bindableType = ( ( Bindable ) attribute ).getBindableType(); - switch ( bindableType ) { - case SINGULAR_ATTRIBUTE: - localDeclSingAttr.put(attribute.getName(), (SingularAttribute) attribute ); - break; - case PLURAL_ATTRIBUTE: - localDeclPlurAttr.put(attribute.getName(), (PluralAttribute) attribute ); - break; - default: - throw new AssertionFailure( "unknown bindable type: " + bindableType ); - } - - } - - public Set> getAttributes() { - return null; //To change body of implemented methods use File | Settings | File Templates. - } - - public Set> getDeclaredAttributes() { - return new HashSet>(declaredAttributes.values()); - } - - public SingularAttribute getSingularAttribute(String name, Class type) { - return null; //To change body of implemented methods use File | Settings | File Templates. - } - - public SingularAttribute getDeclaredSingularAttribute(String name, Class type) { - final SingularAttribute attr = declaredSingularAttributes.get( name ); - checkTypeForSingleAttribute( "SingularAttribute ", attr, name, type ); - @SuppressWarnings( "unchecked") - final SingularAttribute result = ( SingularAttribute ) attr; - return result; - } - - private void checkTypeForSingleAttribute(String error, SingularAttribute attr, String name, Class type) { - if (attr == null || ( type != null && !attr.getBindableJavaType().equals( type ) ) ) { - throw new IllegalArgumentException( - error + " named " + name - + (type != null ? " and of type " + type : "") - + " is not present"); - } - } - - private void checkTypeForPluralAttributes(String error, - PluralAttribute attr, - String name, - Class type, - PluralAttribute.CollectionType collectionType) { - if (attr == null - || ( type != null && !attr.getBindableJavaType().equals( type ) ) - || attr.getCollectionType() != collectionType ) { - throw new IllegalArgumentException( - error + " named " + name - + (type != null ? " and of element type " + type : "") - + " is not present"); - } - } - - private void checkNotNull(String error, Attribute attr, String name) { - if (attr == null) { - throw new IllegalArgumentException( - error + " named " + name - + " is not present"); - } - } - - public Set> getSingularAttributes() { - return null; //To change body of implemented methods use File | Settings | File Templates. - } - - public Set> getDeclaredSingularAttributes() { - return new HashSet>(declaredSingularAttributes.values()); - } - - public CollectionAttribute getCollection(String name, Class elementType) { - return null; //To change body of implemented methods use File | Settings | File Templates. - } - - public SetAttribute getSet(String name, Class elementType) { - return null; //To change body of implemented methods use File | Settings | File Templates. - } - - public ListAttribute getList(String name, Class elementType) { - return null; //To change body of implemented methods use File | Settings | File Templates. - } - - public MapAttribute getMap(String name, Class keyType, Class valueType) { - return null; //To change body of implemented methods use File | Settings | File Templates. - } - - public CollectionAttribute getDeclaredCollection(String name, Class elementType) { - final PluralAttribute attr = declaredCollections.get( name ); - checkTypeForPluralAttributes( "CollectionAttribute ", attr, name, elementType, PluralAttribute.CollectionType.COLLECTION ); - @SuppressWarnings( "unchecked") - final CollectionAttribute result = ( CollectionAttribute ) attr; - return result; - } - - public SetAttribute getDeclaredSet(String name, Class elementType) { - final PluralAttribute attr = declaredCollections.get( name ); - checkTypeForPluralAttributes( "SetAttribute ", attr, name, elementType, PluralAttribute.CollectionType.SET ); - @SuppressWarnings( "unchecked") - final SetAttribute result = ( SetAttribute ) attr; - return result; - } - - public ListAttribute getDeclaredList(String name, Class elementType) { - final PluralAttribute attr = declaredCollections.get( name ); - checkTypeForPluralAttributes( "ListAttribute ", attr, name, elementType, PluralAttribute.CollectionType.LIST ); - @SuppressWarnings( "unchecked") - final ListAttribute result = ( ListAttribute ) attr; - return result; - } - - public MapAttribute getDeclaredMap(String name, Class keyType, Class valueType) { - final PluralAttribute attr = declaredCollections.get( name ); - final String error = "MapAttribute "; - checkTypeForPluralAttributes( error, attr, name, valueType, PluralAttribute.CollectionType.MAP ); - @SuppressWarnings( "unchecked") - final MapAttribute result = ( MapAttribute ) attr; - if ( result.getKeyJavaType() != keyType ) { - throw new IllegalArgumentException( - error + " named " + name + " does not support a key of type " + keyType - ); - } - return result; - } - - public Set> getPluralAttributes() { - return null; //To change body of implemented methods use File | Settings | File Templates. - } - - public Set> getDeclaredPluralAttributes() { - return new HashSet>(declaredCollections.values()); - } - - public Attribute getAttribute(String name) { - return null; //To change body of implemented methods use File | Settings | File Templates. - } - - public Attribute getDeclaredAttribute(String name) { - final Attribute attr = declaredSingularAttributes.get( name ); - checkNotNull( "Attribute ", attr, name ); - return attr; - } - - public SingularAttribute getSingularAttribute(String name) { - return null; //To change body of implemented methods use File | Settings | File Templates. - } - - public SingularAttribute getDeclaredSingularAttribute(String name) { - final SingularAttribute attr = declaredSingularAttributes.get( name ); - checkNotNull( "SingularAttribute ", attr, name ); - return attr; - } - - public CollectionAttribute getCollection(String name) { - return null; //To change body of implemented methods use File | Settings | File Templates. - } - - public SetAttribute getSet(String name) { - return null; //To change body of implemented methods use File | Settings | File Templates. - } - - public ListAttribute getList(String name) { - return null; //To change body of implemented methods use File | Settings | File Templates. - } - - public MapAttribute getMap(String name) { - return null; //To change body of implemented methods use File | Settings | File Templates. - } - - public CollectionAttribute getDeclaredCollection(String name) { - final PluralAttribute attr = declaredCollections.get( name ); - final String error = "CollectionAttribute "; - checkNotNull( error, attr, name ); - if ( ! CollectionAttribute.class.isAssignableFrom( attr.getClass() ) ) { - throw new IllegalArgumentException( name - + " is not a " + error + ": " + attr.getClass() ); - } - @SuppressWarnings( "unchecked") - final CollectionAttribute result = ( CollectionAttribute ) attr; - return result; - } - - public SetAttribute getDeclaredSet(String name) { - final PluralAttribute attr = declaredCollections.get( name ); - final String error = "SetAttribute "; - checkNotNull( error, attr, name ); - if ( ! CollectionAttribute.class.isAssignableFrom( attr.getClass() ) ) { - throw new IllegalArgumentException( name - + " is not a " + error + ": " + attr.getClass() ); - } - @SuppressWarnings( "unchecked") - final SetAttribute result = ( SetAttribute ) attr; - return result; - } - - public ListAttribute getDeclaredList(String name) { - final PluralAttribute attr = declaredCollections.get( name ); - final String error = "ListAttribute "; - checkNotNull( error, attr, name ); - if ( ! CollectionAttribute.class.isAssignableFrom( attr.getClass() ) ) { - throw new IllegalArgumentException( name - + " is not a " + error + ": " + attr.getClass() ); - } - @SuppressWarnings( "unchecked") - final ListAttribute result = ( ListAttribute ) attr; - return result; - } - - public MapAttribute getDeclaredMap(String name) { - final PluralAttribute attr = declaredCollections.get( name ); - final String error = "MapAttribute "; - checkNotNull( error, attr, name ); - if ( ! MapAttribute.class.isAssignableFrom( attr.getClass() ) ) { - throw new IllegalArgumentException( name - + " is not a " + error + ": " + attr.getClass() ); - } - @SuppressWarnings( "unchecked") - final MapAttribute result = ( MapAttribute ) attr; - return result; - } - - public abstract PersistenceType getPersistenceType(); - - public Class getJavaType() { - return javaClass; - } -} diff --git a/entitymanager/src/main/java/org/hibernate/ejb/metamodel/MetadataContext.java b/entitymanager/src/main/java/org/hibernate/ejb/metamodel/MetadataContext.java index a131370680..4271744cfd 100644 --- a/entitymanager/src/main/java/org/hibernate/ejb/metamodel/MetadataContext.java +++ b/entitymanager/src/main/java/org/hibernate/ejb/metamodel/MetadataContext.java @@ -21,43 +21,146 @@ */ package org.hibernate.ejb.metamodel; +import java.util.Collections; import java.util.HashMap; +import java.util.HashSet; +import java.util.Iterator; +import java.util.LinkedHashMap; import java.util.Map; -import javax.persistence.metamodel.Metamodel; -import javax.persistence.metamodel.EmbeddableType; +import java.util.Set; +import javax.persistence.metamodel.Attribute; +import javax.persistence.metamodel.SingularAttribute; + +import org.hibernate.mapping.PersistentClass; +import org.hibernate.mapping.Property; /** - * Keep contextual information related tot he metedata building process. - * In particular keeps data than theens to be processed in a second phase. + * Defines a context for storing information during the building of the {@link MetamodelImpl}. + *

+ * This contextual information includes data needing to be processed in a second pass as well as + * cross-references into the built metamodel classes. + * + * @author Steve Ebersole * @author Emmanuel Bernard */ class MetadataContext { - private Map, Class> delegators = new HashMap, Class>(); - private Map, EmbeddableType> embeddables = new HashMap, EmbeddableType>(); + private final AttributeFactory attributeFactory = new AttributeFactory( this ); - void addDelegator(EntityTypeDelegator type, Class clazz) { - delegators.put(type, clazz); + private HashMap,EntityTypeImpl> entityTypes + = new HashMap, EntityTypeImpl>(); + private HashMap> entityTypesByEntityName + = new HashMap>(); + private LinkedHashMap> entityTypesByPersistentClass + = new LinkedHashMap>(); + private HashMap, EmbeddableTypeImpl> embeddables + = new HashMap, EmbeddableTypeImpl>(); + + /** + * Given a Hibernate {@link PersistentClass}, locate the corresponding JPA {@link org.hibernate.type.EntityType} + * implementation. May retur null if the given {@link PersistentClass} has not yet been processed. + * + * @param persistentClass The Hibernate (config time) metamodel instance representing an entity. + * @return Tne corresponding JPA {@link org.hibernate.type.EntityType}, or null if not yet processed. + */ + public EntityTypeImpl locateEntityType(PersistentClass persistentClass) { + return entityTypesByPersistentClass.get( persistentClass ); } - void postProcess(Metamodel model) { - for ( Map.Entry, Class> entry : delegators.entrySet() ) { - setDelegate( model, entry ); + /** + * Given a Java {@link Class}, locate the corresponding JPA {@link org.hibernate.type.EntityType}. May + * return null which could means that no such mapping exists at least at this time. + * + * @param javaType The java class. + * @return The corresponding JPA {@link org.hibernate.type.EntityType}, or null. + */ + public EntityTypeImpl locateEntityType(Class javaType) { + return entityTypes.get( javaType ); + } + + /** + * Given an entity-name, locate the corresponding JPA {@link org.hibernate.type.EntityType}. May + * return null which could means that no such mapping exists at least at this time. + * + * @param entityName The entity-name. + * @return The corresponding JPA {@link org.hibernate.type.EntityType}, or null. + */ + public EntityTypeImpl locateEntityType(String entityName) { + return entityTypesByEntityName.get( entityName ); + } + + /** + * Retrieves the {@link Class java type} to {@link EntityType} map. + * + * @return The {@link Class java type} to {@link EntityType} map. + */ + public Map, EntityTypeImpl> getEntityTypeMap() { + return Collections.unmodifiableMap( entityTypes ); + } + + /*package*/ void registerEntityType(PersistentClass persistentClass, EntityTypeImpl entityType) { + entityTypes.put( entityType.getBindableJavaType(), entityType ); + entityTypesByEntityName.put( persistentClass.getEntityName(), entityType ); + entityTypesByPersistentClass.put( persistentClass, entityType ); + } + + /*package*/ void registerEmbeddedableType(EmbeddableTypeImpl embeddableType) { + embeddables.put( embeddableType.getJavaType(), embeddableType ); + } + + public Map, EmbeddableTypeImpl> getEmbeddableTypeMap() { + return Collections.unmodifiableMap( embeddables ); + } + + @SuppressWarnings({ "unchecked" }) + public void wrapUp() { + // IMPL NOTE : entityTypesByPersistentClass is a insertion-ordered map, where the insertion order + // ensures that a type's super type is already processed... + for ( Map.Entry> entry : entityTypesByPersistentClass.entrySet() ) { + applyIdMetadata( entry.getKey(), entry.getValue() ); + applyVersionAttribute( entry.getKey(), entry.getValue() ); + Iterator properties = ( Iterator ) entry.getKey().getPropertyIterator(); + while ( properties.hasNext() ) { + final Property property = properties.next(); + final Attribute attribute = attributeFactory.buildAttribute( entry.getValue(), property ); + entry.getValue().getBuilder().addAttribute( attribute ); + } + entry.getValue().lock(); + // todo : find the X_ style metamodel classes, if present, and inject } } - private void setDelegate(Metamodel model, Map.Entry, Class> entry) { - @SuppressWarnings( "unchecked" ) - final Class entityClass = (Class) entry.getValue(); - @SuppressWarnings( "unchecked" ) - final EntityTypeDelegator delegator = (EntityTypeDelegator) entry.getKey(); - delegator.setDelegate( model.entity( entityClass ) ); + private void applyIdMetadata(PersistentClass persistentClass, EntityTypeImpl jpaEntityType) { + if ( persistentClass.hasIdentifierProperty() ) { + jpaEntityType.getBuilder().applyIdAttribute( + attributeFactory.buildIdAttribute( jpaEntityType, persistentClass.getIdentifierProperty() ) + ); + } + else { + jpaEntityType.getBuilder().applyIdClassAttributes( buildIdClassAttributes( jpaEntityType, persistentClass ) ); + } } - void addEmbeddableType(Class clazz, EmbeddableType embeddableType) { - embeddables.put( clazz, embeddableType ); + private void applyVersionAttribute(PersistentClass persistentClass, EntityTypeImpl jpaEntityType) { + if ( ! persistentClass.isVersioned() ) { + return; + } + jpaEntityType.getBuilder().applyVersionAttribute( + attributeFactory.buildVerisonAttribute( jpaEntityType, persistentClass.getVersion() ) + ); } - Map, EmbeddableType> getEmbeddableTypes() { - return embeddables; + @SuppressWarnings( "unchecked") + private Set> buildIdClassAttributes( + EntityTypeImpl jpaEntityType, + PersistentClass persistentClass) { + Set> attributes = new HashSet>(); + Iterator properties = persistentClass.getIdentifierMapper().getPropertyIterator(); + while ( properties.hasNext() ) { + attributes.add( + (SingularAttribute) attributeFactory.buildAttribute( jpaEntityType, properties.next() ) + ); + } + return attributes; } + } diff --git a/entitymanager/src/main/java/org/hibernate/ejb/metamodel/MetamodelImpl.java b/entitymanager/src/main/java/org/hibernate/ejb/metamodel/MetamodelImpl.java index 865bed1992..7e24375e52 100644 --- a/entitymanager/src/main/java/org/hibernate/ejb/metamodel/MetamodelImpl.java +++ b/entitymanager/src/main/java/org/hibernate/ejb/metamodel/MetamodelImpl.java @@ -24,8 +24,6 @@ package org.hibernate.ejb.metamodel; import java.util.Set; import java.util.Iterator; import java.util.Map; -import java.util.HashMap; -import java.util.Collections; import java.util.HashSet; import java.io.Serializable; import javax.persistence.metamodel.Metamodel; @@ -36,31 +34,54 @@ import javax.persistence.metamodel.EmbeddableType; import org.hibernate.mapping.PersistentClass; /** + * Hibernate implementation of the JPA {@link Metamodel} contract. + * + * @author Steve Ebersole * @author Emmanuel Bernard */ public class MetamodelImpl implements Metamodel, Serializable { + private final Map,EntityTypeImpl> entities; + private final Map, EmbeddableTypeImpl> embeddables; - private final Map,EntityType> entities; - private Map, EmbeddableType> embeddables; - - public MetamodelImpl(Iterator classes) { - Map,EntityType> localEntities = new HashMap,EntityType>(); + /** + * Instantiate the metamodel from the collection of Hibernate {@link PersistentClass} models. + * + * @param persistentClasses An iterator over the Hibernate {@link PersistentClass} models. + */ + public MetamodelImpl(Iterator persistentClasses) { MetadataContext context = new MetadataContext(); - while ( classes.hasNext() ) { - buildEntityType( classes, localEntities, context ); + while ( persistentClasses.hasNext() ) { + locateOrBuildEntityType( persistentClasses.next(), context ); } - this.entities = Collections.unmodifiableMap( localEntities ); - this.embeddables = Collections.unmodifiableMap( context.getEmbeddableTypes() ); - context.postProcess( this ); + this.entities = context.getEntityTypeMap(); + context.wrapUp(); + this.embeddables = context.getEmbeddableTypeMap(); } - private void buildEntityType(Iterator classes, Map, EntityType> localEntities, MetadataContext context) { - PersistentClass persistentClass = classes.next(); - @SuppressWarnings( "unchecked" ) - final Class clazz = persistentClass.getMappedClass(); - if ( clazz != null ) { - localEntities.put( clazz, new EntityTypeImpl(clazz, persistentClass, context) ); + private EntityTypeImpl locateOrBuildEntityType(PersistentClass persistentClass, MetadataContext context) { + EntityTypeImpl entityType = context.locateEntityType( persistentClass ); + if ( entityType == null ) { + entityType = buildEntityType( persistentClass, context ); } + return entityType; + } + + @SuppressWarnings({ "unchecked" }) + private EntityTypeImpl buildEntityType(PersistentClass persistentClass, MetadataContext context) { + final PersistentClass superPersistentClass = persistentClass.getSuperclass(); + final EntityTypeImpl superEntityType = superPersistentClass == null + ? null + : locateOrBuildEntityType( superPersistentClass, context ); + final Class javaType = persistentClass.getMappedClass(); + EntityTypeImpl entityType = new EntityTypeImpl( + javaType, + superEntityType, + persistentClass.getClassName(), + persistentClass.hasIdentifierProperty(), + persistentClass.isVersioned() + ); + context.registerEntityType( persistentClass, entityType ); + return entityType; } /** diff --git a/entitymanager/src/main/java/org/hibernate/ejb/metamodel/PluralAttributeImpl.java b/entitymanager/src/main/java/org/hibernate/ejb/metamodel/PluralAttributeImpl.java index 9286aabeb1..3242afae01 100644 --- a/entitymanager/src/main/java/org/hibernate/ejb/metamodel/PluralAttributeImpl.java +++ b/entitymanager/src/main/java/org/hibernate/ejb/metamodel/PluralAttributeImpl.java @@ -21,47 +21,45 @@ */ package org.hibernate.ejb.metamodel; -import java.lang.reflect.Member; -import java.util.Map; -import java.util.List; -import java.util.Set; -import java.util.Collection; import java.io.Serializable; -import javax.persistence.metamodel.PluralAttribute; -import javax.persistence.metamodel.ManagedType; -import javax.persistence.metamodel.Type; -import javax.persistence.metamodel.SetAttribute; +import java.lang.reflect.Member; +import java.util.Collection; +import java.util.List; +import java.util.Map; +import java.util.Set; import javax.persistence.metamodel.CollectionAttribute; import javax.persistence.metamodel.ListAttribute; import javax.persistence.metamodel.MapAttribute; +import javax.persistence.metamodel.PluralAttribute; +import javax.persistence.metamodel.SetAttribute; +import javax.persistence.metamodel.Type; import org.hibernate.mapping.Property; /** * @author Emmanuel Bernard + * @author Steve Ebersole */ -public abstract class PluralAttributeImpl implements PluralAttribute, Serializable { +public abstract class PluralAttributeImpl + extends AbstractAttribute + implements PluralAttribute, Serializable { - private final ManagedType ownerType; private final Type elementType; - //FIXME member is not serializable - private final Member member; - private final String name; - private final PersistentAttributeType persistentAttributeType; - private final Class collectionClass; private PluralAttributeImpl(Builder builder) { - this.ownerType = builder.type; + super( + builder.property.getName(), + builder.collectionClass, + builder.type, + builder.member, + builder.persistentAttributeType + ); this.elementType = builder.attributeType; - this.collectionClass = builder.collectionClass; - this.member = builder.member; - this.name = builder.property.getName(); - this.persistentAttributeType = builder.persistentAttributeType; } public static class Builder { private final Type attributeType; - private final ManagedType type; + private final AbstractManagedType type; private Member member; private PersistentAttributeType persistentAttributeType; private Property property; @@ -69,7 +67,7 @@ public abstract class PluralAttributeImpl implements PluralAttribute keyType; - private Builder(ManagedType ownerType, Type attrType, Class collectionClass, Type keyType) { + private Builder(AbstractManagedType ownerType, Type attrType, Class collectionClass, Type keyType) { this.type = ownerType; this.attributeType = attrType; this.collectionClass = collectionClass; @@ -91,94 +89,75 @@ public abstract class PluralAttributeImpl implements PluralAttribute PluralAttributeImpl build() { if ( Map.class.isAssignableFrom( collectionClass ) ) { - @SuppressWarnings( "unchecked" ) final Builder,E,K> builder = (Builder,E,K>) this; - @SuppressWarnings( "unchecked" ) - final PluralAttributeImpl result = ( PluralAttributeImpl ) new MapAttributeImpl( + return ( PluralAttributeImpl ) new MapAttributeImpl( builder ); - return result; } else if ( Set.class.isAssignableFrom( collectionClass ) ) { - @SuppressWarnings( "unchecked" ) final Builder, E,?> builder = (Builder, E,?>) this; - @SuppressWarnings( "unchecked" ) - final PluralAttributeImpl result = ( PluralAttributeImpl ) new SetAttributeImpl( + return ( PluralAttributeImpl ) new SetAttributeImpl( builder ); - return result; } else if ( List.class.isAssignableFrom( collectionClass ) ) { - @SuppressWarnings( "unchecked" ) final Builder, E,?> builder = (Builder, E,?>) this; - @SuppressWarnings( "unchecked" ) - final PluralAttributeImpl result = ( PluralAttributeImpl ) new ListAttributeImpl( + return ( PluralAttributeImpl ) new ListAttributeImpl( builder ); - return result; } else if ( Collection.class.isAssignableFrom( collectionClass ) ) { - @SuppressWarnings( "unchecked" ) final Builder,E,?> builder = (Builder, E,?>) this; - @SuppressWarnings( "unchecked" ) - final PluralAttributeImpl result = ( PluralAttributeImpl ) new CollectionAttributeImpl( + return ( PluralAttributeImpl ) new CollectionAttributeImpl( builder ); - return result; } throw new UnsupportedOperationException( "Unkown collection: " + collectionClass ); } } public static Builder create( - ManagedType ownerType, + AbstractManagedType ownerType, Type attrType, Class collectionClass, Type keyType) { return new Builder(ownerType, attrType, collectionClass, keyType); } - public String getName() { - return name; - } - - public PersistentAttributeType getPersistentAttributeType() { - return persistentAttributeType; - } - - public ManagedType getDeclaringType() { - return ownerType; - } - - public Class getJavaType() { - return collectionClass; - } - - public abstract CollectionType getCollectionType(); - + /** + * {@inheritDoc} + */ public Type getElementType() { return elementType; } - - public Member getJavaMember() { - return member; - } - + /** + * {@inheritDoc} + */ public boolean isAssociation() { return true; } + /** + * {@inheritDoc} + */ public boolean isCollection() { return true; } + /** + * {@inheritDoc} + */ public BindableType getBindableType() { return BindableType.PLURAL_ATTRIBUTE; } + /** + * {@inheritDoc} + */ public Class getBindableJavaType() { return elementType.getJavaType(); } @@ -188,6 +167,9 @@ public abstract class PluralAttributeImpl implements PluralAttribute implements PluralAttribute implements PluralAttribute implements PluralAttribute getKeyJavaType() { return keyType.getJavaType(); } + /** + * {@inheritDoc} + */ public Type getKeyType() { return keyType; } diff --git a/entitymanager/src/main/java/org/hibernate/ejb/metamodel/SingularAttributeImpl.java b/entitymanager/src/main/java/org/hibernate/ejb/metamodel/SingularAttributeImpl.java index 2bc0ea6b4b..01bcd2a532 100644 --- a/entitymanager/src/main/java/org/hibernate/ejb/metamodel/SingularAttributeImpl.java +++ b/entitymanager/src/main/java/org/hibernate/ejb/metamodel/SingularAttributeImpl.java @@ -23,145 +23,123 @@ package org.hibernate.ejb.metamodel; import java.lang.reflect.Member; import java.io.Serializable; -import javax.persistence.metamodel.ManagedType; import javax.persistence.metamodel.SingularAttribute; import javax.persistence.metamodel.Type; -import org.hibernate.mapping.Property; - /** * @author Emmanuel Bernard + * @author Steve Ebersole */ -public class SingularAttributeImpl implements SingularAttribute, Serializable { - private final boolean isId; +public class SingularAttributeImpl + extends AbstractAttribute + implements SingularAttribute, Serializable { + private final boolean isIdentifier; private final boolean isVersion; private final boolean isOptional; - private final ManagedType ownerType; - private final Type attrType; - //FIXME member is not serializable - private final Member member; - private final String name; - private final PersistentAttributeType persistentAttributeType; + private final Type attributeType; - private SingularAttributeImpl(Builder builder) { - this.ownerType = builder.type; - this.attrType = builder.attributeType; - this.isId = builder.isId; - this.isVersion = builder.isVersion; - final Property property = builder.property; - this.isOptional = property.isOptional(); - this.member = builder.member; - this.name = property.getName(); - if ( builder.persistentAttributeType != null) { - this.persistentAttributeType = builder.persistentAttributeType; - } - else { - this.persistentAttributeType = property.isComposite() ? - PersistentAttributeType.EMBEDDED : - PersistentAttributeType.BASIC; + public SingularAttributeImpl( + String name, + Class javaType, + AbstractManagedType declaringType, + Member member, + boolean isIdentifier, + boolean isVersion, + boolean isOptional, + Type attributeType, + PersistentAttributeType persistentAttributeType) { + super( name, javaType, declaringType, member, persistentAttributeType ); + this.isIdentifier = isIdentifier; + this.isVersion = isVersion; + this.isOptional = isOptional; + this.attributeType = attributeType; + } + + /** + * Subclass used to simply instantiation of singular attributes representing an entity's + * identifier. + */ + public static class Identifier extends SingularAttributeImpl { + public Identifier( + String name, + Class javaType, + AbstractManagedType declaringType, + Member member, + Type attributeType, + PersistentAttributeType persistentAttributeType) { + super( name, javaType, declaringType, member, true, false, false, attributeType, persistentAttributeType ); } } - public static class Builder { - private boolean isId; - private boolean isVersion; - //private boolean isOptional = true; - private final Type attributeType; - private final ManagedType type; - private Member member; - //private String name; - private PersistentAttributeType persistentAttributeType; - private Property property; - - - private Builder(ManagedType ownerType, Type attrType) { - this.type = ownerType; - this.attributeType = attrType; - } - - public Builder member(Member member) { - this.member = member; - return this; - } - - public Builder property(Property property) { - this.property = property; - return this; - } - - public Builder id() { - isId = true; - return this; - } - - public Builder version() { - isVersion = true; - return this; - } - - public SingularAttribute build() { - return new SingularAttributeImpl(this); - } - - public Builder persistentAttributeType(PersistentAttributeType attrType) { - this.persistentAttributeType = attrType; - return this; + /** + * Subclass used to simply instantiation of singular attributes representing an entity's + * version. + */ + public static class Version extends SingularAttributeImpl { + public Version( + String name, + Class javaType, + AbstractManagedType declaringType, + Member member, + Type attributeType, + PersistentAttributeType persistentAttributeType) { + super( name, javaType, declaringType, member, false, true, false, attributeType, persistentAttributeType ); } } - public static Builder create(ManagedType ownerType, Type attrType) { - return new Builder(ownerType, attrType); - } - + /** + * {@inheritDoc} + */ public boolean isId() { - return isId; + return isIdentifier; } + /** + * {@inheritDoc} + */ public boolean isVersion() { return isVersion; } + /** + * {@inheritDoc} + */ public boolean isOptional() { return isOptional; } + /** + * {@inheritDoc} + */ public Type getType() { - return attrType; - } - - public String getName() { - return name; - } - - public PersistentAttributeType getPersistentAttributeType() { - return persistentAttributeType; - } - - public ManagedType getDeclaringType() { - return ownerType; - } - - public Class getJavaType() { - return attrType.getJavaType(); - } - - public Member getJavaMember() { - return member; + return attributeType; } + /** + * {@inheritDoc} + */ public boolean isAssociation() { return false; } + /** + * {@inheritDoc} + */ public boolean isCollection() { return false; } + /** + * {@inheritDoc} + */ public BindableType getBindableType() { return BindableType.SINGULAR_ATTRIBUTE; } + /** + * {@inheritDoc} + */ public Class getBindableJavaType() { - return attrType.getJavaType(); + return attributeType.getJavaType(); } }