HHH-7037 pushing attribute nature into MappedAttribute and creating empty source impls for *toMany sources

This commit is contained in:
Hardy Ferentschik 2012-03-05 17:05:46 +01:00
parent 1657f9f605
commit 3aaed02a2e
10 changed files with 354 additions and 75 deletions

View File

@ -31,7 +31,6 @@ import java.util.List;
import org.jboss.jandex.AnnotationInstance;
import org.jboss.jandex.Index;
import org.jboss.jandex.Indexer;
import org.jboss.logging.Logger;
import org.hibernate.AssertionFailure;
import org.hibernate.HibernateException;
@ -60,8 +59,6 @@ import org.hibernate.service.classloading.spi.ClassLoaderService;
* @author Steve Ebersole
*/
public class AnnotationMetadataSourceProcessorImpl implements MetadataSourceProcessor {
private static final Logger LOG = Logger.getLogger( AnnotationMetadataSourceProcessorImpl.class );
private final MetadataImplementor metadata;
private AnnotationBindingContext bindingContext;

View File

@ -54,7 +54,6 @@ import org.hibernate.metamodel.spi.source.MappingException;
* @author Hardy Ferentschik
*/
public class AssociationAttribute extends MappedAttribute {
private final AttributeNature associationNature;
private final boolean ignoreNotFound;
private final String referencedEntityType;
private final String mappedBy;
@ -90,17 +89,16 @@ public class AssociationAttribute extends MappedAttribute {
AssociationAttribute(String name,
Class<?> javaType,
AttributeNature associationType,
AttributeNature attributeNature,
String accessType,
Map<DotName, List<AnnotationInstance>> annotations,
EntityBindingContext context) {
super( name, javaType, accessType, annotations, context );
this.associationNature = associationType;
super( name, javaType, attributeNature, accessType, annotations, context );
this.ignoreNotFound = ignoreNotFound();
AnnotationInstance associationAnnotation = JandexHelper.getSingleAnnotation(
annotations,
associationType.getAnnotationDotName()
attributeNature.getAnnotationDotName()
);
// using jandex we don't really care which exact type of annotation we are dealing with
@ -129,10 +127,6 @@ public class AssociationAttribute extends MappedAttribute {
return mappedBy;
}
public AttributeNature getAssociationNature() {
return associationNature;
}
public Set<CascadeType> getCascadeTypes() {
return cascadeTypes;
}
@ -324,8 +318,8 @@ public class AssociationAttribute extends MappedAttribute {
return null;
}
if ( !( AttributeNature.MANY_TO_ONE.equals( getAssociationNature() ) || AttributeNature.MANY_TO_ONE
.equals( getAssociationNature() ) ) ) {
if ( !( AttributeNature.MANY_TO_ONE.equals( getAttributeNature() ) || AttributeNature.MANY_TO_ONE
.equals( getAttributeNature() ) ) ) {
throw new MappingException(
"@MapsId can only be specified on a many-to-one or one-to-one associations",
getContext().getOrigin()

View File

@ -25,6 +25,7 @@ package org.hibernate.metamodel.internal.source.annotations.attribute;
import org.jboss.jandex.DotName;
import org.hibernate.metamodel.internal.source.annotations.HibernateDotNames;
import org.hibernate.metamodel.internal.source.annotations.JPADotNames;
/**
@ -38,6 +39,7 @@ public enum AttributeNature {
ONE_TO_MANY( JPADotNames.ONE_TO_MANY ),
MANY_TO_ONE( JPADotNames.MANY_TO_ONE ),
MANY_TO_MANY( JPADotNames.MANY_TO_MANY ),
MANY_TO_ANY( HibernateDotNames.MANY_TO_ANY ),
ELEMENT_COLLECTION( JPADotNames.ELEMENT_COLLECTION ),
EMBEDDED_ID( JPADotNames.EMBEDDED_ID ),
EMBEDDED( JPADotNames.EMBEDDED );

View File

@ -93,23 +93,24 @@ public class BasicAttribute extends MappedAttribute {
private final String customWriteFragment;
private final String customReadFragment;
private final String checkCondition;
private AttributeTypeResolver resolver;
public static BasicAttribute createSimpleAttribute(String name,
Class<?> attributeType,
AttributeNature attributeNature,
Map<DotName, List<AnnotationInstance>> annotations,
String accessType,
EntityBindingContext context) {
return new BasicAttribute( name, attributeType, accessType, annotations, context );
return new BasicAttribute( name, attributeType, attributeNature, accessType, annotations, context );
}
BasicAttribute(String name,
Class<?> attributeType,
AttributeNature attributeNature,
String accessType,
Map<DotName, List<AnnotationInstance>> annotations,
EntityBindingContext context) {
super( name, attributeType, accessType, annotations, context );
super( name, attributeType, attributeNature, accessType, annotations, context );
AnnotationInstance versionAnnotation = JandexHelper.getSingleAnnotation( annotations, JPADotNames.VERSION );
isVersioned = versionAnnotation != null;
@ -149,7 +150,7 @@ public class BasicAttribute extends MappedAttribute {
String[] readWrite = createCustomReadWrite( columnTransformerAnnotations );
this.customReadFragment = readWrite[0];
this.customWriteFragment = readWrite[1];
this.checkCondition = parseCheckAnnotation();
}
public boolean isVersioned() {
@ -184,10 +185,6 @@ public class BasicAttribute extends MappedAttribute {
return customReadFragment;
}
public String getCheckCondition() {
return checkCondition;
}
public IdGenerator getIdGenerator() {
return idGenerator;
}
@ -291,15 +288,6 @@ public class BasicAttribute extends MappedAttribute {
return readWrite;
}
private String parseCheckAnnotation() {
String checkCondition = null;
AnnotationInstance checkAnnotation = JandexHelper.getSingleAnnotation( annotations(), HibernateDotNames.CHECK );
if ( checkAnnotation != null ) {
checkCondition = checkAnnotation.value( "constraints" ).toString();
}
return checkCondition;
}
private IdGenerator checkGeneratedValueAnnotation() {
IdGenerator generator = null;
AnnotationInstance generatedValueAnnotation = JandexHelper.getSingleAnnotation(

View File

@ -25,10 +25,9 @@ package org.hibernate.metamodel.internal.source.annotations.attribute;
import java.util.ArrayList;
import java.util.Collection;
import java.util.HashSet;
import java.util.List;
import org.hibernate.FetchMode;
import org.hibernate.annotations.common.reflection.java.JavaXMember;
import org.hibernate.engine.spi.CascadeStyle;
import org.hibernate.metamodel.spi.binding.CascadeType;
import org.hibernate.metamodel.spi.source.ManyToManyPluralAttributeElementSource;
@ -38,11 +37,10 @@ import org.hibernate.metamodel.spi.source.RelationalValueSource;
/**
* @author Hardy Ferentschik
*/
public class ManyToManyPluralAttributeElementSourceImpl
implements ManyToManyPluralAttributeElementSource {
private final CollectionAssociationAttribute associationAttribute;
public class ManyToManyPluralAttributeElementSourceImpl implements ManyToManyPluralAttributeElementSource {
private final PluralAssociationAttribute associationAttribute;
public ManyToManyPluralAttributeElementSourceImpl(CollectionAssociationAttribute associationAttribute) {
public ManyToManyPluralAttributeElementSourceImpl(PluralAssociationAttribute associationAttribute) {
this.associationAttribute = associationAttribute;
}
@ -59,7 +57,13 @@ public class ManyToManyPluralAttributeElementSourceImpl
@Override
public Collection<String> getReferencedColumnNames() {
return null; //To change body of implemented methods use File | Settings | File Templates.
HashSet<String> referencedColumnNames = new HashSet<String>();
for ( Column column : associationAttribute.getColumnValues() ) {
if ( column.getReferencedColumnName() != null ) {
referencedColumnNames.add( column.getReferencedColumnName() );
}
}
return referencedColumnNames;
}
@Override

View File

@ -59,6 +59,11 @@ public abstract class MappedAttribute implements Comparable<MappedAttribute> {
*/
private final Class<?> attributeType;
/**
* The nature of the attribute
*/
AttributeNature attributeNature;
/**
* The access type for this property. At the moment this is either 'field' or 'property', but Hibernate
* also allows custom named accessors (see {@link org.hibernate.property.PropertyAccessorFactory}).
@ -82,16 +87,23 @@ public abstract class MappedAttribute implements Comparable<MappedAttribute> {
*/
private final boolean isOptimisticLockable;
/**
* Contains the SQL check condition specified via {@link org.hibernate.annotations.Check} or null if no annotation
* is specified.
*/
private final String checkCondition;
/**
* The binding context
*/
private final EntityBindingContext context;
MappedAttribute(String name, Class<?> attributeType, String accessType, Map<DotName, List<AnnotationInstance>> annotations, EntityBindingContext context) {
MappedAttribute(String name, Class<?> attributeType, AttributeNature attributeNature, String accessType, Map<DotName, List<AnnotationInstance>> annotations, EntityBindingContext context) {
this.context = context;
this.annotations = annotations;
this.name = name;
this.attributeType = attributeType;
this.attributeNature = attributeNature;
this.accessType = accessType;
//if this attribute has either @Id or @EmbeddedId, then it is an id attribute
@ -101,7 +113,9 @@ public abstract class MappedAttribute implements Comparable<MappedAttribute> {
JPADotNames.EMBEDDED_ID
);
this.isId = ( idAnnotation != null || embeddedIdAnnotation != null );
this.isOptimisticLockable = checkOptimisticLockAnnotation();
this.checkCondition = checkCheckAnnotation();
checkColumnAnnotations( annotations );
}
@ -137,6 +151,14 @@ public abstract class MappedAttribute implements Comparable<MappedAttribute> {
return isOptimisticLockable;
}
public AttributeNature getAttributeNature() {
return attributeNature;
}
public String getCheckCondition() {
return checkCondition;
}
@Override
public int compareTo(MappedAttribute mappedProperty) {
return name.compareTo( mappedProperty.getName() );
@ -224,7 +246,15 @@ public abstract class MappedAttribute implements Comparable<MappedAttribute> {
columnValues.add( new Column( annotation ) );
}
}
}
private String checkCheckAnnotation() {
String checkCondition = null;
AnnotationInstance checkAnnotation = JandexHelper.getSingleAnnotation( annotations(), HibernateDotNames.CHECK );
if ( checkAnnotation != null ) {
checkCondition = checkAnnotation.value( "constraints" ).toString();
}
return checkCondition;
}
}

View File

@ -37,23 +37,24 @@ import org.hibernate.metamodel.internal.source.annotations.JandexHelper;
import org.hibernate.metamodel.internal.source.annotations.entity.EntityBindingContext;
/**
* Represents an collection association attribute.
* Represents an collection (collection, list, set, map) association attribute.
*
* @author Hardy Ferentschik
*/
public class CollectionAssociationAttribute extends AssociationAttribute {
public class PluralAssociationAttribute extends AssociationAttribute {
private final String whereClause;
private final String orderBy;
// Used for the non-owning side of a ManyToMany relationship
private final String inverseForeignKeyName;
public static CollectionAssociationAttribute createPluralAssociationAttribute(String name,
Class<?> attributeType,
AttributeNature attributeNature,
String accessType,
Map<DotName, List<AnnotationInstance>> annotations,
EntityBindingContext context) {
return new CollectionAssociationAttribute(
public static PluralAssociationAttribute createPluralAssociationAttribute(String name,
Class<?> attributeType,
AttributeNature attributeNature,
String accessType,
Map<DotName, List<AnnotationInstance>> annotations,
EntityBindingContext context) {
return new PluralAssociationAttribute(
name,
attributeType,
attributeNature,
@ -63,17 +64,28 @@ public class CollectionAssociationAttribute extends AssociationAttribute {
);
}
private CollectionAssociationAttribute(String name,
Class<?> javaType,
AttributeNature associationType,
String accessType,
Map<DotName, List<AnnotationInstance>> annotations,
EntityBindingContext context) {
public String getWhereClause() {
return whereClause;
}
public String getOrderBy() {
return orderBy;
}
public String getInverseForeignKeyName() {
return inverseForeignKeyName;
}
private PluralAssociationAttribute(String name,
Class<?> javaType,
AttributeNature associationType,
String accessType,
Map<DotName, List<AnnotationInstance>> annotations,
EntityBindingContext context) {
super( name, javaType, associationType, accessType, annotations, context );
this.whereClause = determineWereClause();
this.orderBy = determineOrderBy();
this.inverseForeignKeyName = determineInverseForeignKeyName();
}
private String determineInverseForeignKeyName() {
@ -137,18 +149,6 @@ public class CollectionAssociationAttribute extends AssociationAttribute {
return orderBy;
}
public String getWhereClause() {
return whereClause;
}
public String getOrderBy() {
return orderBy;
}
public String getInverseForeignKeyName() {
return inverseForeignKeyName;
}
}

View File

@ -0,0 +1,248 @@
/*
* Hibernate, Relational Persistence for Idiomatic Java
*
* Copyright (c) 2012, 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.metamodel.internal.source.annotations.attribute;
import java.util.List;
import java.util.Map;
import java.util.Set;
import org.hibernate.FetchMode;
import org.hibernate.engine.FetchStyle;
import org.hibernate.engine.FetchTiming;
import org.hibernate.engine.spi.CascadeStyle;
import org.hibernate.metamodel.spi.binding.Caching;
import org.hibernate.metamodel.spi.binding.CustomSQL;
import org.hibernate.metamodel.spi.source.ExplicitHibernateTypeSource;
import org.hibernate.metamodel.spi.source.ManyToAnyPluralAttributeElementSource;
import org.hibernate.metamodel.spi.source.MetaAttributeSource;
import org.hibernate.metamodel.spi.source.OneToManyPluralAttributeElementSource;
import org.hibernate.metamodel.spi.source.PluralAttributeElementNature;
import org.hibernate.metamodel.spi.source.PluralAttributeElementSource;
import org.hibernate.metamodel.spi.source.PluralAttributeKeySource;
import org.hibernate.metamodel.spi.source.PluralAttributeNature;
import org.hibernate.metamodel.spi.source.PluralAttributeSource;
import org.hibernate.metamodel.spi.source.TableSpecificationSource;
/**
* @author Hardy Ferentschik
*/
public class PluralAttributeSourceImpl implements PluralAttributeSource {
PluralAssociationAttribute attribute;
public PluralAttributeSourceImpl(PluralAssociationAttribute attribute) {
this.attribute = attribute;
}
@Override
public PluralAttributeNature getPluralAttributeNature() {
if ( Map.class.isAssignableFrom( attribute.getAttributeType() ) ) {
return PluralAttributeNature.MAP;
}
else if ( List.class.isAssignableFrom( attribute.getAttributeType() ) ) {
return PluralAttributeNature.LIST;
}
else if ( Set.class.isAssignableFrom( attribute.getAttributeType() ) ) {
return PluralAttributeNature.SET;
}
else {
return PluralAttributeNature.BAG;
}
}
@Override
public PluralAttributeKeySource getKeySource() {
return null; //To change body of implemented methods use File | Settings | File Templates.
}
@Override
public PluralAttributeElementSource getElementSource() {
switch ( attribute.getAttributeNature() ) {
case MANY_TO_MANY:
return new ManyToManyPluralAttributeElementSourceImpl( attribute );
case MANY_TO_ANY:
return new ManyToAnyPluralAttributeElementSourceImpl();
case ONE_TO_MANY:
return new OneToManyPluralAttributeElementSourceImpl();
}
return null;
}
@Override
public TableSpecificationSource getCollectionTableSpecificationSource() {
return null; //To change body of implemented methods use File | Settings | File Templates.
}
@Override
public String getExplicitSchemaName() {
return null;
}
@Override
public String getExplicitCatalogName() {
return null;
}
@Override
public String getExplicitCollectionTableName() {
return null; //To change body of implemented methods use File | Settings | File Templates.
}
@Override
public String getCollectionTableComment() {
return null; //To change body of implemented methods use File | Settings | File Templates.
}
@Override
public String getCollectionTableCheck() {
return attribute.getCheckCondition();
}
@Override
public Caching getCaching() {
return null; //To change body of implemented methods use File | Settings | File Templates.
}
@Override
public String getCustomPersisterClassName() {
return null; //To change body of implemented methods use File | Settings | File Templates.
}
@Override
public String getWhere() {
return null; //To change body of implemented methods use File | Settings | File Templates.
}
@Override
public boolean isInverse() {
return false; //To change body of implemented methods use File | Settings | File Templates.
}
@Override
public String getCustomLoaderName() {
return null; //To change body of implemented methods use File | Settings | File Templates.
}
@Override
public CustomSQL getCustomSqlInsert() {
return null; //To change body of implemented methods use File | Settings | File Templates.
}
@Override
public CustomSQL getCustomSqlUpdate() {
return null; //To change body of implemented methods use File | Settings | File Templates.
}
@Override
public CustomSQL getCustomSqlDelete() {
return null; //To change body of implemented methods use File | Settings | File Templates.
}
@Override
public CustomSQL getCustomSqlDeleteAll() {
return null; //To change body of implemented methods use File | Settings | File Templates.
}
@Override
public String getName() {
return null; //To change body of implemented methods use File | Settings | File Templates.
}
@Override
public boolean isSingular() {
return false;
}
@Override
public ExplicitHibernateTypeSource getTypeInformation() {
return null; //To change body of implemented methods use File | Settings | File Templates.
}
@Override
public String getPropertyAccessorName() {
return null; //To change body of implemented methods use File | Settings | File Templates.
}
@Override
public boolean isIncludedInOptimisticLocking() {
return false; //To change body of implemented methods use File | Settings | File Templates.
}
@Override
public Iterable<MetaAttributeSource> metaAttributes() {
return null; //To change body of implemented methods use File | Settings | File Templates.
}
@Override
public FetchMode getFetchMode() {
return null; //To change body of implemented methods use File | Settings | File Templates.
}
@Override
public FetchTiming getFetchTiming() {
return null; //To change body of implemented methods use File | Settings | File Templates.
}
@Override
public FetchStyle getFetchStyle() {
return null; //To change body of implemented methods use File | Settings | File Templates.
}
private class OneToManyPluralAttributeElementSourceImpl implements OneToManyPluralAttributeElementSource {
@Override
public String getReferencedEntityName() {
return null; //To change body of implemented methods use File | Settings | File Templates.
}
@Override
public boolean isNotFoundAnException() {
return false; //To change body of implemented methods use File | Settings | File Templates.
}
@Override
public Iterable<CascadeStyle> getCascadeStyles() {
return null; //To change body of implemented methods use File | Settings | File Templates.
}
@Override
public PluralAttributeElementNature getNature() {
return null; //To change body of implemented methods use File | Settings | File Templates.
}
}
private class ManyToAnyPluralAttributeElementSourceImpl implements ManyToAnyPluralAttributeElementSource {
@Override
public Iterable<CascadeStyle> getCascadeStyles() {
return null; //To change body of implemented methods use File | Settings | File Templates.
}
@Override
public PluralAttributeElementNature getNature() {
return null; //To change body of implemented methods use File | Settings | File Templates.
}
}
}

View File

@ -54,7 +54,7 @@ import org.hibernate.AssertionFailure;
import org.hibernate.EntityMode;
import org.hibernate.HibernateException;
import org.hibernate.cfg.NotYetImplementedException;
import org.hibernate.metamodel.internal.source.annotations.attribute.CollectionAssociationAttribute;
import org.hibernate.metamodel.internal.source.annotations.attribute.PluralAssociationAttribute;
import org.hibernate.metamodel.spi.source.MappingException;
import org.hibernate.metamodel.internal.source.annotations.AnnotationBindingContext;
import org.hibernate.metamodel.internal.source.annotations.HibernateDotNames;
@ -427,7 +427,7 @@ public class ConfiguredClass {
switch ( attributeNature ) {
case BASIC: {
BasicAttribute attribute = BasicAttribute.createSimpleAttribute(
attributeName, attributeType, annotations, accessTypeString, getLocalBindingContext()
attributeName, attributeType, attributeNature, annotations, accessTypeString, getLocalBindingContext()
);
if ( attribute.isId() ) {
idAttributeMap.put( attributeName, attribute );
@ -480,7 +480,7 @@ public class ConfiguredClass {
}
case ONE_TO_MANY:
case MANY_TO_MANY: {
AssociationAttribute attribute = CollectionAssociationAttribute.createPluralAssociationAttribute(
AssociationAttribute attribute = PluralAssociationAttribute.createPluralAssociationAttribute(
attributeName,
attributeType,
attributeNature,

View File

@ -29,17 +29,20 @@ import java.util.HashSet;
import java.util.List;
import java.util.Set;
import org.hibernate.cfg.NotYetImplementedException;
import org.hibernate.internal.jaxb.Origin;
import org.hibernate.metamodel.spi.binding.CustomSQL;
import org.hibernate.metamodel.spi.source.ConstraintSource;
import org.hibernate.metamodel.spi.source.EntitySource;
import org.hibernate.metamodel.spi.source.LocalBindingContext;
import org.hibernate.metamodel.internal.source.annotations.attribute.AssociationAttribute;
import org.hibernate.metamodel.internal.source.annotations.attribute.BasicAttribute;
import org.hibernate.metamodel.internal.source.annotations.attribute.PluralAssociationAttribute;
import org.hibernate.metamodel.internal.source.annotations.attribute.PluralAttributeSourceImpl;
import org.hibernate.metamodel.internal.source.annotations.attribute.SingularAttributeSourceImpl;
import org.hibernate.metamodel.internal.source.annotations.attribute.ToOneAttributeSourceImpl;
import org.hibernate.metamodel.spi.binding.CustomSQL;
import org.hibernate.metamodel.spi.source.AttributeSource;
import org.hibernate.metamodel.spi.source.ConstraintSource;
import org.hibernate.metamodel.spi.source.EntitySource;
import org.hibernate.metamodel.spi.source.JpaCallbackSource;
import org.hibernate.metamodel.spi.source.LocalBindingContext;
import org.hibernate.metamodel.spi.source.MetaAttributeSource;
import org.hibernate.metamodel.spi.source.SecondaryTableSource;
import org.hibernate.metamodel.spi.source.SubclassEntitySource;
@ -187,7 +190,20 @@ public class EntitySourceImpl implements EntitySource {
);
}
for ( AssociationAttribute associationAttribute : entityClass.getAssociationAttributes() ) {
attributeList.add( new ToOneAttributeSourceImpl( associationAttribute ) );
switch ( associationAttribute.getAttributeNature() ) {
case ONE_TO_ONE:
case MANY_TO_ONE: {
attributeList.add( new ToOneAttributeSourceImpl( associationAttribute ) );
break;
}
case MANY_TO_MANY: {
attributeList.add( new PluralAttributeSourceImpl( (PluralAssociationAttribute) associationAttribute ) );
break;
}
default: {
throw new NotYetImplementedException();
}
}
}
return attributeList;
}