HHH-7957 - Integrate Public Review Draft of the JPA 2.1 spec : entity graph support - phase 1
This commit is contained in:
parent
76c14b1697
commit
5c453fee8d
|
@ -22,8 +22,10 @@
|
|||
* Boston, MA 02110-1301 USA
|
||||
*/
|
||||
package org.hibernate.cfg.annotations;
|
||||
|
||||
import java.lang.annotation.Annotation;
|
||||
import javax.persistence.Column;
|
||||
import javax.persistence.ForeignKey;
|
||||
import javax.persistence.JoinColumn;
|
||||
import javax.persistence.MapKeyJoinColumn;
|
||||
|
||||
|
@ -38,38 +40,52 @@ public class MapKeyJoinColumnDelegator implements JoinColumn {
|
|||
this.column = column;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String name() {
|
||||
return column.name();
|
||||
}
|
||||
|
||||
@Override
|
||||
public String referencedColumnName() {
|
||||
return column.referencedColumnName();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean unique() {
|
||||
return column.unique();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean nullable() {
|
||||
return column.nullable();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean insertable() {
|
||||
return column.insertable();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean updatable() {
|
||||
return column.updatable();
|
||||
}
|
||||
|
||||
@Override
|
||||
public String columnDefinition() {
|
||||
return column.columnDefinition();
|
||||
}
|
||||
|
||||
@Override
|
||||
public String table() {
|
||||
return column.table();
|
||||
}
|
||||
|
||||
@Override
|
||||
public ForeignKey foreignKey() {
|
||||
return column.foreignKey();
|
||||
}
|
||||
|
||||
@Override
|
||||
public Class<? extends Annotation> annotationType() {
|
||||
return Column.class;
|
||||
}
|
||||
|
|
|
@ -33,14 +33,11 @@ import java.util.Collections;
|
|||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
import org.jboss.logging.Logger;
|
||||
|
||||
import org.hibernate.jpa.internal.EntityManagerMessageLogger;
|
||||
import org.hibernate.jpa.internal.util.PersistenceUtilHelper;
|
||||
import org.hibernate.jpa.boot.internal.ParsedPersistenceXmlDescriptor;
|
||||
import org.hibernate.jpa.boot.internal.PersistenceXmlParser;
|
||||
import org.hibernate.jpa.boot.spi.Bootstrap;
|
||||
import org.hibernate.jpa.boot.spi.ProviderChecker;
|
||||
import org.hibernate.jpa.internal.util.PersistenceUtilHelper;
|
||||
|
||||
/**
|
||||
* The Hibernate {@link PersistenceProvider} implementation
|
||||
|
@ -49,10 +46,6 @@ import org.hibernate.jpa.boot.spi.ProviderChecker;
|
|||
* @author Steve Ebersole
|
||||
*/
|
||||
public class HibernatePersistenceProvider implements PersistenceProvider {
|
||||
private static final EntityManagerMessageLogger LOG = Logger.getMessageLogger(
|
||||
EntityManagerMessageLogger.class,
|
||||
HibernatePersistenceProvider.class.getName()
|
||||
);
|
||||
|
||||
private final PersistenceUtilHelper.MetadataCache cache = new PersistenceUtilHelper.MetadataCache();
|
||||
|
||||
|
@ -103,6 +96,17 @@ public class HibernatePersistenceProvider implements PersistenceProvider {
|
|||
return Bootstrap.getEntityManagerFactoryBuilder( info, integration ).build();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void generateSchema(PersistenceUnitInfo info, Map map) {
|
||||
// todo : implement
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean generateSchema(String persistenceUnitName, Map map) {
|
||||
// todo : implement
|
||||
return false;
|
||||
}
|
||||
|
||||
private final ProviderUtil providerUtil = new ProviderUtil() {
|
||||
@Override
|
||||
public LoadState isLoadedWithoutReference(Object proxy, String property) {
|
||||
|
|
|
@ -24,6 +24,7 @@
|
|||
package org.hibernate.jpa.internal;
|
||||
|
||||
import javax.persistence.Cache;
|
||||
import javax.persistence.EntityGraph;
|
||||
import javax.persistence.EntityManager;
|
||||
import javax.persistence.EntityManagerFactory;
|
||||
import javax.persistence.PersistenceContextType;
|
||||
|
@ -32,6 +33,8 @@ import javax.persistence.PersistenceUnitUtil;
|
|||
import javax.persistence.Query;
|
||||
import javax.persistence.SynchronizationType;
|
||||
import javax.persistence.criteria.CriteriaBuilder;
|
||||
import javax.persistence.metamodel.EntityType;
|
||||
import javax.persistence.metamodel.ManagedType;
|
||||
import javax.persistence.metamodel.Metamodel;
|
||||
import javax.persistence.spi.LoadState;
|
||||
import javax.persistence.spi.PersistenceUnitTransactionType;
|
||||
|
@ -39,10 +42,13 @@ import java.io.IOException;
|
|||
import java.io.InvalidObjectException;
|
||||
import java.io.ObjectOutputStream;
|
||||
import java.io.Serializable;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collections;
|
||||
import java.util.HashMap;
|
||||
import java.util.Iterator;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.concurrent.ConcurrentHashMap;
|
||||
|
||||
import org.jboss.logging.Logger;
|
||||
|
||||
|
@ -64,6 +70,7 @@ import org.hibernate.jpa.AvailableSettings;
|
|||
import org.hibernate.jpa.HibernateQuery;
|
||||
import org.hibernate.jpa.boot.internal.SettingsImpl;
|
||||
import org.hibernate.jpa.criteria.CriteriaBuilderImpl;
|
||||
import org.hibernate.jpa.internal.graph.EntityGraphImpl;
|
||||
import org.hibernate.jpa.internal.metamodel.MetamodelImpl;
|
||||
import org.hibernate.jpa.internal.util.PersistenceUtilHelper;
|
||||
import org.hibernate.mapping.PersistentClass;
|
||||
|
@ -94,6 +101,7 @@ public class EntityManagerFactoryImpl implements HibernateEntityManagerFactory {
|
|||
private final String entityManagerFactoryName;
|
||||
|
||||
private final transient PersistenceUtilHelper.MetadataCache cache = new PersistenceUtilHelper.MetadataCache();
|
||||
private final transient Map<String,EntityGraphImpl> entityGraphs = new ConcurrentHashMap<String, EntityGraphImpl>();
|
||||
|
||||
@SuppressWarnings( "unchecked" )
|
||||
public EntityManagerFactoryImpl(
|
||||
|
@ -321,6 +329,40 @@ public class EntityManagerFactoryImpl implements HibernateEntityManagerFactory {
|
|||
throw new PersistenceException( "Hibernate cannot unwrap EntityManagerFactory as " + cls.getName() );
|
||||
}
|
||||
|
||||
@Override
|
||||
public <T> void addNamedEntityGraph(String graphName, EntityGraph<T> entityGraph) {
|
||||
if ( ! EntityGraphImpl.class.isInstance( entityGraph ) ) {
|
||||
throw new IllegalArgumentException(
|
||||
"Unknown type of EntityGraph for making named : " + entityGraph.getClass().getName()
|
||||
);
|
||||
}
|
||||
final EntityGraphImpl<T> copy = ( (EntityGraphImpl<T>) entityGraph ).makeImmutableCopy( graphName );
|
||||
final EntityGraphImpl old = entityGraphs.put( graphName, copy );
|
||||
if ( old != null ) {
|
||||
log.debugf( "EntityGraph being replaced on EntityManagerFactory for name %s", graphName );
|
||||
}
|
||||
}
|
||||
|
||||
public EntityGraphImpl findEntityGraphByName(String name) {
|
||||
return entityGraphs.get( name );
|
||||
}
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
public <T> List<EntityGraph<? super T>> findEntityGraphsByType(Class<T> entityClass) {
|
||||
final EntityType<T> entityType = getMetamodel().entity( entityClass );
|
||||
if ( entityType == null ) {
|
||||
throw new IllegalArgumentException( "Given class is not an entity : " + entityClass.getName() );
|
||||
}
|
||||
|
||||
final List<EntityGraph<? super T>> results = new ArrayList<EntityGraph<? super T>>();
|
||||
for ( EntityGraphImpl entityGraph : this.entityGraphs.values() ) {
|
||||
if ( entityGraph.appliesTo( entityType ) ) {
|
||||
results.add( entityGraph );
|
||||
}
|
||||
}
|
||||
return results;
|
||||
}
|
||||
|
||||
public boolean isOpen() {
|
||||
return ! sessionFactory.isClosed();
|
||||
}
|
||||
|
|
|
@ -23,10 +23,13 @@
|
|||
*/
|
||||
package org.hibernate.jpa.internal;
|
||||
|
||||
import javax.persistence.EntityGraph;
|
||||
import javax.persistence.PersistenceContextType;
|
||||
import javax.persistence.PersistenceException;
|
||||
import javax.persistence.SynchronizationType;
|
||||
import javax.persistence.metamodel.EntityType;
|
||||
import javax.persistence.spi.PersistenceUnitTransactionType;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
import org.jboss.logging.Logger;
|
||||
|
@ -40,6 +43,7 @@ import org.hibernate.engine.spi.SessionBuilderImplementor;
|
|||
import org.hibernate.engine.spi.SessionImplementor;
|
||||
import org.hibernate.engine.spi.SessionOwner;
|
||||
import org.hibernate.jpa.AvailableSettings;
|
||||
import org.hibernate.jpa.internal.graph.EntityGraphImpl;
|
||||
|
||||
/**
|
||||
* Hibernate implementation of {@link javax.persistence.EntityManager}.
|
||||
|
@ -159,6 +163,35 @@ public class EntityManagerImpl extends AbstractEntityManagerImpl implements Sess
|
|||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public <T> EntityGraph<T> createEntityGraph(Class<T> rootType) {
|
||||
return new EntityGraphImpl<T>( null, getMetamodel().entity( rootType ), getEntityManagerFactory() );
|
||||
}
|
||||
|
||||
@Override
|
||||
public EntityGraph<?> createEntityGraph(String graphName) {
|
||||
final EntityGraphImpl named = getEntityManagerFactory().findEntityGraphByName( graphName );
|
||||
if ( named == null ) {
|
||||
return null;
|
||||
}
|
||||
return named.makeMutableCopy();
|
||||
}
|
||||
|
||||
@Override
|
||||
@SuppressWarnings("unchecked")
|
||||
public <T> EntityGraph<T> getEntityGraph(String graphName) {
|
||||
final EntityGraphImpl named = getEntityManagerFactory().findEntityGraphByName( graphName );
|
||||
if ( named == null ) {
|
||||
throw new IllegalArgumentException( "Could not locate EntityGraph with given name : " + graphName );
|
||||
}
|
||||
return named;
|
||||
}
|
||||
|
||||
@Override
|
||||
public <T> List<EntityGraph<? super T>> getEntityGraphs(Class<T> entityClass) {
|
||||
return getEntityManagerFactory().findEntityGraphsByType( entityClass );
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean shouldAutoCloseSession() {
|
||||
return !isOpen();
|
||||
|
|
|
@ -0,0 +1,67 @@
|
|||
/*
|
||||
* Hibernate, Relational Persistence for Idiomatic Java
|
||||
*
|
||||
* Copyright (c) 2013, Red Hat Inc. or third-party contributors as
|
||||
* indicated by the @author tags or express copyright attribution
|
||||
* statements applied by the authors. All third-party contributions are
|
||||
* distributed under license by Red Hat Inc.
|
||||
*
|
||||
* This copyrighted material is made available to anyone wishing to use, modify,
|
||||
* copy, or redistribute it subject to the terms and conditions of the GNU
|
||||
* Lesser General Public License, as published by the Free Software Foundation.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
|
||||
* or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License
|
||||
* for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public License
|
||||
* along with this distribution; if not, write to:
|
||||
* Free Software Foundation, Inc.
|
||||
* 51 Franklin Street, Fifth Floor
|
||||
* Boston, MA 02110-1301 USA
|
||||
*/
|
||||
package org.hibernate.jpa.internal.graph;
|
||||
|
||||
import javax.persistence.AttributeNode;
|
||||
import javax.persistence.metamodel.Attribute;
|
||||
import javax.persistence.metamodel.Type;
|
||||
|
||||
/**
|
||||
* Hibernate implementation of the JPA AttributeNode contract
|
||||
*
|
||||
* @author Steve Ebersole
|
||||
*/
|
||||
public class AttributeNodeImpl<T> implements AttributeNode<T>, GraphNode<T> {
|
||||
private final Attribute attribute;
|
||||
|
||||
public AttributeNodeImpl(Attribute attribute) {
|
||||
this.attribute = attribute;
|
||||
}
|
||||
|
||||
@Override
|
||||
public AttributeNodeImpl<T> makeImmutableCopy() {
|
||||
// simple attribute nodes are immutable already
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Type<T> getType() {
|
||||
// Linda says this is going away
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getAttributeName() {
|
||||
return attribute.getName();
|
||||
}
|
||||
|
||||
public Attribute getAttribute() {
|
||||
return attribute;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getRegistrationName() {
|
||||
return getAttributeName();
|
||||
}
|
||||
}
|
|
@ -0,0 +1,267 @@
|
|||
/*
|
||||
* Hibernate, Relational Persistence for Idiomatic Java
|
||||
*
|
||||
* Copyright (c) 2013, Red Hat Inc. or third-party contributors as
|
||||
* indicated by the @author tags or express copyright attribution
|
||||
* statements applied by the authors. All third-party contributions are
|
||||
* distributed under license by Red Hat Inc.
|
||||
*
|
||||
* This copyrighted material is made available to anyone wishing to use, modify,
|
||||
* copy, or redistribute it subject to the terms and conditions of the GNU
|
||||
* Lesser General Public License, as published by the Free Software Foundation.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
|
||||
* or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License
|
||||
* for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public License
|
||||
* along with this distribution; if not, write to:
|
||||
* Free Software Foundation, Inc.
|
||||
* 51 Franklin Street, Fifth Floor
|
||||
* Boston, MA 02110-1301 USA
|
||||
*/
|
||||
package org.hibernate.jpa.internal.graph;
|
||||
|
||||
import javax.persistence.AttributeNode;
|
||||
import javax.persistence.EntityGraph;
|
||||
import javax.persistence.Subgraph;
|
||||
import javax.persistence.metamodel.Attribute;
|
||||
import javax.persistence.metamodel.EntityType;
|
||||
import javax.persistence.metamodel.IdentifiableType;
|
||||
import javax.persistence.metamodel.ManagedType;
|
||||
import javax.persistence.metamodel.PluralAttribute;
|
||||
import javax.persistence.metamodel.SingularAttribute;
|
||||
import javax.persistence.metamodel.Type;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
import org.hibernate.jpa.HibernateEntityManagerFactory;
|
||||
|
||||
/**
|
||||
* The Hibernate implementation of the JPA EntityGraph contract.
|
||||
*
|
||||
* @author Steve Ebersole
|
||||
*/
|
||||
public class EntityGraphImpl<T> implements EntityGraph<T>, GraphDelegate.AttributeDelegate<T> {
|
||||
private final HibernateEntityManagerFactory entityManagerFactory;
|
||||
|
||||
private final String name;
|
||||
private final EntityType<T> entityType;
|
||||
private final GraphDelegate<T> graphDelegate;
|
||||
|
||||
|
||||
public EntityGraphImpl(String name, EntityType<T> entityType, HibernateEntityManagerFactory entityManagerFactory) {
|
||||
this.name = name;
|
||||
this.entityType = entityType;
|
||||
this.entityManagerFactory = entityManagerFactory;
|
||||
this.graphDelegate = new GraphDelegate<T>( this );
|
||||
}
|
||||
|
||||
public EntityGraphImpl<T> makeImmutableCopy(String name) {
|
||||
return new EntityGraphImpl<T>( name, this, false );
|
||||
}
|
||||
|
||||
public EntityGraphImpl<T> makeMutableCopy() {
|
||||
return new EntityGraphImpl<T>( name, this, true );
|
||||
}
|
||||
|
||||
private EntityGraphImpl(String name, EntityGraphImpl<T> original, boolean mutable) {
|
||||
this.name = name;
|
||||
this.entityType = original.entityType;
|
||||
this.entityManagerFactory = original.entityManagerFactory;
|
||||
this.graphDelegate = mutable
|
||||
? original.graphDelegate.makeMutableCopy( this )
|
||||
: original.graphDelegate.makeImmutableCopy( this );
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getName() {
|
||||
return name;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void addAttributeNodes(String... attributeNames) {
|
||||
graphDelegate.addAttributeNodes( attributeNames );
|
||||
}
|
||||
|
||||
@Override
|
||||
public void addAttributeNodes(Attribute<T, ?>... attributes) {
|
||||
graphDelegate.addAttributeNodes( attributes );
|
||||
}
|
||||
|
||||
@Override
|
||||
@SuppressWarnings("unchecked")
|
||||
public <X> Subgraph<X> addSubgraph(Attribute<T, X> attribute) {
|
||||
return (Subgraph<X>) addSubgraph( attribute, attribute.getJavaType() );
|
||||
}
|
||||
|
||||
@Override
|
||||
public <X> Subgraph<? extends X> addSubgraph(Attribute<T, X> attribute, Class<? extends X> type) {
|
||||
return graphDelegate.addSubgraph( attribute, type );
|
||||
}
|
||||
|
||||
@Override
|
||||
public <X> Subgraph<X> addSubgraph(String attributeName) {
|
||||
return graphDelegate.addSubgraph( attributeName );
|
||||
}
|
||||
|
||||
@Override
|
||||
public <X> Subgraph<X> addSubgraph(String attributeName, Class<X> type) {
|
||||
return graphDelegate.addSubgraph( attributeName, type );
|
||||
}
|
||||
|
||||
@Override
|
||||
@SuppressWarnings("unchecked")
|
||||
public <X> Subgraph<X> addKeySubgraph(Attribute<T, X> attribute) {
|
||||
return (Subgraph<X>) addKeySubgraph( attribute, attribute.getJavaType() );
|
||||
}
|
||||
|
||||
@Override
|
||||
public <X> Subgraph<? extends X> addKeySubgraph(Attribute<T, X> attribute, Class<? extends X> type) {
|
||||
return graphDelegate.addKeySubgraph( attribute, type );
|
||||
}
|
||||
|
||||
@Override
|
||||
public <X> Subgraph<X> addKeySubgraph(String attributeName) {
|
||||
return graphDelegate.addKeySubgraph( attributeName );
|
||||
}
|
||||
|
||||
@Override
|
||||
public <X> Subgraph<X> addKeySubgraph(String attributeName, Class<X> type) {
|
||||
return graphDelegate.addKeySubgraph( attributeName, type );
|
||||
}
|
||||
|
||||
@Override
|
||||
public <T1 extends Object> Subgraph<? extends T1> addSubclassSubgraph(Class<? extends T1> type) {
|
||||
return null; //To change body of implemented methods use File | Settings | File Templates.
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<AttributeNode<?>> getAttributeNodes() {
|
||||
return new ArrayList<AttributeNode<?>>( graphDelegate.getGraphNodes() );
|
||||
}
|
||||
|
||||
|
||||
// AttributeDelegate impl ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
@Override
|
||||
@SuppressWarnings("unchecked")
|
||||
public AttributeNodeImpl<?> buildAttributeNode(String attributeName) {
|
||||
return buildAttributeNode( resolveAttribute( attributeName ) );
|
||||
}
|
||||
|
||||
private Attribute<T,?> resolveAttribute(String attributeName) {
|
||||
final Attribute<T,?> attribute = entityType.getDeclaredAttribute( attributeName );
|
||||
if ( attribute == null ) {
|
||||
throw new IllegalArgumentException(
|
||||
String.format(
|
||||
"Given attribute name [%s] is not an attribute on this entity [%s]",
|
||||
attributeName,
|
||||
entityType.getName()
|
||||
)
|
||||
);
|
||||
}
|
||||
return attribute;
|
||||
}
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
private <X> Attribute<T, ? extends X> resolveAttribute(String attributeName, Class<? extends X> type) {
|
||||
final Attribute<T,?> attribute = entityType.getDeclaredAttribute( attributeName );
|
||||
if ( attribute == null ) {
|
||||
throw new IllegalArgumentException(
|
||||
String.format(
|
||||
"Given attribute name [%s] is not an attribute on this entity [%s]",
|
||||
attributeName,
|
||||
entityType.getName()
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
return (Attribute<T, ? extends X>) attribute;
|
||||
}
|
||||
|
||||
@Override
|
||||
public AttributeNodeImpl<?> buildAttributeNode(Attribute<T, ?> attribute) {
|
||||
return new AttributeNodeImpl<Object>( attribute );
|
||||
}
|
||||
|
||||
@Override
|
||||
public SubgraphImpl buildSubgraph(String attributeName) {
|
||||
final Attribute<T,?> attribute = resolveAttribute( attributeName );
|
||||
return new SubgraphImpl( attribute, toManagedType( attribute ) );
|
||||
}
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
private <X> ManagedType<X> toManagedType(Attribute<T, X> attribute) {
|
||||
if ( attribute.isCollection() ) {
|
||||
final Type elementType = ( (PluralAttribute) attribute ).getElementType();
|
||||
if ( ! ManagedType.class.isInstance( elementType ) ) {
|
||||
throw new IllegalArgumentException(
|
||||
String.format(
|
||||
"Specified collection attribute [%s] is not comprised of elements of a ManagedType",
|
||||
attribute.toString()
|
||||
)
|
||||
);
|
||||
}
|
||||
return (ManagedType<X>) elementType;
|
||||
}
|
||||
else {
|
||||
final Type type = ( (SingularAttribute) attribute ).getType();
|
||||
if ( ! ManagedType.class.isInstance( type ) ) {
|
||||
throw new IllegalArgumentException(
|
||||
String.format( "Specified attribute [%s] is not a ManagedType" , attribute.toString() )
|
||||
);
|
||||
}
|
||||
return (ManagedType<X>) type;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
@SuppressWarnings("unchecked")
|
||||
public <X> SubgraphImpl<X> buildSubgraph(String attributeName, Class<X> type) {
|
||||
final Attribute<T,X> attribute = (Attribute<T, X>) resolveAttribute( attributeName, type );
|
||||
return new SubgraphImpl<X>( attribute, toManagedType( attribute ) );
|
||||
}
|
||||
|
||||
@Override
|
||||
@SuppressWarnings("unchecked")
|
||||
public <X> SubgraphImpl<? extends X> buildSubgraph(Attribute<T, X> attribute, Class<? extends X> type) {
|
||||
return new SubgraphImpl( attribute, toManagedType( attribute ) );
|
||||
}
|
||||
|
||||
@Override
|
||||
public SubgraphImpl buildKeySubgraph(String attributeName) {
|
||||
final Attribute<T,?> attribute = resolveAttribute( attributeName );
|
||||
return new SubgraphImpl( attribute, toManagedType( attribute ), true );
|
||||
}
|
||||
|
||||
@Override
|
||||
@SuppressWarnings("unchecked")
|
||||
public <X> SubgraphImpl<X> buildKeySubgraph(String attributeName, Class<X> type) {
|
||||
final Attribute<T,X> attribute = (Attribute<T, X>) resolveAttribute( attributeName, type );
|
||||
return new SubgraphImpl<X>( attribute, toManagedType( attribute ), true );
|
||||
}
|
||||
|
||||
@Override
|
||||
@SuppressWarnings("unchecked")
|
||||
public <X> SubgraphImpl<? extends X> buildKeySubgraph(Attribute<T, X> attribute, Class<? extends X> type) {
|
||||
return new SubgraphImpl( attribute, toManagedType( attribute ), true );
|
||||
}
|
||||
|
||||
public boolean appliesTo(EntityType<? super T> entityType) {
|
||||
if ( this.entityType.equals( entityType ) ) {
|
||||
return true;
|
||||
}
|
||||
|
||||
IdentifiableType superType = entityType.getSupertype();
|
||||
while ( superType != null ) {
|
||||
if ( superType.equals( entityType ) ) {
|
||||
return true;
|
||||
}
|
||||
superType = superType.getSupertype();
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,194 @@
|
|||
/*
|
||||
* Hibernate, Relational Persistence for Idiomatic Java
|
||||
*
|
||||
* Copyright (c) 2013, Red Hat Inc. or third-party contributors as
|
||||
* indicated by the @author tags or express copyright attribution
|
||||
* statements applied by the authors. All third-party contributions are
|
||||
* distributed under license by Red Hat Inc.
|
||||
*
|
||||
* This copyrighted material is made available to anyone wishing to use, modify,
|
||||
* copy, or redistribute it subject to the terms and conditions of the GNU
|
||||
* Lesser General Public License, as published by the Free Software Foundation.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
|
||||
* or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License
|
||||
* for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public License
|
||||
* along with this distribution; if not, write to:
|
||||
* Free Software Foundation, Inc.
|
||||
* 51 Franklin Street, Fifth Floor
|
||||
* Boston, MA 02110-1301 USA
|
||||
*/
|
||||
package org.hibernate.jpa.internal.graph;
|
||||
|
||||
import javax.persistence.AttributeNode;
|
||||
import javax.persistence.Subgraph;
|
||||
import javax.persistence.metamodel.Attribute;
|
||||
import java.util.Collection;
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
|
||||
import org.jboss.logging.Logger;
|
||||
|
||||
import org.hibernate.internal.util.collections.CollectionHelper;
|
||||
|
||||
/**
|
||||
* @author Steve Ebersole
|
||||
*/
|
||||
public class GraphDelegate<T> {
|
||||
private static final Logger log = Logger.getLogger( GraphDelegate.class );
|
||||
|
||||
private final AttributeDelegate<T> attributeDelegate;
|
||||
private final boolean mutable;
|
||||
private Map<String, GraphNode<?>> graphNodeMap;
|
||||
|
||||
public GraphDelegate(AttributeDelegate<T> attributeDelegate) {
|
||||
this.attributeDelegate = attributeDelegate;
|
||||
this.mutable = true;
|
||||
}
|
||||
|
||||
private GraphDelegate(
|
||||
AttributeDelegate<T> attributeDelegate,
|
||||
GraphDelegate<T> original,
|
||||
boolean mutable) {
|
||||
this.attributeDelegate = attributeDelegate;
|
||||
this.graphNodeMap = makeSafeGraphNodeMapCopy( original.graphNodeMap );
|
||||
this.mutable = mutable;
|
||||
}
|
||||
|
||||
public GraphDelegate<T> makeImmutableCopy(AttributeDelegate<T> attributeDelegate) {
|
||||
return new GraphDelegate<T>( attributeDelegate, this, false );
|
||||
}
|
||||
|
||||
public GraphDelegate<T> makeMutableCopy(AttributeDelegate<T> attributeDelegate) {
|
||||
return new GraphDelegate<T>( attributeDelegate, this, true );
|
||||
}
|
||||
|
||||
private static Map<String, GraphNode<?>> makeSafeGraphNodeMapCopy(Map<String, GraphNode<?>> graphNodeMap) {
|
||||
if ( graphNodeMap == null ) {
|
||||
return null;
|
||||
}
|
||||
|
||||
final HashMap<String,GraphNode<?>> copy
|
||||
= new HashMap<String,GraphNode<?>>( CollectionHelper.determineProperSizing( graphNodeMap ) );
|
||||
for ( Map.Entry<String,GraphNode<?>> attributeNodeEntry : graphNodeMap.entrySet() ) {
|
||||
copy.put(
|
||||
attributeNodeEntry.getKey(),
|
||||
attributeNodeEntry.getValue().makeImmutableCopy()
|
||||
);
|
||||
}
|
||||
return copy;
|
||||
}
|
||||
|
||||
public Collection<GraphNode<?>> getGraphNodes() {
|
||||
return graphNodeMap.values();
|
||||
}
|
||||
|
||||
public void addAttributeNodes(String... attributeNames) {
|
||||
checkMutability();
|
||||
|
||||
for ( String attributeName : attributeNames ) {
|
||||
addNode( attributeDelegate.buildAttributeNode( attributeName ) );
|
||||
}
|
||||
}
|
||||
|
||||
private void checkMutability() {
|
||||
if ( ! mutable ) {
|
||||
throw new IllegalStateException( "Entity graph is not mutable" );
|
||||
}
|
||||
}
|
||||
|
||||
private void addNode(GraphNode graphNode) {
|
||||
if ( graphNodeMap == null ) {
|
||||
graphNodeMap = new HashMap<String, GraphNode<?>>();
|
||||
}
|
||||
else {
|
||||
final AttributeNode old = graphNodeMap.get( graphNode.getRegistrationName() );
|
||||
if ( old != null ) {
|
||||
log.debugf(
|
||||
"Encountered request to add entity graph node [%s] using a name [%s] under which another " +
|
||||
"node is already registered [%s]",
|
||||
old.getClass().getName(),
|
||||
graphNode.getRegistrationName(),
|
||||
graphNode.getClass().getName()
|
||||
);
|
||||
}
|
||||
}
|
||||
graphNodeMap.put( graphNode.getAttributeName(), graphNode );
|
||||
}
|
||||
|
||||
public void addAttributeNodes(Attribute<T, ?>... attributes) {
|
||||
checkMutability();
|
||||
|
||||
for ( Attribute<T,?> attribute : attributes ) {
|
||||
addNode( attributeDelegate.buildAttributeNode( attribute ) );
|
||||
}
|
||||
}
|
||||
|
||||
public <X> Subgraph<? extends X> addSubgraph(Attribute<T, X> attribute, Class<? extends X> type) {
|
||||
checkMutability();
|
||||
|
||||
final SubgraphImpl<? extends X> subgraph = attributeDelegate.buildSubgraph( attribute, type );
|
||||
addNode( subgraph );
|
||||
return subgraph;
|
||||
}
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
public <X> Subgraph<X> addSubgraph(String attributeName) {
|
||||
checkMutability();
|
||||
|
||||
final SubgraphImpl<X> subgraph = attributeDelegate.buildSubgraph( attributeName );
|
||||
addNode( subgraph );
|
||||
return subgraph;
|
||||
}
|
||||
|
||||
public <X> Subgraph<X> addSubgraph(String attributeName, Class<X> type) {
|
||||
checkMutability();
|
||||
|
||||
final SubgraphImpl<X> subgraph = attributeDelegate.buildSubgraph( attributeName, type );
|
||||
addNode( subgraph );
|
||||
return subgraph;
|
||||
}
|
||||
|
||||
public <X> Subgraph<? extends X> addKeySubgraph(Attribute<T, X> attribute, Class<? extends X> type) {
|
||||
checkMutability();
|
||||
|
||||
final SubgraphImpl<? extends X> subgraph = attributeDelegate.buildKeySubgraph( attribute, type );
|
||||
addNode( subgraph );
|
||||
return subgraph;
|
||||
}
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
public <X> Subgraph<X> addKeySubgraph(String attributeName) {
|
||||
checkMutability();
|
||||
|
||||
final SubgraphImpl<X> subgraph = attributeDelegate.buildKeySubgraph( attributeName );
|
||||
addNode( subgraph );
|
||||
return subgraph;
|
||||
}
|
||||
|
||||
public <X> Subgraph<X> addKeySubgraph(String attributeName, Class<X> type) {
|
||||
checkMutability();
|
||||
|
||||
final SubgraphImpl<X> subgraph = attributeDelegate.buildKeySubgraph( attributeName, type );
|
||||
addNode( subgraph );
|
||||
return subgraph;
|
||||
}
|
||||
|
||||
|
||||
public static interface AttributeDelegate<T> {
|
||||
public AttributeNodeImpl<?> buildAttributeNode(String attributeName);
|
||||
public AttributeNodeImpl<?> buildAttributeNode(Attribute<T,?> attribute);
|
||||
|
||||
public SubgraphImpl buildSubgraph(String atributeName);
|
||||
public <X> SubgraphImpl<X> buildSubgraph(String atributeName, Class<X> type);
|
||||
public <X> SubgraphImpl<? extends X> buildSubgraph(Attribute<T, X> attribute, Class<? extends X> type);
|
||||
|
||||
public SubgraphImpl buildKeySubgraph(String attributeName);
|
||||
public <X> SubgraphImpl<X> buildKeySubgraph(String attributeName, Class<X> type);
|
||||
public <X> SubgraphImpl<? extends X> buildKeySubgraph(Attribute<T,X> attribute, Class<? extends X> type);
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,34 @@
|
|||
/*
|
||||
* Hibernate, Relational Persistence for Idiomatic Java
|
||||
*
|
||||
* Copyright (c) 2013, Red Hat Inc. or third-party contributors as
|
||||
* indicated by the @author tags or express copyright attribution
|
||||
* statements applied by the authors. All third-party contributions are
|
||||
* distributed under license by Red Hat Inc.
|
||||
*
|
||||
* This copyrighted material is made available to anyone wishing to use, modify,
|
||||
* copy, or redistribute it subject to the terms and conditions of the GNU
|
||||
* Lesser General Public License, as published by the Free Software Foundation.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
|
||||
* or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License
|
||||
* for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public License
|
||||
* along with this distribution; if not, write to:
|
||||
* Free Software Foundation, Inc.
|
||||
* 51 Franklin Street, Fifth Floor
|
||||
* Boston, MA 02110-1301 USA
|
||||
*/
|
||||
package org.hibernate.jpa.internal.graph;
|
||||
|
||||
import javax.persistence.AttributeNode;
|
||||
|
||||
/**
|
||||
* @author Steve Ebersole
|
||||
*/
|
||||
public interface GraphNode<T> extends AttributeNode<T> {
|
||||
public String getRegistrationName();
|
||||
public GraphNode<T> makeImmutableCopy();
|
||||
}
|
|
@ -0,0 +1,244 @@
|
|||
/*
|
||||
* Hibernate, Relational Persistence for Idiomatic Java
|
||||
*
|
||||
* Copyright (c) 2013, Red Hat Inc. or third-party contributors as
|
||||
* indicated by the @author tags or express copyright attribution
|
||||
* statements applied by the authors. All third-party contributions are
|
||||
* distributed under license by Red Hat Inc.
|
||||
*
|
||||
* This copyrighted material is made available to anyone wishing to use, modify,
|
||||
* copy, or redistribute it subject to the terms and conditions of the GNU
|
||||
* Lesser General Public License, as published by the Free Software Foundation.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
|
||||
* or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License
|
||||
* for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public License
|
||||
* along with this distribution; if not, write to:
|
||||
* Free Software Foundation, Inc.
|
||||
* 51 Franklin Street, Fifth Floor
|
||||
* Boston, MA 02110-1301 USA
|
||||
*/
|
||||
package org.hibernate.jpa.internal.graph;
|
||||
|
||||
import javax.persistence.AttributeNode;
|
||||
import javax.persistence.Subgraph;
|
||||
import javax.persistence.metamodel.Attribute;
|
||||
import javax.persistence.metamodel.ManagedType;
|
||||
import javax.persistence.metamodel.PluralAttribute;
|
||||
import javax.persistence.metamodel.SingularAttribute;
|
||||
import javax.persistence.metamodel.Type;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* @author Steve Ebersole
|
||||
*/
|
||||
public class SubgraphImpl<T> extends AttributeNodeImpl<T>
|
||||
implements Subgraph<T>, GraphNode<T>, GraphDelegate.AttributeDelegate<T> {
|
||||
|
||||
private final ManagedType managedType;
|
||||
private final boolean isMapKeySubgraph;
|
||||
private final GraphDelegate<T> graphDelegate;
|
||||
|
||||
public SubgraphImpl(Attribute attribute, ManagedType managedType) {
|
||||
this( attribute, managedType, false );
|
||||
}
|
||||
|
||||
public SubgraphImpl(Attribute attribute, ManagedType managedType, boolean isMapKeySubgraph) {
|
||||
super( attribute );
|
||||
this.managedType = managedType;
|
||||
this.isMapKeySubgraph = isMapKeySubgraph;
|
||||
this.graphDelegate = new GraphDelegate<T>( this );
|
||||
}
|
||||
|
||||
private SubgraphImpl(SubgraphImpl<T> original) {
|
||||
super( original.getAttribute() );
|
||||
this.managedType = original.managedType;
|
||||
this.isMapKeySubgraph = original.isMapKeySubgraph;
|
||||
this.graphDelegate = original.graphDelegate.makeImmutableCopy( this );
|
||||
}
|
||||
|
||||
@Override
|
||||
public SubgraphImpl<T> makeImmutableCopy() {
|
||||
return new SubgraphImpl<T>( this );
|
||||
}
|
||||
|
||||
public boolean isMapKeySubgraph() {
|
||||
return isMapKeySubgraph;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void addAttributeNodes(String... attributeNames) {
|
||||
graphDelegate.addAttributeNodes( attributeNames );
|
||||
}
|
||||
|
||||
@Override
|
||||
public void addAttributeNodes(Attribute<T, ?>... attributes) {
|
||||
graphDelegate.addAttributeNodes( attributes );
|
||||
}
|
||||
|
||||
@Override
|
||||
@SuppressWarnings("unchecked")
|
||||
public <X> Subgraph<X> addSubgraph(Attribute<T, X> attribute) {
|
||||
return (Subgraph<X>) addSubgraph( attribute, attribute.getJavaType() );
|
||||
}
|
||||
|
||||
@Override
|
||||
public <X> Subgraph<? extends X> addSubgraph(Attribute<T, X> attribute, Class<? extends X> type) {
|
||||
return graphDelegate.addSubgraph( attribute, type );
|
||||
}
|
||||
|
||||
@Override
|
||||
public <X> Subgraph<X> addSubgraph(String attributeName) {
|
||||
return graphDelegate.addSubgraph( attributeName );
|
||||
}
|
||||
|
||||
@Override
|
||||
public <X> Subgraph<X> addSubgraph(String attributeName, Class<X> type) {
|
||||
return graphDelegate.addSubgraph( attributeName, type );
|
||||
}
|
||||
|
||||
@Override
|
||||
@SuppressWarnings("unchecked")
|
||||
public <X> Subgraph<X> addKeySubgraph(Attribute<T, X> attribute) {
|
||||
return (Subgraph<X>) addKeySubgraph( attribute, attribute.getJavaType() );
|
||||
}
|
||||
|
||||
@Override
|
||||
public <X> Subgraph<? extends X> addKeySubgraph(Attribute<T, X> attribute, Class<? extends X> type) {
|
||||
return graphDelegate.addKeySubgraph( attribute, type );
|
||||
}
|
||||
|
||||
@Override
|
||||
public <X> Subgraph<X> addKeySubgraph(String attributeName) {
|
||||
return graphDelegate.addKeySubgraph( attributeName );
|
||||
}
|
||||
|
||||
@Override
|
||||
public <X> Subgraph<X> addKeySubgraph(String attributeName, Class<X> type) {
|
||||
return graphDelegate.addKeySubgraph( attributeName, type );
|
||||
}
|
||||
|
||||
@Override
|
||||
@SuppressWarnings("unchecked")
|
||||
public Class<T> getClassType() {
|
||||
return managedType.getJavaType();
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<AttributeNode<?>> getAttributeNodes() {
|
||||
return new ArrayList<AttributeNode<?>>( graphDelegate.getGraphNodes() );
|
||||
}
|
||||
|
||||
|
||||
// AttributeDelegate impl ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
@Override
|
||||
@SuppressWarnings("unchecked")
|
||||
public AttributeNodeImpl<?> buildAttributeNode(String attributeName) {
|
||||
return buildAttributeNode( resolveAttribute( attributeName ) );
|
||||
}
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
private Attribute<T,?> resolveAttribute(String attributeName) {
|
||||
final Attribute<T,?> attribute = managedType.getDeclaredAttribute( attributeName );
|
||||
if ( attribute == null ) {
|
||||
throw new IllegalArgumentException(
|
||||
String.format(
|
||||
"Given attribute name [%s] is not an attribute on this class [%s]",
|
||||
attributeName,
|
||||
managedType.getClass().getName()
|
||||
)
|
||||
);
|
||||
}
|
||||
return attribute;
|
||||
}
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
private <X> Attribute<T, ? extends X> resolveAttribute(String attributeName, Class<? extends X> type) {
|
||||
final Attribute<T,?> attribute = managedType.getDeclaredAttribute( attributeName );
|
||||
if ( attribute == null ) {
|
||||
throw new IllegalArgumentException(
|
||||
String.format(
|
||||
"Given attribute name [%s] is not an attribute on this class [%s]",
|
||||
attributeName,
|
||||
managedType.getClass().getName()
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
return (Attribute<T, ? extends X>) attribute;
|
||||
}
|
||||
|
||||
@Override
|
||||
public AttributeNodeImpl<?> buildAttributeNode(Attribute<T, ?> attribute) {
|
||||
return new AttributeNodeImpl<Object>( attribute );
|
||||
}
|
||||
|
||||
@Override
|
||||
public SubgraphImpl buildSubgraph(String attributeName) {
|
||||
final Attribute<T,?> attribute = resolveAttribute( attributeName );
|
||||
return new SubgraphImpl( attribute, toManagedType( attribute ) );
|
||||
}
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
private <X> ManagedType<X> toManagedType(Attribute<T, X> attribute) {
|
||||
if ( attribute.isCollection() ) {
|
||||
final Type elementType = ( (PluralAttribute) attribute ).getElementType();
|
||||
if ( ! ManagedType.class.isInstance( elementType ) ) {
|
||||
throw new IllegalArgumentException(
|
||||
String.format(
|
||||
"Specified collection attribute [%s] is not comprised of elements of a ManagedType",
|
||||
attribute.toString()
|
||||
)
|
||||
);
|
||||
}
|
||||
return (ManagedType<X>) elementType;
|
||||
}
|
||||
else {
|
||||
final Type type = ( (SingularAttribute) attribute ).getType();
|
||||
if ( ! ManagedType.class.isInstance( type ) ) {
|
||||
throw new IllegalArgumentException(
|
||||
String.format( "Specified attribute [%s] is not a ManagedType" , attribute.toString() )
|
||||
);
|
||||
}
|
||||
return (ManagedType<X>) type;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
@SuppressWarnings("unchecked")
|
||||
public <X> SubgraphImpl<X> buildSubgraph(String attributeName, Class<X> type) {
|
||||
final Attribute<T,X> attribute = (Attribute<T, X>) resolveAttribute( attributeName, type );
|
||||
return new SubgraphImpl<X>( attribute, toManagedType( attribute ) );
|
||||
}
|
||||
|
||||
@Override
|
||||
@SuppressWarnings("unchecked")
|
||||
public <X> SubgraphImpl<? extends X> buildSubgraph(Attribute<T, X> attribute, Class<? extends X> type) {
|
||||
return new SubgraphImpl( attribute, toManagedType( attribute ) );
|
||||
}
|
||||
|
||||
@Override
|
||||
public SubgraphImpl buildKeySubgraph(String attributeName) {
|
||||
final Attribute<T,?> attribute = resolveAttribute( attributeName );
|
||||
return new SubgraphImpl( attribute, toManagedType( attribute ), true );
|
||||
}
|
||||
|
||||
@Override
|
||||
@SuppressWarnings("unchecked")
|
||||
public <X> SubgraphImpl<X> buildKeySubgraph(String attributeName, Class<X> type) {
|
||||
final Attribute<T,X> attribute = (Attribute<T, X>) resolveAttribute( attributeName, type );
|
||||
return new SubgraphImpl<X>( attribute, toManagedType( attribute ), true );
|
||||
}
|
||||
|
||||
@Override
|
||||
@SuppressWarnings("unchecked")
|
||||
public <X> SubgraphImpl<? extends X> buildKeySubgraph(Attribute<T, X> attribute, Class<? extends X> type) {
|
||||
return new SubgraphImpl( attribute, toManagedType( attribute ), true );
|
||||
}
|
||||
|
||||
}
|
|
@ -54,7 +54,7 @@ ext {
|
|||
javassist: 'org.javassist:javassist:3.15.0-GA',
|
||||
|
||||
// javax
|
||||
jpa: 'org.hibernate.javax.persistence:hibernate-jpa-2.1-api:1.0.0.Draft-7plus',
|
||||
jpa: 'org.hibernate.javax.persistence:hibernate-jpa-2.1-api:1.0.0.Draft-10',
|
||||
jta: 'org.jboss.spec.javax.transaction:jboss-transaction-api_1.1_spec:1.0.0.Final',
|
||||
validation: 'javax.validation:validation-api:1.0.0.GA',
|
||||
jacc: 'org.jboss.spec.javax.security.jacc:jboss-jacc-api_1.4_spec:1.0.0.Final',
|
||||
|
|
Loading…
Reference in New Issue