METAGEN-94 Initializing members of mapped superclasses lazily in order to correctly take access type declared by subtypes into account
This commit is contained in:
parent
b61dc5cc98
commit
399bc3542f
|
@ -39,7 +39,6 @@ import javax.lang.model.util.ElementFilter;
|
||||||
import javax.lang.model.util.SimpleTypeVisitor6;
|
import javax.lang.model.util.SimpleTypeVisitor6;
|
||||||
import javax.tools.Diagnostic;
|
import javax.tools.Diagnostic;
|
||||||
|
|
||||||
import org.hibernate.jpamodelgen.annotation.AnnotationEmbeddable;
|
|
||||||
import org.hibernate.jpamodelgen.annotation.AnnotationMetaEntity;
|
import org.hibernate.jpamodelgen.annotation.AnnotationMetaEntity;
|
||||||
import org.hibernate.jpamodelgen.model.MetaEntity;
|
import org.hibernate.jpamodelgen.model.MetaEntity;
|
||||||
import org.hibernate.jpamodelgen.util.Constants;
|
import org.hibernate.jpamodelgen.util.Constants;
|
||||||
|
@ -243,14 +242,15 @@ public class JPAMetaModelEntityProcessor extends AbstractProcessor {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
boolean requiresLazyMemberInitialization = false;
|
||||||
AnnotationMetaEntity metaEntity;
|
AnnotationMetaEntity metaEntity;
|
||||||
if ( TypeUtils.containsAnnotation( element, Constants.EMBEDDABLE ) ) {
|
if ( TypeUtils.containsAnnotation( element, Constants.EMBEDDABLE ) ||
|
||||||
metaEntity = new AnnotationEmbeddable( (TypeElement) element, context );
|
TypeUtils.containsAnnotation( element, Constants.MAPPED_SUPERCLASS ) ) {
|
||||||
}
|
requiresLazyMemberInitialization = true;
|
||||||
else {
|
|
||||||
metaEntity = new AnnotationMetaEntity( (TypeElement) element, context );
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
metaEntity = new AnnotationMetaEntity( (TypeElement) element, context, requiresLazyMemberInitialization );
|
||||||
|
|
||||||
if ( alreadyExistingMetaEntity != null ) {
|
if ( alreadyExistingMetaEntity != null ) {
|
||||||
metaEntity.mergeInMembers( alreadyExistingMetaEntity.getMembers() );
|
metaEntity.mergeInMembers( alreadyExistingMetaEntity.getMembers() );
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,68 +0,0 @@
|
||||||
/*
|
|
||||||
* JBoss, Home of Professional Open Source
|
|
||||||
* Copyright 2010, Red Hat Middleware LLC, and individual contributors
|
|
||||||
* by the @authors tag. See the copyright.txt in the distribution for a
|
|
||||||
* full listing of individual contributors.
|
|
||||||
*
|
|
||||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
|
||||||
* you may not use this file except in compliance with the License.
|
|
||||||
* You may obtain a copy of the License at
|
|
||||||
* http://www.apache.org/licenses/LICENSE-2.0
|
|
||||||
* Unless required by applicable law or agreed to in writing, software
|
|
||||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
|
||||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
||||||
* See the License for the specific language governing permissions and
|
|
||||||
* limitations under the License.
|
|
||||||
*/
|
|
||||||
package org.hibernate.jpamodelgen.annotation;
|
|
||||||
|
|
||||||
import java.util.List;
|
|
||||||
import javax.lang.model.element.TypeElement;
|
|
||||||
import javax.tools.Diagnostic;
|
|
||||||
|
|
||||||
import org.hibernate.jpamodelgen.Context;
|
|
||||||
import org.hibernate.jpamodelgen.model.MetaAttribute;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @author Max Andersen
|
|
||||||
* @author Hardy Ferentschik
|
|
||||||
* @author Emmanuel Bernard
|
|
||||||
*/
|
|
||||||
public class AnnotationEmbeddable extends AnnotationMetaEntity {
|
|
||||||
|
|
||||||
// Embeddables needs to be lazily initialized since the access type be determined by the class which is embedding
|
|
||||||
// the entity. This might not be known until annotations are processed.
|
|
||||||
// Also note, that if two different classes with different access types embed this entity the access type of the
|
|
||||||
// embeddable will be the one of the last embedding entity processed. The result is not determined (that's ok
|
|
||||||
// according to the spec)
|
|
||||||
private boolean initialized;
|
|
||||||
|
|
||||||
public AnnotationEmbeddable(TypeElement element, Context context) {
|
|
||||||
super( element, context, true );
|
|
||||||
}
|
|
||||||
|
|
||||||
public List<MetaAttribute> getMembers() {
|
|
||||||
if ( !initialized ) {
|
|
||||||
getContext().logMessage( Diagnostic.Kind.OTHER, "Entity " + getQualifiedName() + " was lazily initialised." );
|
|
||||||
init();
|
|
||||||
initialized = true;
|
|
||||||
}
|
|
||||||
return super.getMembers();
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public String toString() {
|
|
||||||
final StringBuilder sb = new StringBuilder();
|
|
||||||
sb.append( "AnnotationEmbeddable" );
|
|
||||||
sb.append( "{element=" ).append( getElement() );
|
|
||||||
sb.append( ", members=" );
|
|
||||||
if ( initialized ) {
|
|
||||||
sb.append( getMembers() );
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
sb.append( "[un-initalized]" );
|
|
||||||
}
|
|
||||||
sb.append( '}' );
|
|
||||||
return sb.toString();
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -26,6 +26,7 @@ import javax.lang.model.element.Modifier;
|
||||||
import javax.lang.model.element.PackageElement;
|
import javax.lang.model.element.PackageElement;
|
||||||
import javax.lang.model.element.TypeElement;
|
import javax.lang.model.element.TypeElement;
|
||||||
import javax.lang.model.util.ElementFilter;
|
import javax.lang.model.util.ElementFilter;
|
||||||
|
import javax.tools.Diagnostic;
|
||||||
|
|
||||||
import org.hibernate.jpamodelgen.Context;
|
import org.hibernate.jpamodelgen.Context;
|
||||||
import org.hibernate.jpamodelgen.ImportContextImpl;
|
import org.hibernate.jpamodelgen.ImportContextImpl;
|
||||||
|
@ -38,7 +39,7 @@ import org.hibernate.jpamodelgen.util.Constants;
|
||||||
import org.hibernate.jpamodelgen.util.TypeUtils;
|
import org.hibernate.jpamodelgen.util.TypeUtils;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Class used to collect meta information about an annotated entity.
|
* Class used to collect meta information about an annotated type (entity, embeddable or mapped superclass).
|
||||||
*
|
*
|
||||||
* @author Max Andersen
|
* @author Max Andersen
|
||||||
* @author Hardy Ferentschik
|
* @author Hardy Ferentschik
|
||||||
|
@ -49,15 +50,24 @@ public class AnnotationMetaEntity implements MetaEntity {
|
||||||
private final ImportContext importContext;
|
private final ImportContext importContext;
|
||||||
private final TypeElement element;
|
private final TypeElement element;
|
||||||
private final Map<String, MetaAttribute> members;
|
private final Map<String, MetaAttribute> members;
|
||||||
private Context context;
|
private final Context context;
|
||||||
|
|
||||||
private AccessTypeInformation entityAccessTypeInfo;
|
private AccessTypeInformation entityAccessTypeInfo;
|
||||||
|
|
||||||
public AnnotationMetaEntity(TypeElement element, Context context) {
|
/**
|
||||||
this( element, context, false );
|
* Whether the members of this type have already been initialized or not.
|
||||||
}
|
* <p>
|
||||||
|
* Embeddables and mapped super-classes need to be lazily initialized since the access type may be determined by
|
||||||
|
* the class which is embedding or sub-classing the entity or super-class. This might not be known until
|
||||||
|
* annotations are processed.
|
||||||
|
* <p>
|
||||||
|
* Also note, that if two different classes with different access types embed this entity or extend this mapped
|
||||||
|
* super-class, the access type of the embeddable/super-class will be the one of the last embedding/sub-classing
|
||||||
|
* entity processed. The result is not determined (that's ok according to the spec).
|
||||||
|
*/
|
||||||
|
private boolean initialized;
|
||||||
|
|
||||||
protected AnnotationMetaEntity(TypeElement element, Context context, boolean lazilyInitialised) {
|
public AnnotationMetaEntity(TypeElement element, Context context, boolean lazilyInitialised) {
|
||||||
this.element = element;
|
this.element = element;
|
||||||
this.context = context;
|
this.context = context;
|
||||||
this.members = new HashMap<String, MetaAttribute>();
|
this.members = new HashMap<String, MetaAttribute>();
|
||||||
|
@ -89,6 +99,10 @@ public class AnnotationMetaEntity implements MetaEntity {
|
||||||
}
|
}
|
||||||
|
|
||||||
public List<MetaAttribute> getMembers() {
|
public List<MetaAttribute> getMembers() {
|
||||||
|
if ( !initialized ) {
|
||||||
|
init();
|
||||||
|
}
|
||||||
|
|
||||||
return new ArrayList<MetaAttribute>( members.values() );
|
return new ArrayList<MetaAttribute>( members.values() );
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -134,6 +148,8 @@ public class AnnotationMetaEntity implements MetaEntity {
|
||||||
}
|
}
|
||||||
|
|
||||||
protected final void init() {
|
protected final void init() {
|
||||||
|
getContext().logMessage( Diagnostic.Kind.OTHER, "Initializing type " + getQualifiedName() + "." );
|
||||||
|
|
||||||
TypeUtils.determineAccessTypeForHierarchy( element, context );
|
TypeUtils.determineAccessTypeForHierarchy( element, context );
|
||||||
entityAccessTypeInfo = context.getAccessTypeInfo( getQualifiedName() );
|
entityAccessTypeInfo = context.getAccessTypeInfo( getQualifiedName() );
|
||||||
|
|
||||||
|
@ -142,6 +158,8 @@ public class AnnotationMetaEntity implements MetaEntity {
|
||||||
|
|
||||||
List<? extends Element> methodsOfClass = ElementFilter.methodsIn( element.getEnclosedElements() );
|
List<? extends Element> methodsOfClass = ElementFilter.methodsIn( element.getEnclosedElements() );
|
||||||
addPersistentMembers( methodsOfClass, AccessType.PROPERTY );
|
addPersistentMembers( methodsOfClass, AccessType.PROPERTY );
|
||||||
|
|
||||||
|
initialized = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
private void addPersistentMembers(List<? extends Element> membersOfClass, AccessType membersKind) {
|
private void addPersistentMembers(List<? extends Element> membersOfClass, AccessType membersKind) {
|
||||||
|
|
|
@ -268,7 +268,7 @@ public class JpaDescriptorParser {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
XmlMetaEntity metaEntity = new XmlMetaEmbeddable( embeddable, pkg, getXmlMappedType( fqcn ), context );
|
XmlMetaEntity metaEntity = new XmlMetaEntity( embeddable, pkg, getXmlMappedType( fqcn ), context );
|
||||||
if ( context.containsMetaEmbeddable( fqcn ) ) {
|
if ( context.containsMetaEmbeddable( fqcn ) ) {
|
||||||
context.logMessage(
|
context.logMessage(
|
||||||
Diagnostic.Kind.WARNING,
|
Diagnostic.Kind.WARNING,
|
||||||
|
|
|
@ -1,68 +0,0 @@
|
||||||
/*
|
|
||||||
* JBoss, Home of Professional Open Source
|
|
||||||
* Copyright 2010, Red Hat Middleware LLC, and individual contributors
|
|
||||||
* by the @authors tag. See the copyright.txt in the distribution for a
|
|
||||||
* full listing of individual contributors.
|
|
||||||
*
|
|
||||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
|
||||||
* you may not use this file except in compliance with the License.
|
|
||||||
* You may obtain a copy of the License at
|
|
||||||
* http://www.apache.org/licenses/LICENSE-2.0
|
|
||||||
* Unless required by applicable law or agreed to in writing, software
|
|
||||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
|
||||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
||||||
* See the License for the specific language governing permissions and
|
|
||||||
* limitations under the License.
|
|
||||||
*/
|
|
||||||
package org.hibernate.jpamodelgen.xml;
|
|
||||||
|
|
||||||
import java.util.List;
|
|
||||||
import javax.lang.model.element.TypeElement;
|
|
||||||
import javax.tools.Diagnostic;
|
|
||||||
|
|
||||||
import org.hibernate.jpamodelgen.Context;
|
|
||||||
import org.hibernate.jpamodelgen.model.MetaAttribute;
|
|
||||||
import org.hibernate.jpamodelgen.xml.jaxb.Embeddable;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @author Hardy Ferentschik
|
|
||||||
*/
|
|
||||||
public class XmlMetaEmbeddable extends XmlMetaEntity {
|
|
||||||
// Embeddables needs to be lazily initialized since the access type be determined by the class which is embedding
|
|
||||||
// the entity. This might not be known until annotations are processed.
|
|
||||||
// Also note, that if two different classes with different access types embed this entity the access type of the
|
|
||||||
// embeddable will be the one of the last embedding entity processed. The result is not determined (that's ok
|
|
||||||
// according to the spec)
|
|
||||||
private boolean initialized;
|
|
||||||
|
|
||||||
public XmlMetaEmbeddable(Embeddable embeddable, String packageName, TypeElement element, Context context) {
|
|
||||||
super( embeddable, packageName, element, context );
|
|
||||||
}
|
|
||||||
|
|
||||||
public List<MetaAttribute> getMembers() {
|
|
||||||
if ( !initialized ) {
|
|
||||||
context.logMessage( Diagnostic.Kind.OTHER, "Entity " + getQualifiedName() + " was lazily initialised." );
|
|
||||||
init();
|
|
||||||
initialized = true;
|
|
||||||
}
|
|
||||||
return members;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public String toString() {
|
|
||||||
final StringBuilder sb = new StringBuilder();
|
|
||||||
sb.append( "XmlMetaEmbeddable" );
|
|
||||||
sb.append( "{accessTypeInfo=" ).append( accessTypeInfo );
|
|
||||||
sb.append( ", clazzName='" ).append( clazzName ).append( '\'' );
|
|
||||||
sb.append( ", members=" );
|
|
||||||
if ( initialized ) {
|
|
||||||
sb.append( members );
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
sb.append( "[un-initalized]" );
|
|
||||||
}
|
|
||||||
sb.append( ", isMetaComplete=" ).append( isMetaComplete );
|
|
||||||
sb.append( '}' );
|
|
||||||
return sb.toString();
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -55,6 +55,8 @@ import org.hibernate.jpamodelgen.xml.jaxb.OneToMany;
|
||||||
import org.hibernate.jpamodelgen.xml.jaxb.OneToOne;
|
import org.hibernate.jpamodelgen.xml.jaxb.OneToOne;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
* Collects XML-based meta information about an annotated type (entity, embeddable or mapped superclass).
|
||||||
|
*
|
||||||
* @author Hardy Ferentschik
|
* @author Hardy Ferentschik
|
||||||
*/
|
*/
|
||||||
public class XmlMetaEntity implements MetaEntity {
|
public class XmlMetaEntity implements MetaEntity {
|
||||||
|
@ -68,20 +70,33 @@ public class XmlMetaEntity implements MetaEntity {
|
||||||
COLLECTIONS.put( "java.util.Map", "javax.persistence.metamodel.MapAttribute" );
|
COLLECTIONS.put( "java.util.Map", "javax.persistence.metamodel.MapAttribute" );
|
||||||
}
|
}
|
||||||
|
|
||||||
protected final String clazzName;
|
private final String clazzName;
|
||||||
protected final String packageName;
|
private final String packageName;
|
||||||
protected final String defaultPackageName;
|
private final String defaultPackageName;
|
||||||
protected final ImportContext importContext;
|
private final ImportContext importContext;
|
||||||
protected final List<MetaAttribute> members = new ArrayList<MetaAttribute>();
|
private final List<MetaAttribute> members = new ArrayList<MetaAttribute>();
|
||||||
protected final TypeElement element;
|
private final TypeElement element;
|
||||||
protected final Context context;
|
private final Context context;
|
||||||
protected final boolean isMetaComplete;
|
private final boolean isMetaComplete;
|
||||||
|
|
||||||
private Attributes attributes;
|
private Attributes attributes;
|
||||||
private EmbeddableAttributes embeddableAttributes;
|
private EmbeddableAttributes embeddableAttributes;
|
||||||
protected AccessTypeInformation accessTypeInfo;
|
private AccessTypeInformation accessTypeInfo;
|
||||||
|
|
||||||
public XmlMetaEntity(Entity ormEntity, String defaultPackageName, TypeElement element, Context context) {
|
/**
|
||||||
|
* Whether the members of this type have already been initialized or not.
|
||||||
|
* <p>
|
||||||
|
* Embeddables and mapped super-classes need to be lazily initialized since the access type may be determined by
|
||||||
|
* the class which is embedding or sub-classing the entity or super-class. This might not be known until
|
||||||
|
* annotations are processed.
|
||||||
|
* <p>
|
||||||
|
* Also note, that if two different classes with different access types embed this entity or extend this mapped
|
||||||
|
* super-class, the access type of the embeddable/super-class will be the one of the last embedding/sub-classing
|
||||||
|
* entity processed. The result is not determined (that's ok according to the spec).
|
||||||
|
*/
|
||||||
|
private boolean initialized;
|
||||||
|
|
||||||
|
XmlMetaEntity(Entity ormEntity, String defaultPackageName, TypeElement element, Context context) {
|
||||||
this( ormEntity.getClazz(), defaultPackageName, element, context, ormEntity.isMetadataComplete() );
|
this( ormEntity.getClazz(), defaultPackageName, element, context, ormEntity.isMetadataComplete() );
|
||||||
this.attributes = ormEntity.getAttributes();
|
this.attributes = ormEntity.getAttributes();
|
||||||
this.embeddableAttributes = null;
|
this.embeddableAttributes = null;
|
||||||
|
@ -89,7 +104,7 @@ public class XmlMetaEntity implements MetaEntity {
|
||||||
init();
|
init();
|
||||||
}
|
}
|
||||||
|
|
||||||
protected XmlMetaEntity(MappedSuperclass mappedSuperclass, String defaultPackageName, TypeElement element, Context context) {
|
XmlMetaEntity(MappedSuperclass mappedSuperclass, String defaultPackageName, TypeElement element, Context context) {
|
||||||
this(
|
this(
|
||||||
mappedSuperclass.getClazz(),
|
mappedSuperclass.getClazz(),
|
||||||
defaultPackageName,
|
defaultPackageName,
|
||||||
|
@ -99,11 +114,9 @@ public class XmlMetaEntity implements MetaEntity {
|
||||||
);
|
);
|
||||||
this.attributes = mappedSuperclass.getAttributes();
|
this.attributes = mappedSuperclass.getAttributes();
|
||||||
this.embeddableAttributes = null;
|
this.embeddableAttributes = null;
|
||||||
// entities can be directly initialised
|
|
||||||
init();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
protected XmlMetaEntity(Embeddable embeddable, String defaultPackageName, TypeElement element, Context context) {
|
XmlMetaEntity(Embeddable embeddable, String defaultPackageName, TypeElement element, Context context) {
|
||||||
this( embeddable.getClazz(), defaultPackageName, element, context, embeddable.isMetadataComplete() );
|
this( embeddable.getClazz(), defaultPackageName, element, context, embeddable.isMetadataComplete() );
|
||||||
this.attributes = null;
|
this.attributes = null;
|
||||||
this.embeddableAttributes = embeddable.getAttributes();
|
this.embeddableAttributes = embeddable.getAttributes();
|
||||||
|
@ -127,7 +140,9 @@ public class XmlMetaEntity implements MetaEntity {
|
||||||
this.isMetaComplete = initIsMetaComplete( metaComplete );
|
this.isMetaComplete = initIsMetaComplete( metaComplete );
|
||||||
}
|
}
|
||||||
|
|
||||||
protected final void init() {
|
private final void init() {
|
||||||
|
context.logMessage( Diagnostic.Kind.OTHER, "Initializing type " + getQualifiedName() + "." );
|
||||||
|
|
||||||
this.accessTypeInfo = context.getAccessTypeInfo( getQualifiedName() );
|
this.accessTypeInfo = context.getAccessTypeInfo( getQualifiedName() );
|
||||||
if ( attributes != null ) {
|
if ( attributes != null ) {
|
||||||
parseAttributes( attributes );
|
parseAttributes( attributes );
|
||||||
|
@ -135,6 +150,8 @@ public class XmlMetaEntity implements MetaEntity {
|
||||||
else {
|
else {
|
||||||
parseEmbeddableAttributes( embeddableAttributes );
|
parseEmbeddableAttributes( embeddableAttributes );
|
||||||
}
|
}
|
||||||
|
|
||||||
|
initialized = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
public String getSimpleName() {
|
public String getSimpleName() {
|
||||||
|
@ -150,6 +167,10 @@ public class XmlMetaEntity implements MetaEntity {
|
||||||
}
|
}
|
||||||
|
|
||||||
public List<MetaAttribute> getMembers() {
|
public List<MetaAttribute> getMembers() {
|
||||||
|
if ( !initialized ) {
|
||||||
|
init();
|
||||||
|
}
|
||||||
|
|
||||||
return members;
|
return members;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -39,4 +39,4 @@ public class MappedSuperclassWithoutExplicitIdTest extends CompilationTest {
|
||||||
protected String getPackageNameOfCurrentTest() {
|
protected String getPackageNameOfCurrentTest() {
|
||||||
return MappedSuperclassWithoutExplicitIdTest.class.getPackage().getName();
|
return MappedSuperclassWithoutExplicitIdTest.class.getPackage().getName();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue