HHH-6172 Creating class hierarchy - MappedAttribute -> SimpleAttribute -> AssociationAttribute
This commit is contained in:
parent
7a33446f54
commit
49e75c83ce
|
@ -23,18 +23,29 @@
|
|||
*/
|
||||
package org.hibernate.metamodel.source.annotations.entity;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
import org.jboss.jandex.AnnotationInstance;
|
||||
import org.jboss.jandex.DotName;
|
||||
|
||||
/**
|
||||
* @author Hardy Ferentschik
|
||||
*/
|
||||
public class AssociationAttribute {
|
||||
private final MappedAttribute mappedAttribute;
|
||||
public class AssociationAttribute extends SimpleAttribute {
|
||||
private final AssociationType associationType;
|
||||
|
||||
public AssociationAttribute(MappedAttribute mappedAttribute) {
|
||||
this.mappedAttribute = mappedAttribute;
|
||||
public static AssociationAttribute createAssociationAttribute(String name, String type, AssociationType associationType, Map<DotName, List<AnnotationInstance>> annotations) {
|
||||
return new AssociationAttribute( name, type, associationType, annotations );
|
||||
}
|
||||
|
||||
public MappedAttribute getMappedAttribute() {
|
||||
return mappedAttribute;
|
||||
private AssociationAttribute(String name, String type, AssociationType associationType, Map<DotName, List<AnnotationInstance>> annotations) {
|
||||
super( name, type, annotations, false );
|
||||
this.associationType = associationType;
|
||||
}
|
||||
|
||||
public AssociationType getAssociationType() {
|
||||
return associationType;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -0,0 +1,35 @@
|
|||
/*
|
||||
* Hibernate, Relational Persistence for Idiomatic Java
|
||||
*
|
||||
* Copyright (c) 2011, 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.source.annotations.entity;
|
||||
|
||||
/**
|
||||
* @author Hardy Ferentschik
|
||||
*/
|
||||
public enum AssociationType {
|
||||
NO_ASSOCIATION,
|
||||
ONE_TO_ONE,
|
||||
ONE_TO_MANY,
|
||||
MANY_TO_ONE,
|
||||
MANY_TO_MANY
|
||||
}
|
|
@ -104,11 +104,11 @@ public class ConfiguredClass {
|
|||
this.hasOwnTable = definesItsOwnTable();
|
||||
this.primaryTableName = determinePrimaryTableName();
|
||||
|
||||
List<MappedAttribute> properties = collectMappedProperties( resolvedType );
|
||||
List<MappedAttribute> simpleProps = collectAttributes( resolvedType );
|
||||
// make sure the properties are ordered by property name
|
||||
Collections.sort( properties );
|
||||
Collections.sort( simpleProps );
|
||||
Map<String, MappedAttribute> tmpMap = new LinkedHashMap<String, MappedAttribute>();
|
||||
for ( MappedAttribute property : properties ) {
|
||||
for ( MappedAttribute property : simpleProps ) {
|
||||
tmpMap.put( property.getName(), property );
|
||||
}
|
||||
this.mappedAttributes = Collections.unmodifiableMap( tmpMap );
|
||||
|
@ -118,10 +118,6 @@ public class ConfiguredClass {
|
|||
return clazz.getName();
|
||||
}
|
||||
|
||||
public String getSimpleName() {
|
||||
return clazz.getSimpleName();
|
||||
}
|
||||
|
||||
public ClassInfo getClassInfo() {
|
||||
return classInfo;
|
||||
}
|
||||
|
@ -212,9 +208,11 @@ public class ConfiguredClass {
|
|||
}
|
||||
|
||||
/**
|
||||
* @param resolvedTypes the resolved types for the field/properties of this class
|
||||
*
|
||||
* @return A list of the persistent properties of this configured class
|
||||
*/
|
||||
private List<MappedAttribute> collectMappedProperties(ResolvedTypeWithMembers resolvedTypes) {
|
||||
private List<MappedAttribute> collectAttributes(ResolvedTypeWithMembers resolvedTypes) {
|
||||
// create sets of transient field and method names
|
||||
Set<String> transientFieldNames = new HashSet<String>();
|
||||
Set<String> transientMethodNames = new HashSet<String>();
|
||||
|
@ -279,6 +277,7 @@ public class ConfiguredClass {
|
|||
* Creates {@code MappedProperty} instances for the explicitly configured persistent properties
|
||||
*
|
||||
* @param mappedProperties list to which to add the explicitly configured mapped properties
|
||||
* @param resolvedMembers the resolved type parameters for this class
|
||||
*
|
||||
* @return the property names of the explicitly configured class names in a set
|
||||
*/
|
||||
|
@ -380,7 +379,48 @@ public class ConfiguredClass {
|
|||
final Map<DotName, List<AnnotationInstance>> annotations = JandexHelper.getMemberAnnotations(
|
||||
classInfo, member.getName()
|
||||
);
|
||||
return MappedAttribute.createMappedAttribute( name, ( (Class) type ).getName(), annotations );
|
||||
|
||||
MappedAttribute attribute;
|
||||
AssociationType associationType = determineAssociationType( annotations );
|
||||
switch ( associationType ) {
|
||||
case NO_ASSOCIATION: {
|
||||
attribute = SimpleAttribute.createSimpleAttribute( name, ( (Class) type ).getName(), annotations );
|
||||
break;
|
||||
}
|
||||
default: {
|
||||
attribute = AssociationAttribute.createAssociationAttribute(
|
||||
name, ( (Class) type ).getName(), associationType, annotations
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
return attribute;
|
||||
}
|
||||
|
||||
private AssociationType determineAssociationType(Map<DotName, List<AnnotationInstance>> annotations) {
|
||||
AnnotationInstance oneToOne = JandexHelper.getSingleAnnotation( annotations, JPADotNames.ONE_TO_ONE );
|
||||
AnnotationInstance oneToMany = JandexHelper.getSingleAnnotation( annotations, JPADotNames.ONE_TO_MANY );
|
||||
AnnotationInstance manyToOne = JandexHelper.getSingleAnnotation( annotations, JPADotNames.MANY_TO_ONE );
|
||||
AnnotationInstance manyToMany = JandexHelper.getSingleAnnotation( annotations, JPADotNames.MANY_TO_MANY );
|
||||
|
||||
if ( oneToOne == null && oneToMany == null && manyToOne == null && manyToMany == null ) {
|
||||
return AssociationType.NO_ASSOCIATION;
|
||||
}
|
||||
else if ( oneToOne != null && oneToMany == null && manyToOne == null && manyToMany == null ) {
|
||||
return AssociationType.ONE_TO_ONE;
|
||||
}
|
||||
else if ( oneToOne == null && oneToMany != null && manyToOne == null && manyToMany == null ) {
|
||||
return AssociationType.ONE_TO_MANY;
|
||||
}
|
||||
else if ( oneToOne == null && oneToMany == null && manyToOne != null && manyToMany == null ) {
|
||||
return AssociationType.MANY_TO_ONE;
|
||||
}
|
||||
else if ( oneToOne == null && oneToMany == null && manyToOne == null && manyToMany != null ) {
|
||||
return AssociationType.MANY_TO_MANY;
|
||||
}
|
||||
else {
|
||||
throw new AnnotationException( "More than one association type configured for property " + getName() + " of class " + getName() );
|
||||
}
|
||||
}
|
||||
|
||||
private Type findResolvedType(String name, ResolvedMember[] resolvedMembers) {
|
||||
|
|
|
@ -122,7 +122,7 @@ public class EntityBinder {
|
|||
final Map<DotName, List<AnnotationInstance>> typeAnnotations = JandexHelper.getTypeAnnotations(
|
||||
configuredClass.getClassInfo()
|
||||
);
|
||||
MappedAttribute discriminatorAttribute = MappedAttribute.createDiscriminatorAttribute( typeAnnotations );
|
||||
SimpleAttribute discriminatorAttribute = SimpleAttribute.createDiscriminatorAttribute( typeAnnotations );
|
||||
|
||||
bindSingleMappedAttribute( entityBinding, discriminatorAttribute );
|
||||
|
||||
|
@ -305,21 +305,29 @@ public class EntityBinder {
|
|||
|
||||
String idName = JandexHelper.getPropertyName( idAnnotation.target() );
|
||||
MappedAttribute idAttribute = configuredClass.getMappedProperty( idName );
|
||||
if ( !( idAttribute instanceof SimpleAttribute ) ) {
|
||||
throw new AssertionFailure( "Unexpected attribute type for id attribute" );
|
||||
}
|
||||
|
||||
entityBinding.getEntity().getOrCreateSingularAttribute( idName );
|
||||
|
||||
SimpleAttributeBinding attributeBinding = entityBinding.makeSimpleIdAttributeBinding( idName );
|
||||
attributeBinding.initialize( new AttributeBindingStateImpl( idAttribute ) );
|
||||
attributeBinding.initialize( new ColumnRelationalStateImpl( idAttribute, meta ) );
|
||||
attributeBinding.initialize( new AttributeBindingStateImpl( (SimpleAttribute) idAttribute ) );
|
||||
attributeBinding.initialize( new ColumnRelationalStateImpl( (SimpleAttribute) idAttribute, meta ) );
|
||||
}
|
||||
|
||||
private void bindAttributes(EntityBinding entityBinding) {
|
||||
for ( MappedAttribute mappedAttribute : configuredClass.getMappedAttributes() ) {
|
||||
bindSingleMappedAttribute( entityBinding, mappedAttribute );
|
||||
if ( mappedAttribute instanceof AssociationAttribute ) {
|
||||
// todo
|
||||
}
|
||||
else {
|
||||
bindSingleMappedAttribute( entityBinding, (SimpleAttribute) mappedAttribute );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void bindSingleMappedAttribute(EntityBinding entityBinding, MappedAttribute mappedAttribute) {
|
||||
private void bindSingleMappedAttribute(EntityBinding entityBinding, SimpleAttribute mappedAttribute) {
|
||||
if ( mappedAttribute.isId() ) {
|
||||
return;
|
||||
}
|
||||
|
|
|
@ -26,24 +26,16 @@ package org.hibernate.metamodel.source.annotations.entity;
|
|||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import javax.persistence.DiscriminatorType;
|
||||
import javax.persistence.FetchType;
|
||||
|
||||
import org.jboss.jandex.AnnotationInstance;
|
||||
import org.jboss.jandex.AnnotationValue;
|
||||
import org.jboss.jandex.DotName;
|
||||
|
||||
import org.hibernate.AnnotationException;
|
||||
import org.hibernate.AssertionFailure;
|
||||
import org.hibernate.annotations.GenerationTime;
|
||||
import org.hibernate.mapping.PropertyGeneration;
|
||||
import org.hibernate.metamodel.source.annotations.HibernateDotNames;
|
||||
import org.hibernate.metamodel.source.annotations.JPADotNames;
|
||||
import org.hibernate.metamodel.source.annotations.util.JandexHelper;
|
||||
|
||||
/**
|
||||
* Represent a mapped attribute (explicitly or implicitly mapped). Also used for synthetic attributes like a
|
||||
* discriminator column.
|
||||
* Base class for the different types of mapped attributes
|
||||
*
|
||||
* @author Hardy Ferentschik
|
||||
*/
|
||||
|
@ -53,11 +45,6 @@ public class MappedAttribute implements Comparable<MappedAttribute> {
|
|||
*/
|
||||
private final Map<DotName, List<AnnotationInstance>> annotations;
|
||||
|
||||
/**
|
||||
* The property name.
|
||||
*/
|
||||
private final String name;
|
||||
|
||||
/**
|
||||
* The property type as string.
|
||||
*/
|
||||
|
@ -69,117 +56,19 @@ public class MappedAttribute implements Comparable<MappedAttribute> {
|
|||
private final Map<String, String> typeParameters;
|
||||
|
||||
/**
|
||||
* Is this property an id property (or part thereof).
|
||||
* The property name.
|
||||
*/
|
||||
private final boolean isId;
|
||||
private final String name;
|
||||
|
||||
/**
|
||||
* Is this a versioned property (annotated w/ {@code @Version}.
|
||||
*/
|
||||
private final boolean isVersioned;
|
||||
|
||||
/**
|
||||
* Is this property a discriminator property.
|
||||
*/
|
||||
private final boolean isDiscriminator;
|
||||
|
||||
/**
|
||||
* Whether a change of the property's value triggers a version increment of the entity (in case of optimistic
|
||||
* locking).
|
||||
*/
|
||||
private final boolean isOptimisticLockable;
|
||||
|
||||
/**
|
||||
* Is this property lazy loaded (see {@link javax.persistence.Basic}).
|
||||
*/
|
||||
private boolean isLazy = false;
|
||||
|
||||
/**
|
||||
* Is this property optional (see {@link javax.persistence.Basic}).
|
||||
*/
|
||||
private boolean isOptional = true;
|
||||
|
||||
private PropertyGeneration propertyGeneration;
|
||||
private boolean isInsertable = true;
|
||||
private boolean isUpdatable = true;
|
||||
|
||||
/**
|
||||
* Defines the column values (relational values) for this property.
|
||||
*/
|
||||
private final ColumnValues columnValues;
|
||||
|
||||
static MappedAttribute createMappedAttribute(String name, String type, Map<DotName, List<AnnotationInstance>> annotations) {
|
||||
return new MappedAttribute( name, type, annotations, false );
|
||||
}
|
||||
|
||||
static MappedAttribute createDiscriminatorAttribute(Map<DotName, List<AnnotationInstance>> annotations) {
|
||||
AnnotationInstance discriminatorOptionsAnnotation = JandexHelper.getSingleAnnotation(
|
||||
annotations, JPADotNames.DISCRIMINATOR_COLUMN
|
||||
);
|
||||
String name = DiscriminatorColumnValues.DEFAULT_DISCRIMINATOR_COLUMN_NAME;
|
||||
String type = String.class.toString(); // string is the discriminator default
|
||||
if ( discriminatorOptionsAnnotation != null ) {
|
||||
name = discriminatorOptionsAnnotation.value( "name" ).asString();
|
||||
|
||||
DiscriminatorType discriminatorType = Enum.valueOf(
|
||||
DiscriminatorType.class, discriminatorOptionsAnnotation.value( "discriminatorType" ).asEnum()
|
||||
);
|
||||
switch ( discriminatorType ) {
|
||||
case STRING: {
|
||||
type = String.class.toString();
|
||||
break;
|
||||
}
|
||||
case CHAR: {
|
||||
type = Character.class.toString();
|
||||
break;
|
||||
}
|
||||
case INTEGER: {
|
||||
type = Integer.class.toString();
|
||||
break;
|
||||
}
|
||||
default: {
|
||||
throw new AnnotationException( "Unsupported discriminator type: " + discriminatorType );
|
||||
}
|
||||
}
|
||||
}
|
||||
return new MappedAttribute( name, type, annotations, true );
|
||||
}
|
||||
|
||||
private MappedAttribute(String name, String type, Map<DotName, List<AnnotationInstance>> annotations, boolean isDiscriminator) {
|
||||
this.name = name;
|
||||
MappedAttribute(String name, String type, Map<DotName, List<AnnotationInstance>> annotations) {
|
||||
this.annotations = annotations;
|
||||
this.isDiscriminator = isDiscriminator;
|
||||
this.name = name;
|
||||
|
||||
this.typeParameters = new HashMap<String, String>();
|
||||
this.type = determineType( type, typeParameters );
|
||||
|
||||
AnnotationInstance idAnnotation = JandexHelper.getSingleAnnotation( annotations, JPADotNames.ID );
|
||||
isId = idAnnotation != null;
|
||||
|
||||
AnnotationInstance versionAnnotation = JandexHelper.getSingleAnnotation( annotations, JPADotNames.VERSION );
|
||||
isVersioned = versionAnnotation != null;
|
||||
|
||||
if ( isDiscriminator ) {
|
||||
columnValues = new DiscriminatorColumnValues( annotations );
|
||||
}
|
||||
else {
|
||||
AnnotationInstance columnAnnotation = JandexHelper.getSingleAnnotation( annotations, JPADotNames.COLUMN );
|
||||
columnValues = new ColumnValues( columnAnnotation );
|
||||
}
|
||||
|
||||
if ( isId ) {
|
||||
// an id must be unique and cannot be nullable
|
||||
columnValues.setUnique( true );
|
||||
columnValues.setNullable( false );
|
||||
}
|
||||
|
||||
this.isOptimisticLockable = checkOptimisticLockAnnotation();
|
||||
|
||||
checkBasicAnnotation();
|
||||
checkGeneratedAnnotation();
|
||||
}
|
||||
|
||||
public final String getName() {
|
||||
public String getName() {
|
||||
return name;
|
||||
}
|
||||
|
||||
|
@ -187,50 +76,10 @@ public class MappedAttribute implements Comparable<MappedAttribute> {
|
|||
return type;
|
||||
}
|
||||
|
||||
public final ColumnValues getColumnValues() {
|
||||
return columnValues;
|
||||
}
|
||||
|
||||
public Map<String, String> getTypeParameters() {
|
||||
return typeParameters;
|
||||
}
|
||||
|
||||
public boolean isId() {
|
||||
return isId;
|
||||
}
|
||||
|
||||
public boolean isVersioned() {
|
||||
return isVersioned;
|
||||
}
|
||||
|
||||
public boolean isDiscriminator() {
|
||||
return isDiscriminator;
|
||||
}
|
||||
|
||||
public boolean isLazy() {
|
||||
return isLazy;
|
||||
}
|
||||
|
||||
public boolean isOptional() {
|
||||
return isOptional;
|
||||
}
|
||||
|
||||
public boolean isInsertable() {
|
||||
return isInsertable;
|
||||
}
|
||||
|
||||
public boolean isUpdatable() {
|
||||
return isUpdatable;
|
||||
}
|
||||
|
||||
public PropertyGeneration getPropertyGeneration() {
|
||||
return propertyGeneration;
|
||||
}
|
||||
|
||||
public boolean isOptimisticLockable() {
|
||||
return isOptimisticLockable;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the annotation with the specified name or {@code null}
|
||||
*
|
||||
|
@ -252,24 +101,6 @@ public class MappedAttribute implements Comparable<MappedAttribute> {
|
|||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public int compareTo(MappedAttribute mappedProperty) {
|
||||
return name.compareTo( mappedProperty.getName() );
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
final StringBuilder sb = new StringBuilder();
|
||||
sb.append( "MappedAttribute" );
|
||||
sb.append( "{name='" ).append( name ).append( '\'' );
|
||||
sb.append( ", type='" ).append( type ).append( '\'' );
|
||||
sb.append( ", isId=" ).append( isId );
|
||||
sb.append( ", isVersioned=" ).append( isVersioned );
|
||||
sb.append( ", isDiscriminator=" ).append( isDiscriminator );
|
||||
sb.append( '}' );
|
||||
return sb.toString();
|
||||
}
|
||||
|
||||
/**
|
||||
* We need to check whether the is an explicit type specified via {@link org.hibernate.annotations.Type}.
|
||||
*
|
||||
|
@ -299,48 +130,20 @@ public class MappedAttribute implements Comparable<MappedAttribute> {
|
|||
return typeAnnotation.value( "type" ).asString();
|
||||
}
|
||||
|
||||
private boolean checkOptimisticLockAnnotation() {
|
||||
boolean triggersVersionIncrement = true;
|
||||
AnnotationInstance optimisticLockAnnotation = getIfExists( HibernateDotNames.OPTIMISTIC_LOCK );
|
||||
if ( optimisticLockAnnotation != null ) {
|
||||
boolean exclude = optimisticLockAnnotation.value( "excluded" ).asBoolean();
|
||||
triggersVersionIncrement = !exclude;
|
||||
}
|
||||
return triggersVersionIncrement;
|
||||
@Override
|
||||
public int compareTo(MappedAttribute mappedProperty) {
|
||||
return name.compareTo( mappedProperty.getName() );
|
||||
}
|
||||
|
||||
private void checkBasicAnnotation() {
|
||||
AnnotationInstance basicAnnotation = getIfExists( JPADotNames.BASIC );
|
||||
if ( basicAnnotation != null ) {
|
||||
FetchType fetchType = FetchType.LAZY;
|
||||
AnnotationValue fetchValue = basicAnnotation.value( "fetch" );
|
||||
if ( fetchValue != null ) {
|
||||
fetchType = Enum.valueOf( FetchType.class, fetchValue.asEnum() );
|
||||
}
|
||||
this.isLazy = fetchType == FetchType.LAZY;
|
||||
|
||||
AnnotationValue optionalValue = basicAnnotation.value( "optional" );
|
||||
if ( optionalValue != null ) {
|
||||
this.isOptional = optionalValue.asBoolean();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// TODO - there is more todo for updatable and insertable. Checking the @Generated annotation is only one part (HF)
|
||||
private void checkGeneratedAnnotation() {
|
||||
AnnotationInstance generatedAnnotation = getIfExists( HibernateDotNames.GENERATED );
|
||||
if ( generatedAnnotation != null ) {
|
||||
this.isInsertable = false;
|
||||
|
||||
AnnotationValue generationTimeValue = generatedAnnotation.value();
|
||||
if ( generationTimeValue != null ) {
|
||||
GenerationTime genTime = Enum.valueOf( GenerationTime.class, generationTimeValue.asEnum() );
|
||||
if ( GenerationTime.ALWAYS.equals( genTime ) ) {
|
||||
this.isUpdatable = false;
|
||||
this.propertyGeneration = PropertyGeneration.parse( genTime.toString().toLowerCase() );
|
||||
}
|
||||
}
|
||||
}
|
||||
@Override
|
||||
public String toString() {
|
||||
final StringBuilder sb = new StringBuilder();
|
||||
sb.append( "MappedAttribute" );
|
||||
sb.append( "{type='" ).append( type ).append( '\'' );
|
||||
sb.append( ", typeParameters=" ).append( typeParameters );
|
||||
sb.append( ", name='" ).append( name ).append( '\'' );
|
||||
sb.append( '}' );
|
||||
return sb.toString();
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -0,0 +1,261 @@
|
|||
/*
|
||||
* Hibernate, Relational Persistence for Idiomatic Java
|
||||
*
|
||||
* Copyright (c) 2011, 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.source.annotations.entity;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import javax.persistence.DiscriminatorType;
|
||||
import javax.persistence.FetchType;
|
||||
|
||||
import org.jboss.jandex.AnnotationInstance;
|
||||
import org.jboss.jandex.AnnotationValue;
|
||||
import org.jboss.jandex.DotName;
|
||||
|
||||
import org.hibernate.AnnotationException;
|
||||
import org.hibernate.annotations.GenerationTime;
|
||||
import org.hibernate.mapping.PropertyGeneration;
|
||||
import org.hibernate.metamodel.source.annotations.HibernateDotNames;
|
||||
import org.hibernate.metamodel.source.annotations.JPADotNames;
|
||||
import org.hibernate.metamodel.source.annotations.util.JandexHelper;
|
||||
|
||||
/**
|
||||
* Represent a mapped attribute (explicitly or implicitly mapped). Also used for synthetic attributes like a
|
||||
* discriminator column.
|
||||
*
|
||||
* @author Hardy Ferentschik
|
||||
*/
|
||||
public class SimpleAttribute extends MappedAttribute {
|
||||
/**
|
||||
* Is this property an id property (or part thereof).
|
||||
*/
|
||||
private final boolean isId;
|
||||
|
||||
/**
|
||||
* Is this a versioned property (annotated w/ {@code @Version}.
|
||||
*/
|
||||
private final boolean isVersioned;
|
||||
|
||||
/**
|
||||
* Is this property a discriminator property.
|
||||
*/
|
||||
private final boolean isDiscriminator;
|
||||
|
||||
/**
|
||||
* Whether a change of the property's value triggers a version increment of the entity (in case of optimistic
|
||||
* locking).
|
||||
*/
|
||||
private final boolean isOptimisticLockable;
|
||||
|
||||
/**
|
||||
* Is this property lazy loaded (see {@link javax.persistence.Basic}).
|
||||
*/
|
||||
private boolean isLazy = false;
|
||||
|
||||
/**
|
||||
* Is this property optional (see {@link javax.persistence.Basic}).
|
||||
*/
|
||||
private boolean isOptional = true;
|
||||
|
||||
private PropertyGeneration propertyGeneration;
|
||||
private boolean isInsertable = true;
|
||||
private boolean isUpdatable = true;
|
||||
|
||||
/**
|
||||
* Defines the column values (relational values) for this property.
|
||||
*/
|
||||
private final ColumnValues columnValues;
|
||||
|
||||
static SimpleAttribute createSimpleAttribute(String name, String type, Map<DotName, List<AnnotationInstance>> annotations) {
|
||||
return new SimpleAttribute( name, type, annotations, false );
|
||||
}
|
||||
|
||||
static SimpleAttribute createDiscriminatorAttribute(Map<DotName, List<AnnotationInstance>> annotations) {
|
||||
AnnotationInstance discriminatorOptionsAnnotation = JandexHelper.getSingleAnnotation(
|
||||
annotations, JPADotNames.DISCRIMINATOR_COLUMN
|
||||
);
|
||||
String name = DiscriminatorColumnValues.DEFAULT_DISCRIMINATOR_COLUMN_NAME;
|
||||
String type = String.class.toString(); // string is the discriminator default
|
||||
if ( discriminatorOptionsAnnotation != null ) {
|
||||
name = discriminatorOptionsAnnotation.value( "name" ).asString();
|
||||
|
||||
DiscriminatorType discriminatorType = Enum.valueOf(
|
||||
DiscriminatorType.class, discriminatorOptionsAnnotation.value( "discriminatorType" ).asEnum()
|
||||
);
|
||||
switch ( discriminatorType ) {
|
||||
case STRING: {
|
||||
type = String.class.toString();
|
||||
break;
|
||||
}
|
||||
case CHAR: {
|
||||
type = Character.class.toString();
|
||||
break;
|
||||
}
|
||||
case INTEGER: {
|
||||
type = Integer.class.toString();
|
||||
break;
|
||||
}
|
||||
default: {
|
||||
throw new AnnotationException( "Unsupported discriminator type: " + discriminatorType );
|
||||
}
|
||||
}
|
||||
}
|
||||
return new SimpleAttribute( name, type, annotations, true );
|
||||
}
|
||||
|
||||
SimpleAttribute(String name, String type, Map<DotName, List<AnnotationInstance>> annotations, boolean isDiscriminator) {
|
||||
super( name, type, annotations );
|
||||
|
||||
this.isDiscriminator = isDiscriminator;
|
||||
|
||||
|
||||
AnnotationInstance idAnnotation = JandexHelper.getSingleAnnotation( annotations, JPADotNames.ID );
|
||||
isId = idAnnotation != null;
|
||||
|
||||
AnnotationInstance versionAnnotation = JandexHelper.getSingleAnnotation( annotations, JPADotNames.VERSION );
|
||||
isVersioned = versionAnnotation != null;
|
||||
|
||||
if ( isDiscriminator ) {
|
||||
columnValues = new DiscriminatorColumnValues( annotations );
|
||||
}
|
||||
else {
|
||||
AnnotationInstance columnAnnotation = JandexHelper.getSingleAnnotation( annotations, JPADotNames.COLUMN );
|
||||
columnValues = new ColumnValues( columnAnnotation );
|
||||
}
|
||||
|
||||
if ( isId ) {
|
||||
// an id must be unique and cannot be nullable
|
||||
columnValues.setUnique( true );
|
||||
columnValues.setNullable( false );
|
||||
}
|
||||
|
||||
this.isOptimisticLockable = checkOptimisticLockAnnotation();
|
||||
|
||||
checkBasicAnnotation();
|
||||
checkGeneratedAnnotation();
|
||||
}
|
||||
|
||||
|
||||
public final ColumnValues getColumnValues() {
|
||||
return columnValues;
|
||||
}
|
||||
|
||||
public boolean isId() {
|
||||
return isId;
|
||||
}
|
||||
|
||||
public boolean isVersioned() {
|
||||
return isVersioned;
|
||||
}
|
||||
|
||||
public boolean isDiscriminator() {
|
||||
return isDiscriminator;
|
||||
}
|
||||
|
||||
public boolean isLazy() {
|
||||
return isLazy;
|
||||
}
|
||||
|
||||
public boolean isOptional() {
|
||||
return isOptional;
|
||||
}
|
||||
|
||||
public boolean isInsertable() {
|
||||
return isInsertable;
|
||||
}
|
||||
|
||||
public boolean isUpdatable() {
|
||||
return isUpdatable;
|
||||
}
|
||||
|
||||
public PropertyGeneration getPropertyGeneration() {
|
||||
return propertyGeneration;
|
||||
}
|
||||
|
||||
public boolean isOptimisticLockable() {
|
||||
return isOptimisticLockable;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
final StringBuilder sb = new StringBuilder();
|
||||
sb.append( "SimpleAttribute" );
|
||||
sb.append( "{isId=" ).append( isId );
|
||||
sb.append( ", isVersioned=" ).append( isVersioned );
|
||||
sb.append( ", isDiscriminator=" ).append( isDiscriminator );
|
||||
sb.append( ", isOptimisticLockable=" ).append( isOptimisticLockable );
|
||||
sb.append( ", isLazy=" ).append( isLazy );
|
||||
sb.append( ", isOptional=" ).append( isOptional );
|
||||
sb.append( ", propertyGeneration=" ).append( propertyGeneration );
|
||||
sb.append( ", isInsertable=" ).append( isInsertable );
|
||||
sb.append( ", isUpdatable=" ).append( isUpdatable );
|
||||
sb.append( '}' );
|
||||
return sb.toString();
|
||||
}
|
||||
|
||||
private boolean checkOptimisticLockAnnotation() {
|
||||
boolean triggersVersionIncrement = true;
|
||||
AnnotationInstance optimisticLockAnnotation = getIfExists( HibernateDotNames.OPTIMISTIC_LOCK );
|
||||
if ( optimisticLockAnnotation != null ) {
|
||||
boolean exclude = optimisticLockAnnotation.value( "excluded" ).asBoolean();
|
||||
triggersVersionIncrement = !exclude;
|
||||
}
|
||||
return triggersVersionIncrement;
|
||||
}
|
||||
|
||||
private void checkBasicAnnotation() {
|
||||
AnnotationInstance basicAnnotation = getIfExists( JPADotNames.BASIC );
|
||||
if ( basicAnnotation != null ) {
|
||||
FetchType fetchType = FetchType.LAZY;
|
||||
AnnotationValue fetchValue = basicAnnotation.value( "fetch" );
|
||||
if ( fetchValue != null ) {
|
||||
fetchType = Enum.valueOf( FetchType.class, fetchValue.asEnum() );
|
||||
}
|
||||
this.isLazy = fetchType == FetchType.LAZY;
|
||||
|
||||
AnnotationValue optionalValue = basicAnnotation.value( "optional" );
|
||||
if ( optionalValue != null ) {
|
||||
this.isOptional = optionalValue.asBoolean();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// TODO - there is more todo for updatable and insertable. Checking the @Generated annotation is only one part (HF)
|
||||
private void checkGeneratedAnnotation() {
|
||||
AnnotationInstance generatedAnnotation = getIfExists( HibernateDotNames.GENERATED );
|
||||
if ( generatedAnnotation != null ) {
|
||||
this.isInsertable = false;
|
||||
|
||||
AnnotationValue generationTimeValue = generatedAnnotation.value();
|
||||
if ( generationTimeValue != null ) {
|
||||
GenerationTime genTime = Enum.valueOf( GenerationTime.class, generationTimeValue.asEnum() );
|
||||
if ( GenerationTime.ALWAYS.equals( genTime ) ) {
|
||||
this.isUpdatable = false;
|
||||
this.propertyGeneration = PropertyGeneration.parse( genTime.toString().toLowerCase() );
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -28,7 +28,7 @@ import java.util.Map;
|
|||
import org.hibernate.mapping.PropertyGeneration;
|
||||
import org.hibernate.metamodel.binding.state.SimpleAttributeBindingState;
|
||||
import org.hibernate.metamodel.domain.MetaAttribute;
|
||||
import org.hibernate.metamodel.source.annotations.entity.MappedAttribute;
|
||||
import org.hibernate.metamodel.source.annotations.entity.SimpleAttribute;
|
||||
|
||||
/**
|
||||
* Implementation of the attribute binding state via annotation configuration.
|
||||
|
@ -37,9 +37,9 @@ import org.hibernate.metamodel.source.annotations.entity.MappedAttribute;
|
|||
* @todo in the end we can maybe just let MappedAttribute implement SimpleAttributeBindingState. (HF)
|
||||
*/
|
||||
public class AttributeBindingStateImpl implements SimpleAttributeBindingState {
|
||||
private final MappedAttribute mappedAttribute;
|
||||
private final SimpleAttribute mappedAttribute;
|
||||
|
||||
public AttributeBindingStateImpl(MappedAttribute mappedAttribute) {
|
||||
public AttributeBindingStateImpl(SimpleAttribute mappedAttribute) {
|
||||
this.mappedAttribute = mappedAttribute;
|
||||
}
|
||||
|
||||
|
|
|
@ -24,7 +24,7 @@
|
|||
package org.hibernate.metamodel.source.annotations.entity.state.binding;
|
||||
|
||||
import org.hibernate.metamodel.source.annotations.entity.DiscriminatorColumnValues;
|
||||
import org.hibernate.metamodel.source.annotations.entity.MappedAttribute;
|
||||
import org.hibernate.metamodel.source.annotations.entity.SimpleAttribute;
|
||||
|
||||
/**
|
||||
* @author Gail Badner
|
||||
|
@ -36,7 +36,7 @@ public class DiscriminatorBindingStateImpl
|
|||
private final boolean isForced;
|
||||
private final boolean isInserted;
|
||||
|
||||
public DiscriminatorBindingStateImpl(MappedAttribute mappedAttribute) {
|
||||
public DiscriminatorBindingStateImpl(SimpleAttribute mappedAttribute) {
|
||||
super( mappedAttribute );
|
||||
DiscriminatorColumnValues columnValues = DiscriminatorColumnValues.class.cast( mappedAttribute.getColumnValues() );
|
||||
isForced = columnValues.isForced();
|
||||
|
|
|
@ -31,7 +31,7 @@ import org.hibernate.metamodel.source.annotations.entity.AssociationAttribute;
|
|||
*/
|
||||
public class ManyToOneBindingStateImpl extends AttributeBindingStateImpl implements ManyToOneAttributeBindingState {
|
||||
public ManyToOneBindingStateImpl(AssociationAttribute associationAttribute) {
|
||||
super( associationAttribute.getMappedAttribute() );
|
||||
super( associationAttribute );
|
||||
}
|
||||
|
||||
@Override
|
||||
|
|
|
@ -37,7 +37,7 @@ import org.hibernate.metamodel.relational.Size;
|
|||
import org.hibernate.metamodel.relational.state.ColumnRelationalState;
|
||||
import org.hibernate.metamodel.source.annotations.HibernateDotNames;
|
||||
import org.hibernate.metamodel.source.annotations.entity.ColumnValues;
|
||||
import org.hibernate.metamodel.source.annotations.entity.MappedAttribute;
|
||||
import org.hibernate.metamodel.source.annotations.entity.SimpleAttribute;
|
||||
import org.hibernate.metamodel.source.spi.MetadataImplementor;
|
||||
|
||||
/**
|
||||
|
@ -61,7 +61,7 @@ public class ColumnRelationalStateImpl implements ColumnRelationalState {
|
|||
private Set<String> uniqueKeys = new HashSet<String>();
|
||||
|
||||
|
||||
public ColumnRelationalStateImpl(MappedAttribute attribute, MetadataImplementor meta) {
|
||||
public ColumnRelationalStateImpl(SimpleAttribute attribute, MetadataImplementor meta) {
|
||||
ColumnValues columnValues = attribute.getColumnValues();
|
||||
namingStrategy = meta.getOptions().getNamingStrategy();
|
||||
columnName = columnValues.getName().isEmpty() ? attribute.getName() : columnValues.getName();
|
||||
|
@ -151,7 +151,7 @@ public class ColumnRelationalStateImpl implements ColumnRelationalState {
|
|||
return size;
|
||||
}
|
||||
|
||||
private List<AnnotationInstance> getAllColumnTransformerAnnotations(MappedAttribute attribute) {
|
||||
private List<AnnotationInstance> getAllColumnTransformerAnnotations(SimpleAttribute attribute) {
|
||||
List<AnnotationInstance> allColumnTransformerAnnotations = new ArrayList<AnnotationInstance>();
|
||||
|
||||
// not quite sure about the usefulness of @ColumnTransformers (HF)
|
||||
|
@ -194,7 +194,7 @@ public class ColumnRelationalStateImpl implements ColumnRelationalState {
|
|||
return readWrite;
|
||||
}
|
||||
|
||||
private String parseCheckAnnotation(MappedAttribute attribute) {
|
||||
private String parseCheckAnnotation(SimpleAttribute attribute) {
|
||||
String checkCondition = null;
|
||||
AnnotationInstance checkAnnotation = attribute.getIfExists( HibernateDotNames.CHECK );
|
||||
if ( checkAnnotation != null ) {
|
||||
|
@ -203,7 +203,7 @@ public class ColumnRelationalStateImpl implements ColumnRelationalState {
|
|||
return checkCondition;
|
||||
}
|
||||
|
||||
private Set<String> parseIndexAnnotation(MappedAttribute attribute) {
|
||||
private Set<String> parseIndexAnnotation(SimpleAttribute attribute) {
|
||||
Set<String> indexNames = new HashSet<String>();
|
||||
AnnotationInstance indexAnnotation = attribute.getIfExists( HibernateDotNames.INDEX );
|
||||
if ( indexAnnotation != null ) {
|
||||
|
|
|
@ -23,11 +23,10 @@
|
|||
*/
|
||||
package org.hibernate.metamodel.binding;
|
||||
|
||||
import javax.persistence.Entity;
|
||||
import javax.persistence.Id;
|
||||
import javax.persistence.ManyToOne;
|
||||
|
||||
import org.hibernate.annotations.Entity;
|
||||
|
||||
/**
|
||||
* @author Gail Badner
|
||||
*/
|
||||
|
|
Loading…
Reference in New Issue