METAGEN-69
This commit is contained in:
parent
d155b70923
commit
d5110ad8bc
|
@ -0,0 +1,136 @@
|
|||
Hibernate JPA 2 Metamodel Generator Changelog
|
||||
=============================================
|
||||
|
||||
1.2.0.CR1 (25.01.2012)
|
||||
----------------------
|
||||
|
||||
** Bug
|
||||
* [METAGEN-54] - XML-only field access type Set attribute not generated
|
||||
* [METAGEN-55] - XML Only reference to Embeddable not written
|
||||
* [METAGEN-57] - Attributes are not generated for EmbeddedId and collections when the mapping is defined in orm.xml mapping files
|
||||
* [METAGEN-63] - Parameter for additional entity mapping files is ormXmlList but not ormXml
|
||||
* [METAGEN-64] - Normal class in hierarchy breaks metamodel
|
||||
* [METAGEN-65] - Example maven configuration is not working
|
||||
* [METAGEN-66] - XML Based Mapping of Embeddets in Mapped-Superclass is ignored
|
||||
* [METAGEN-67] - @MappedSuperclass without @Id or explicit access type don't inherit the right hierachy access type
|
||||
* [METAGEN-68] - Some documented options are not recognized, namely, ormXml and addGeneratedAnnotation
|
||||
* [METAGEN-69] - When the root class of hierarchy does not declare @Id default access type cannot be resolved
|
||||
* [METAGEN-75] - Maven plugin and JPA XML configuration path problem
|
||||
* [METAGEN-76] - hashCode is treated as a persistent attribute
|
||||
* [METAGEN-77] - Inheritance of metamodel classes
|
||||
|
||||
** Improvement
|
||||
* [METAGEN-50] - Suppress Warnings
|
||||
* [METAGEN-52] - Remove dependency to JPA jar/classes
|
||||
* [METAGEN-62] - SortedSet attributes are not included in metamodel
|
||||
* [METAGEN-73] - Refactoring of the Generated annotation
|
||||
* [METAGEN-78] - Support for Java 7
|
||||
|
||||
** New Feature
|
||||
* [METAGEN-53] - Remove dependency of JPA API classes to simplify setup
|
||||
|
||||
** Task
|
||||
* [METAGEN-79] - The Generated annotation should be added by default
|
||||
|
||||
1.1.1.Final (06.12.2010)
|
||||
------------------------
|
||||
|
||||
** Bug
|
||||
* [METAGEN-48] - Distribution bundle does not contain jar artifact
|
||||
* [METAGEN-49] - JPAMetaModelEntityProcessor.createMetaModelClasses calls remove within foreach loop (causing a ConcurrentModificationException)
|
||||
|
||||
** Improvement
|
||||
* [METAGEN-47] - Improve documentation on IntelliJ's configuration
|
||||
|
||||
1.1.0.Final (03.11.2010)
|
||||
------------------------
|
||||
|
||||
** Bug
|
||||
* [METAGEN-42] - The Hibernate Metamodel Generator project contains an outdated version of persistence_2_0.xsd
|
||||
* [METAGEN-45] - Generated metamodel sources are not compiled in JDK 6
|
||||
|
||||
** Task
|
||||
* [METAGEN-41] - Update pom and readme after move to GitHub
|
||||
|
||||
1.1.0.CR1 (15.10.2010)
|
||||
------------------------
|
||||
|
||||
** Bug
|
||||
* [METAGEN-28] - Custom UserType not supported in Hibernate's static MetaModel generator
|
||||
* [METAGEN-29] - Embedded generic types not supported by metamodel generator
|
||||
* [METAGEN-30] - @Target
|
||||
* [METAGEN-35] - Generated meta model classes does not extend the super class' meta model.
|
||||
* [METAGEN-36] - Attempt to recreate a file for type
|
||||
* [METAGEN-37] - MappedSuperclass with type parameters result in uncompilable metamodels
|
||||
* [METAGEN-38] - Attribute not generated for Blob type fields
|
||||
* [METAGEN-40] - Generator does not work when classes are in the default package
|
||||
* [METAGEN-43] - @Entity extending from @MappedSuperClass from another package does not generate META MODEL properly
|
||||
|
||||
** Task
|
||||
* [METAGEN-7] - Try to find a way to be able to use @SupportedAnnotationTypes("javax.persistence.Entity") in JPAMetaModelEntityProcessor
|
||||
* [METAGEN-31] - Update pom to use the new distributationManagement information
|
||||
* [METAGEN-32] - Update the documentation regarding the usage of the maven-processor-plugin
|
||||
* [METAGEN-33] - Metamodel is not generated with @Generated annotation
|
||||
* [METAGEN-39] - Cleanup the pom
|
||||
|
||||
1.0.0.Final (10.03.2010)
|
||||
------------------------
|
||||
|
||||
** Bug
|
||||
* [METAGEN-27] - Review of documentation
|
||||
|
||||
** Task
|
||||
* [METAGEN-26] - Update readme.txt
|
||||
|
||||
1.0.0-CR-1 (10.03.2010)
|
||||
-----------------------
|
||||
|
||||
** Bug
|
||||
* [METAGEN-17] - Consider XML for targetEntity
|
||||
* [METAGEN-19] - Support @MapKeyClass overriding of the key class
|
||||
* [METAGEN-22] - Handle map-key-class in xml configuration
|
||||
* [METAGEN-23] - Handle @IdClass case
|
||||
* [METAGEN-25] - Ensure that the default package name gets used in all cases where class names can be specified
|
||||
|
||||
** Improvement
|
||||
* [METAGEN-13] - Only re-process xml files if thay have changed
|
||||
|
||||
** Task
|
||||
* [METAGEN-4] - Document how to use the processor in different environments
|
||||
* [METAGEN-9] - Implement mixed configuration (annotation + xml)
|
||||
* [METAGEN-24] - Create a mechanism to check whether xml files have changed
|
||||
|
||||
1.0.0-Beta-3 (27.01.2010)
|
||||
-------------------------
|
||||
|
||||
** Bug
|
||||
* [METAGEN-14] - Compiling HEM tests raises an error level log
|
||||
* [METAGEN-15] - When generics are used (outside of collection), the face value of the generic is used leading to compilation failure of the metaclass
|
||||
* [METAGEN-16] - Code makes use of getAnnotation() instead of getAnnotationMirrors()
|
||||
* [METAGEN-18] - Support @ElementCollection.targetClass + its XML equivalent
|
||||
* [METAGEN-20] - Support collections defined as raw types and targetElement
|
||||
|
||||
** Improvement
|
||||
* [METAGEN-10] - Output to the compiler are meaninglessly verbose
|
||||
|
||||
** Task
|
||||
* [METAGEN-5] - Make the logging output configurable
|
||||
* [METAGEN-6] - Move xml parsing code in JPAMetaModelEntityProcessor into a separate class
|
||||
* [METAGEN-21] - Add @SupportedOptions annotation to annotation processor so that tools can query the processor for supported options
|
||||
|
||||
|
||||
1.1.0-Beta-2 (12.12.2009)
|
||||
-------------------------
|
||||
|
||||
** Task
|
||||
* [METAGEN-11] - Upgrade JPA dependency to hibernate-jpa-2.0-api-1.0.0-CR-1
|
||||
|
||||
1.1.0-Beta-1 (01.12.2009)
|
||||
-------------------------
|
||||
|
||||
** Bug
|
||||
* [METAGEN-2] - Does not handle byte[] at all
|
||||
* [METAGEN-8] - Processor does not handle @ElementCollection on a Map
|
||||
|
||||
** Task
|
||||
* [METAGEN-3] - Refactor project structure
|
|
@ -11,7 +11,7 @@
|
|||
Latest stable version
|
||||
-------------------
|
||||
|
||||
1.1.1.Final, 6.12.2010
|
||||
1.2.0.CR1, 25.01.2012
|
||||
|
||||
|
||||
System Requirements
|
||||
|
|
|
@ -60,6 +60,7 @@
|
|||
<include>pom.xml</include>
|
||||
<include>license.txt</include>
|
||||
<include>readme.txt</include>
|
||||
<include>changelog.txt</include>
|
||||
<include>src/**</include>
|
||||
</includes>
|
||||
</fileSet>
|
||||
|
|
|
@ -1,439 +1,438 @@
|
|||
/*
|
||||
* 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.util;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collections;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import javax.lang.model.element.AnnotationMirror;
|
||||
import javax.lang.model.element.AnnotationValue;
|
||||
import javax.lang.model.element.Element;
|
||||
import javax.lang.model.element.ElementKind;
|
||||
import javax.lang.model.element.ExecutableElement;
|
||||
import javax.lang.model.element.TypeElement;
|
||||
import javax.lang.model.type.DeclaredType;
|
||||
import javax.lang.model.type.ExecutableType;
|
||||
import javax.lang.model.type.TypeKind;
|
||||
import javax.lang.model.type.TypeMirror;
|
||||
import javax.lang.model.type.TypeVariable;
|
||||
import javax.lang.model.util.ElementFilter;
|
||||
import javax.lang.model.util.Elements;
|
||||
import javax.lang.model.util.SimpleTypeVisitor6;
|
||||
import javax.tools.Diagnostic;
|
||||
|
||||
import org.hibernate.jpamodelgen.Context;
|
||||
import org.hibernate.jpamodelgen.MetaModelGenerationException;
|
||||
|
||||
/**
|
||||
* Utility class.
|
||||
*
|
||||
* @author Max Andersen
|
||||
* @author Hardy Ferentschik
|
||||
* @author Emmanuel Bernard
|
||||
*/
|
||||
public final class TypeUtils {
|
||||
|
||||
public static final String DEFAULT_ANNOTATION_PARAMETER_NAME = "value";
|
||||
private static final Map<String, String> PRIMITIVES = new HashMap<String, String>();
|
||||
|
||||
static {
|
||||
PRIMITIVES.put( "char", "Character" );
|
||||
|
||||
PRIMITIVES.put( "byte", "Byte" );
|
||||
PRIMITIVES.put( "short", "Short" );
|
||||
PRIMITIVES.put( "int", "Integer" );
|
||||
PRIMITIVES.put( "long", "Long" );
|
||||
|
||||
PRIMITIVES.put( "boolean", "Boolean" );
|
||||
|
||||
PRIMITIVES.put( "float", "Float" );
|
||||
PRIMITIVES.put( "double", "Double" );
|
||||
}
|
||||
|
||||
private TypeUtils() {
|
||||
}
|
||||
|
||||
public static String toTypeString(TypeMirror type) {
|
||||
if ( type.getKind().isPrimitive() ) {
|
||||
return PRIMITIVES.get( type.toString() );
|
||||
}
|
||||
return type.toString();
|
||||
}
|
||||
|
||||
public static TypeElement getSuperclassTypeElement(TypeElement element) {
|
||||
final TypeMirror superClass = element.getSuperclass();
|
||||
//superclass of Object is of NoType which returns some other kind
|
||||
if ( superClass.getKind() == TypeKind.DECLARED ) {
|
||||
//F..king Ch...t Have those people used their horrible APIs even once?
|
||||
final Element superClassElement = ( (DeclaredType) superClass ).asElement();
|
||||
return (TypeElement) superClassElement;
|
||||
}
|
||||
else {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
public static String extractClosestRealTypeAsString(TypeMirror type, Context context) {
|
||||
if ( type instanceof TypeVariable ) {
|
||||
final TypeMirror compositeUpperBound = ( (TypeVariable) type ).getUpperBound();
|
||||
return extractClosestRealTypeAsString( compositeUpperBound, context );
|
||||
}
|
||||
else {
|
||||
return context.getTypeUtils().erasure( type ).toString();
|
||||
}
|
||||
}
|
||||
|
||||
public static boolean containsAnnotation(Element element, String... annotations) {
|
||||
assert element != null;
|
||||
assert annotations != null;
|
||||
|
||||
List<String> annotationClassNames = new ArrayList<String>();
|
||||
Collections.addAll( annotationClassNames, annotations );
|
||||
|
||||
List<? extends AnnotationMirror> annotationMirrors = element.getAnnotationMirrors();
|
||||
for ( AnnotationMirror mirror : annotationMirrors ) {
|
||||
if ( annotationClassNames.contains( mirror.getAnnotationType().toString() ) ) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns {@code true} if the provided annotation type is of the same type as the provided class, {@code false} otherwise.
|
||||
* This method uses the string class names for comparison. See also
|
||||
* <a href="http://www.retep.org/2009/02/getting-class-values-from-annotations.html">getting-class-values-from-annotations</a>.
|
||||
*
|
||||
* @param annotationMirror The annotation mirror
|
||||
* @param fqcn the fully qualified class name to check against
|
||||
*
|
||||
* @return {@code true} if the provided annotation type is of the same type as the provided class, {@code false} otherwise.
|
||||
*/
|
||||
public static boolean isAnnotationMirrorOfType(AnnotationMirror annotationMirror, String fqcn) {
|
||||
assert annotationMirror != null;
|
||||
assert fqcn != null;
|
||||
String annotationClassName = annotationMirror.getAnnotationType().toString();
|
||||
|
||||
return annotationClassName.equals( fqcn );
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks whether the {@code Element} hosts the annotation with the given fully qualified class name.
|
||||
*
|
||||
* @param element the element to check for the hosted annotation
|
||||
* @param fqcn the fully qualified class name of the annotation to check for
|
||||
*
|
||||
* @return the annotation mirror for the specified annotation class from the {@code Element} or {@code null} in case
|
||||
* the {@code TypeElement} does not host the specified annotation.
|
||||
*/
|
||||
public static AnnotationMirror getAnnotationMirror(Element element, String fqcn) {
|
||||
assert element != null;
|
||||
assert fqcn != null;
|
||||
|
||||
AnnotationMirror mirror = null;
|
||||
for ( AnnotationMirror am : element.getAnnotationMirrors() ) {
|
||||
if ( isAnnotationMirrorOfType( am, fqcn ) ) {
|
||||
mirror = am;
|
||||
break;
|
||||
}
|
||||
}
|
||||
return mirror;
|
||||
}
|
||||
|
||||
public static Object getAnnotationValue(AnnotationMirror annotationMirror, String parameterValue) {
|
||||
assert annotationMirror != null;
|
||||
assert parameterValue != null;
|
||||
|
||||
Object returnValue = null;
|
||||
for ( Map.Entry<? extends ExecutableElement, ? extends AnnotationValue> entry : annotationMirror.getElementValues()
|
||||
.entrySet() ) {
|
||||
if ( parameterValue.equals( entry.getKey().getSimpleName().toString() ) ) {
|
||||
returnValue = entry.getValue().getValue();
|
||||
break;
|
||||
}
|
||||
}
|
||||
return returnValue;
|
||||
}
|
||||
|
||||
public static void determineAccessTypeForHierarchy(TypeElement searchedElement, Context context) {
|
||||
String fqcn = searchedElement.getQualifiedName().toString();
|
||||
context.logMessage( Diagnostic.Kind.OTHER, "Determining access type for " + fqcn );
|
||||
AccessTypeInformation accessTypeInfo = context.getAccessTypeInfo( fqcn );
|
||||
|
||||
if ( accessTypeInfo != null && accessTypeInfo.isAccessTypeResolved() ) {
|
||||
context.logMessage(
|
||||
Diagnostic.Kind.OTHER,
|
||||
"AccessType for " + searchedElement.toString() + " found in cache: " + accessTypeInfo
|
||||
);
|
||||
return;
|
||||
}
|
||||
|
||||
// check for explicit access type
|
||||
AccessType forcedAccessType = determineAnnotationSpecifiedAccessType( searchedElement );
|
||||
if ( forcedAccessType != null ) {
|
||||
context.logMessage(
|
||||
Diagnostic.Kind.OTHER, "Explicit access type on " + searchedElement + ":" + forcedAccessType
|
||||
);
|
||||
accessTypeInfo = new AccessTypeInformation( fqcn, forcedAccessType, null );
|
||||
context.addAccessTypeInformation( fqcn, accessTypeInfo );
|
||||
updateEmbeddableAccessType( searchedElement, context, forcedAccessType );
|
||||
return;
|
||||
}
|
||||
|
||||
// need to find the default access type for this class
|
||||
// let's check first if this entity is the root of the class hierarchy and defines an id. If so the
|
||||
// placement of the id annotation determines the access type
|
||||
AccessType defaultAccessType = getAccessTypeInCaseElementIsRoot( searchedElement, context );
|
||||
if ( defaultAccessType != null ) {
|
||||
accessTypeInfo = new AccessTypeInformation( fqcn, null, defaultAccessType );
|
||||
context.addAccessTypeInformation( fqcn, accessTypeInfo );
|
||||
updateEmbeddableAccessType( searchedElement, context, defaultAccessType );
|
||||
setDefaultAccessTypeForMappedSuperclassesInHierarchy( searchedElement, defaultAccessType, context );
|
||||
return;
|
||||
}
|
||||
|
||||
// if we end up here we need to recursively look for superclasses
|
||||
defaultAccessType = getDefaultAccessForHierarchy( searchedElement, context );
|
||||
if ( defaultAccessType == null ) {
|
||||
defaultAccessType = AccessType.PROPERTY;
|
||||
}
|
||||
accessTypeInfo = new AccessTypeInformation( fqcn, null, defaultAccessType );
|
||||
context.addAccessTypeInformation( fqcn, accessTypeInfo );
|
||||
}
|
||||
|
||||
public static TypeMirror getCollectionElementType(DeclaredType t, String fqNameOfReturnedType, String explicitTargetEntityName, Context context) {
|
||||
TypeMirror collectionElementType;
|
||||
if ( explicitTargetEntityName != null ) {
|
||||
Elements elements = context.getElementUtils();
|
||||
TypeElement element = elements.getTypeElement( explicitTargetEntityName );
|
||||
collectionElementType = element.asType();
|
||||
}
|
||||
else {
|
||||
List<? extends TypeMirror> typeArguments = t.getTypeArguments();
|
||||
if ( typeArguments.size() == 0 ) {
|
||||
throw new MetaModelGenerationException( "Unable to determine collection type" );
|
||||
}
|
||||
else if ( Map.class.getCanonicalName().equals( fqNameOfReturnedType ) ) {
|
||||
collectionElementType = t.getTypeArguments().get( 1 );
|
||||
}
|
||||
else {
|
||||
collectionElementType = t.getTypeArguments().get( 0 );
|
||||
}
|
||||
}
|
||||
return collectionElementType;
|
||||
}
|
||||
|
||||
private static void updateEmbeddableAccessType(TypeElement element, Context context, AccessType defaultAccessType) {
|
||||
List<? extends Element> fieldsOfClass = ElementFilter.fieldsIn( element.getEnclosedElements() );
|
||||
for ( Element field : fieldsOfClass ) {
|
||||
updateEmbeddableAccessTypeForMember( context, defaultAccessType, field );
|
||||
}
|
||||
|
||||
List<? extends Element> methodOfClass = ElementFilter.methodsIn( element.getEnclosedElements() );
|
||||
for ( Element method : methodOfClass ) {
|
||||
updateEmbeddableAccessTypeForMember( context, defaultAccessType, method );
|
||||
}
|
||||
}
|
||||
|
||||
private static void updateEmbeddableAccessTypeForMember(Context context, AccessType defaultAccessType, Element member) {
|
||||
EmbeddedAttributeVisitor visitor = new EmbeddedAttributeVisitor( context );
|
||||
String embeddedClassName = member.asType().accept( visitor, member );
|
||||
if ( embeddedClassName != null ) {
|
||||
AccessTypeInformation accessTypeInfo = context.getAccessTypeInfo( embeddedClassName );
|
||||
if ( accessTypeInfo == null ) {
|
||||
accessTypeInfo = new AccessTypeInformation( embeddedClassName, null, defaultAccessType );
|
||||
context.addAccessTypeInformation( embeddedClassName, accessTypeInfo );
|
||||
}
|
||||
else {
|
||||
accessTypeInfo.setDefaultAccessType( defaultAccessType );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private static AccessType getDefaultAccessForHierarchy(TypeElement element, Context context) {
|
||||
AccessType defaultAccessType = null;
|
||||
TypeElement superClass = element;
|
||||
do {
|
||||
superClass = TypeUtils.getSuperclassTypeElement( superClass );
|
||||
if ( superClass != null ) {
|
||||
String fqcn = superClass.getQualifiedName().toString();
|
||||
AccessTypeInformation accessTypeInfo = context.getAccessTypeInfo( fqcn );
|
||||
if ( accessTypeInfo != null && accessTypeInfo.getDefaultAccessType() != null ) {
|
||||
return accessTypeInfo.getDefaultAccessType();
|
||||
}
|
||||
if ( TypeUtils.containsAnnotation( superClass, Constants.ENTITY, Constants.MAPPED_SUPERCLASS ) ) {
|
||||
defaultAccessType = getAccessTypeInCaseElementIsRoot( superClass, context );
|
||||
if ( defaultAccessType != null ) {
|
||||
accessTypeInfo = new AccessTypeInformation( fqcn, null, defaultAccessType );
|
||||
context.addAccessTypeInformation( fqcn, accessTypeInfo );
|
||||
|
||||
// we found an id within the class hierarchy and determined a default access type
|
||||
// there cannot be any super entity classes (otherwise it would be a configuration error)
|
||||
// but there might be mapped super classes
|
||||
// Also note, that if two different class hierarchies with different access types ave a common
|
||||
// mapped super class, the access type of the mapped super class will be the one of the last
|
||||
// hierarchy processed. The result is not determined which is od with the spec
|
||||
setDefaultAccessTypeForMappedSuperclassesInHierarchy( superClass, defaultAccessType, context );
|
||||
|
||||
// we found a default access type, o need to look further
|
||||
break;
|
||||
}
|
||||
else {
|
||||
defaultAccessType = getDefaultAccessForHierarchy( superClass, context );
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
while ( superClass != null );
|
||||
return defaultAccessType;
|
||||
}
|
||||
|
||||
private static void setDefaultAccessTypeForMappedSuperclassesInHierarchy(TypeElement element, AccessType defaultAccessType, Context context) {
|
||||
TypeElement superClass = element;
|
||||
do {
|
||||
superClass = TypeUtils.getSuperclassTypeElement( superClass );
|
||||
if ( superClass != null ) {
|
||||
String fqcn = superClass.getQualifiedName().toString();
|
||||
if ( TypeUtils.containsAnnotation( superClass, Constants.MAPPED_SUPERCLASS ) ) {
|
||||
AccessTypeInformation accessTypeInfo;
|
||||
AccessType forcedAccessType = determineAnnotationSpecifiedAccessType( superClass );
|
||||
if ( forcedAccessType != null ) {
|
||||
accessTypeInfo = new AccessTypeInformation( fqcn, null, forcedAccessType );
|
||||
}
|
||||
else {
|
||||
accessTypeInfo = new AccessTypeInformation( fqcn, null, defaultAccessType );
|
||||
}
|
||||
context.addAccessTypeInformation( fqcn, accessTypeInfo );
|
||||
}
|
||||
}
|
||||
}
|
||||
while ( superClass != null );
|
||||
}
|
||||
|
||||
/**
|
||||
* Iterates all elements of a type to check whether they contain the id annotation. If so the placement of this
|
||||
* annotation determines the access type
|
||||
*
|
||||
* @param searchedElement the type to be searched
|
||||
* @param context The global execution context
|
||||
*
|
||||
* @return returns the access type of the element annotated with the id annotation. If no element is annotated
|
||||
* {@code null} is returned.
|
||||
*/
|
||||
private static AccessType getAccessTypeInCaseElementIsRoot(TypeElement searchedElement, Context context) {
|
||||
AccessType defaultAccessType = null;
|
||||
List<? extends Element> myMembers = searchedElement.getEnclosedElements();
|
||||
for ( Element subElement : myMembers ) {
|
||||
List<? extends AnnotationMirror> entityAnnotations =
|
||||
context.getElementUtils().getAllAnnotationMirrors( subElement );
|
||||
for ( Object entityAnnotation : entityAnnotations ) {
|
||||
AnnotationMirror annotationMirror = (AnnotationMirror) entityAnnotation;
|
||||
if ( isIdAnnotation( annotationMirror ) ) {
|
||||
defaultAccessType = getAccessTypeOfIdAnnotation( subElement );
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
return defaultAccessType;
|
||||
}
|
||||
|
||||
private static AccessType getAccessTypeOfIdAnnotation(Element element) {
|
||||
AccessType accessType = null;
|
||||
final ElementKind kind = element.getKind();
|
||||
if ( kind == ElementKind.FIELD || kind == ElementKind.METHOD ) {
|
||||
accessType = kind == ElementKind.FIELD ? AccessType.FIELD : AccessType.PROPERTY;
|
||||
}
|
||||
return accessType;
|
||||
}
|
||||
|
||||
private static boolean isIdAnnotation(AnnotationMirror annotationMirror) {
|
||||
return TypeUtils.isAnnotationMirrorOfType( annotationMirror, Constants.ID )
|
||||
|| TypeUtils.isAnnotationMirrorOfType( annotationMirror, Constants.EMBEDDED_ID );
|
||||
}
|
||||
|
||||
public static AccessType determineAnnotationSpecifiedAccessType(Element element) {
|
||||
final AnnotationMirror accessAnnotationMirror = TypeUtils.getAnnotationMirror( element, Constants.ACCESS );
|
||||
AccessType forcedAccessType = null;
|
||||
if ( accessAnnotationMirror != null ) {
|
||||
Element accessElement = (Element) TypeUtils.getAnnotationValue(
|
||||
accessAnnotationMirror,
|
||||
DEFAULT_ANNOTATION_PARAMETER_NAME
|
||||
);
|
||||
if ( accessElement.getKind().equals( ElementKind.ENUM_CONSTANT ) ) {
|
||||
if ( accessElement.getSimpleName().toString().equals( AccessType.PROPERTY.toString() ) ) {
|
||||
forcedAccessType = AccessType.PROPERTY;
|
||||
}
|
||||
else if ( accessElement.getSimpleName().toString().equals( AccessType.FIELD.toString() ) ) {
|
||||
forcedAccessType = AccessType.FIELD;
|
||||
}
|
||||
}
|
||||
}
|
||||
return forcedAccessType;
|
||||
}
|
||||
|
||||
public static ElementKind getElementKindForAccessType(AccessType accessType) {
|
||||
if ( AccessType.FIELD.equals( accessType ) ) {
|
||||
return ElementKind.FIELD;
|
||||
}
|
||||
else {
|
||||
return ElementKind.METHOD;
|
||||
}
|
||||
}
|
||||
|
||||
public static String getKeyType(DeclaredType t, Context context) {
|
||||
List<? extends TypeMirror> typeArguments = t.getTypeArguments();
|
||||
if ( typeArguments.size() == 0 ) {
|
||||
context.logMessage( Diagnostic.Kind.ERROR, "Unable to determine type argument for " + t );
|
||||
}
|
||||
return extractClosestRealTypeAsString( typeArguments.get( 0 ), context );
|
||||
}
|
||||
|
||||
static class EmbeddedAttributeVisitor extends SimpleTypeVisitor6<String, Element> {
|
||||
private Context context;
|
||||
|
||||
EmbeddedAttributeVisitor(Context context) {
|
||||
this.context = context;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String visitDeclared(DeclaredType declaredType, Element element) {
|
||||
TypeElement returnedElement = (TypeElement) context.getTypeUtils().asElement( declaredType );
|
||||
String fqNameOfReturnType = null;
|
||||
if ( containsAnnotation( returnedElement, Constants.EMBEDDABLE ) ) {
|
||||
fqNameOfReturnType = returnedElement.getQualifiedName().toString();
|
||||
}
|
||||
return fqNameOfReturnType;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String visitExecutable(ExecutableType t, Element p) {
|
||||
if ( !p.getKind().equals( ElementKind.METHOD ) ) {
|
||||
return null;
|
||||
}
|
||||
|
||||
String string = p.getSimpleName().toString();
|
||||
if ( !StringUtil.isPropertyName( string ) ) {
|
||||
return null;
|
||||
}
|
||||
|
||||
TypeMirror returnType = t.getReturnType();
|
||||
return returnType.accept( this, p );
|
||||
}
|
||||
}
|
||||
}
|
||||
/*
|
||||
* 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.util;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collections;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import javax.lang.model.element.AnnotationMirror;
|
||||
import javax.lang.model.element.AnnotationValue;
|
||||
import javax.lang.model.element.Element;
|
||||
import javax.lang.model.element.ElementKind;
|
||||
import javax.lang.model.element.ExecutableElement;
|
||||
import javax.lang.model.element.TypeElement;
|
||||
import javax.lang.model.type.DeclaredType;
|
||||
import javax.lang.model.type.ExecutableType;
|
||||
import javax.lang.model.type.TypeKind;
|
||||
import javax.lang.model.type.TypeMirror;
|
||||
import javax.lang.model.type.TypeVariable;
|
||||
import javax.lang.model.util.ElementFilter;
|
||||
import javax.lang.model.util.Elements;
|
||||
import javax.lang.model.util.SimpleTypeVisitor6;
|
||||
import javax.tools.Diagnostic;
|
||||
|
||||
import org.hibernate.jpamodelgen.Context;
|
||||
import org.hibernate.jpamodelgen.MetaModelGenerationException;
|
||||
|
||||
/**
|
||||
* Utility class.
|
||||
*
|
||||
* @author Max Andersen
|
||||
* @author Hardy Ferentschik
|
||||
* @author Emmanuel Bernard
|
||||
*/
|
||||
public final class TypeUtils {
|
||||
|
||||
public static final String DEFAULT_ANNOTATION_PARAMETER_NAME = "value";
|
||||
private static final Map<String, String> PRIMITIVES = new HashMap<String, String>();
|
||||
|
||||
static {
|
||||
PRIMITIVES.put( "char", "Character" );
|
||||
|
||||
PRIMITIVES.put( "byte", "Byte" );
|
||||
PRIMITIVES.put( "short", "Short" );
|
||||
PRIMITIVES.put( "int", "Integer" );
|
||||
PRIMITIVES.put( "long", "Long" );
|
||||
|
||||
PRIMITIVES.put( "boolean", "Boolean" );
|
||||
|
||||
PRIMITIVES.put( "float", "Float" );
|
||||
PRIMITIVES.put( "double", "Double" );
|
||||
}
|
||||
|
||||
private TypeUtils() {
|
||||
}
|
||||
|
||||
public static String toTypeString(TypeMirror type) {
|
||||
if ( type.getKind().isPrimitive() ) {
|
||||
return PRIMITIVES.get( type.toString() );
|
||||
}
|
||||
return type.toString();
|
||||
}
|
||||
|
||||
public static TypeElement getSuperclassTypeElement(TypeElement element) {
|
||||
final TypeMirror superClass = element.getSuperclass();
|
||||
//superclass of Object is of NoType which returns some other kind
|
||||
if ( superClass.getKind() == TypeKind.DECLARED ) {
|
||||
//F..king Ch...t Have those people used their horrible APIs even once?
|
||||
final Element superClassElement = ( (DeclaredType) superClass ).asElement();
|
||||
return (TypeElement) superClassElement;
|
||||
}
|
||||
else {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
public static String extractClosestRealTypeAsString(TypeMirror type, Context context) {
|
||||
if ( type instanceof TypeVariable ) {
|
||||
final TypeMirror compositeUpperBound = ( (TypeVariable) type ).getUpperBound();
|
||||
return extractClosestRealTypeAsString( compositeUpperBound, context );
|
||||
}
|
||||
else {
|
||||
return context.getTypeUtils().erasure( type ).toString();
|
||||
}
|
||||
}
|
||||
|
||||
public static boolean containsAnnotation(Element element, String... annotations) {
|
||||
assert element != null;
|
||||
assert annotations != null;
|
||||
|
||||
List<String> annotationClassNames = new ArrayList<String>();
|
||||
Collections.addAll( annotationClassNames, annotations );
|
||||
|
||||
List<? extends AnnotationMirror> annotationMirrors = element.getAnnotationMirrors();
|
||||
for ( AnnotationMirror mirror : annotationMirrors ) {
|
||||
if ( annotationClassNames.contains( mirror.getAnnotationType().toString() ) ) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns {@code true} if the provided annotation type is of the same type as the provided class, {@code false} otherwise.
|
||||
* This method uses the string class names for comparison. See also
|
||||
* <a href="http://www.retep.org/2009/02/getting-class-values-from-annotations.html">getting-class-values-from-annotations</a>.
|
||||
*
|
||||
* @param annotationMirror The annotation mirror
|
||||
* @param fqcn the fully qualified class name to check against
|
||||
*
|
||||
* @return {@code true} if the provided annotation type is of the same type as the provided class, {@code false} otherwise.
|
||||
*/
|
||||
public static boolean isAnnotationMirrorOfType(AnnotationMirror annotationMirror, String fqcn) {
|
||||
assert annotationMirror != null;
|
||||
assert fqcn != null;
|
||||
String annotationClassName = annotationMirror.getAnnotationType().toString();
|
||||
|
||||
return annotationClassName.equals( fqcn );
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks whether the {@code Element} hosts the annotation with the given fully qualified class name.
|
||||
*
|
||||
* @param element the element to check for the hosted annotation
|
||||
* @param fqcn the fully qualified class name of the annotation to check for
|
||||
*
|
||||
* @return the annotation mirror for the specified annotation class from the {@code Element} or {@code null} in case
|
||||
* the {@code TypeElement} does not host the specified annotation.
|
||||
*/
|
||||
public static AnnotationMirror getAnnotationMirror(Element element, String fqcn) {
|
||||
assert element != null;
|
||||
assert fqcn != null;
|
||||
|
||||
AnnotationMirror mirror = null;
|
||||
for ( AnnotationMirror am : element.getAnnotationMirrors() ) {
|
||||
if ( isAnnotationMirrorOfType( am, fqcn ) ) {
|
||||
mirror = am;
|
||||
break;
|
||||
}
|
||||
}
|
||||
return mirror;
|
||||
}
|
||||
|
||||
public static Object getAnnotationValue(AnnotationMirror annotationMirror, String parameterValue) {
|
||||
assert annotationMirror != null;
|
||||
assert parameterValue != null;
|
||||
|
||||
Object returnValue = null;
|
||||
for ( Map.Entry<? extends ExecutableElement, ? extends AnnotationValue> entry : annotationMirror.getElementValues()
|
||||
.entrySet() ) {
|
||||
if ( parameterValue.equals( entry.getKey().getSimpleName().toString() ) ) {
|
||||
returnValue = entry.getValue().getValue();
|
||||
break;
|
||||
}
|
||||
}
|
||||
return returnValue;
|
||||
}
|
||||
|
||||
public static void determineAccessTypeForHierarchy(TypeElement searchedElement, Context context) {
|
||||
String fqcn = searchedElement.getQualifiedName().toString();
|
||||
context.logMessage( Diagnostic.Kind.OTHER, "Determining access type for " + fqcn );
|
||||
AccessTypeInformation accessTypeInfo = context.getAccessTypeInfo( fqcn );
|
||||
|
||||
if ( accessTypeInfo != null && accessTypeInfo.isAccessTypeResolved() ) {
|
||||
context.logMessage(
|
||||
Diagnostic.Kind.OTHER,
|
||||
"AccessType for " + searchedElement.toString() + " found in cache: " + accessTypeInfo
|
||||
);
|
||||
return;
|
||||
}
|
||||
|
||||
// check for explicit access type
|
||||
AccessType forcedAccessType = determineAnnotationSpecifiedAccessType( searchedElement );
|
||||
if ( forcedAccessType != null ) {
|
||||
context.logMessage(
|
||||
Diagnostic.Kind.OTHER, "Explicit access type on " + searchedElement + ":" + forcedAccessType
|
||||
);
|
||||
accessTypeInfo = new AccessTypeInformation( fqcn, forcedAccessType, null );
|
||||
context.addAccessTypeInformation( fqcn, accessTypeInfo );
|
||||
updateEmbeddableAccessType( searchedElement, context, forcedAccessType );
|
||||
return;
|
||||
}
|
||||
|
||||
// need to find the default access type for this class
|
||||
// let's check first if this entity is the root of the class hierarchy and defines an id. If so the
|
||||
// placement of the id annotation determines the access type
|
||||
AccessType defaultAccessType = getAccessTypeInCaseElementIsRoot( searchedElement, context );
|
||||
if ( defaultAccessType != null ) {
|
||||
accessTypeInfo = new AccessTypeInformation( fqcn, null, defaultAccessType );
|
||||
context.addAccessTypeInformation( fqcn, accessTypeInfo );
|
||||
updateEmbeddableAccessType( searchedElement, context, defaultAccessType );
|
||||
setDefaultAccessTypeForMappedSuperclassesInHierarchy( searchedElement, defaultAccessType, context );
|
||||
return;
|
||||
}
|
||||
|
||||
// if we end up here we need to recursively look for superclasses
|
||||
defaultAccessType = getDefaultAccessForHierarchy( searchedElement, context );
|
||||
if ( defaultAccessType == null ) {
|
||||
defaultAccessType = AccessType.PROPERTY;
|
||||
}
|
||||
accessTypeInfo = new AccessTypeInformation( fqcn, null, defaultAccessType );
|
||||
context.addAccessTypeInformation( fqcn, accessTypeInfo );
|
||||
}
|
||||
|
||||
public static TypeMirror getCollectionElementType(DeclaredType t, String fqNameOfReturnedType, String explicitTargetEntityName, Context context) {
|
||||
TypeMirror collectionElementType;
|
||||
if ( explicitTargetEntityName != null ) {
|
||||
Elements elements = context.getElementUtils();
|
||||
TypeElement element = elements.getTypeElement( explicitTargetEntityName );
|
||||
collectionElementType = element.asType();
|
||||
}
|
||||
else {
|
||||
List<? extends TypeMirror> typeArguments = t.getTypeArguments();
|
||||
if ( typeArguments.size() == 0 ) {
|
||||
throw new MetaModelGenerationException( "Unable to determine collection type" );
|
||||
}
|
||||
else if ( Map.class.getCanonicalName().equals( fqNameOfReturnedType ) ) {
|
||||
collectionElementType = t.getTypeArguments().get( 1 );
|
||||
}
|
||||
else {
|
||||
collectionElementType = t.getTypeArguments().get( 0 );
|
||||
}
|
||||
}
|
||||
return collectionElementType;
|
||||
}
|
||||
|
||||
private static void updateEmbeddableAccessType(TypeElement element, Context context, AccessType defaultAccessType) {
|
||||
List<? extends Element> fieldsOfClass = ElementFilter.fieldsIn( element.getEnclosedElements() );
|
||||
for ( Element field : fieldsOfClass ) {
|
||||
updateEmbeddableAccessTypeForMember( context, defaultAccessType, field );
|
||||
}
|
||||
|
||||
List<? extends Element> methodOfClass = ElementFilter.methodsIn( element.getEnclosedElements() );
|
||||
for ( Element method : methodOfClass ) {
|
||||
updateEmbeddableAccessTypeForMember( context, defaultAccessType, method );
|
||||
}
|
||||
}
|
||||
|
||||
private static void updateEmbeddableAccessTypeForMember(Context context, AccessType defaultAccessType, Element member) {
|
||||
EmbeddedAttributeVisitor visitor = new EmbeddedAttributeVisitor( context );
|
||||
String embeddedClassName = member.asType().accept( visitor, member );
|
||||
if ( embeddedClassName != null ) {
|
||||
AccessTypeInformation accessTypeInfo = context.getAccessTypeInfo( embeddedClassName );
|
||||
if ( accessTypeInfo == null ) {
|
||||
accessTypeInfo = new AccessTypeInformation( embeddedClassName, null, defaultAccessType );
|
||||
context.addAccessTypeInformation( embeddedClassName, accessTypeInfo );
|
||||
}
|
||||
else {
|
||||
accessTypeInfo.setDefaultAccessType( defaultAccessType );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private static AccessType getDefaultAccessForHierarchy(TypeElement element, Context context) {
|
||||
AccessType defaultAccessType = null;
|
||||
TypeElement superClass = element;
|
||||
do {
|
||||
superClass = TypeUtils.getSuperclassTypeElement( superClass );
|
||||
if ( superClass != null ) {
|
||||
String fqcn = superClass.getQualifiedName().toString();
|
||||
AccessTypeInformation accessTypeInfo = context.getAccessTypeInfo( fqcn );
|
||||
if ( accessTypeInfo != null && accessTypeInfo.getDefaultAccessType() != null ) {
|
||||
return accessTypeInfo.getDefaultAccessType();
|
||||
}
|
||||
if ( TypeUtils.containsAnnotation( superClass, Constants.ENTITY, Constants.MAPPED_SUPERCLASS ) ) {
|
||||
defaultAccessType = getAccessTypeInCaseElementIsRoot( superClass, context );
|
||||
if ( defaultAccessType != null ) {
|
||||
accessTypeInfo = new AccessTypeInformation( fqcn, null, defaultAccessType );
|
||||
context.addAccessTypeInformation( fqcn, accessTypeInfo );
|
||||
|
||||
// we found an id within the class hierarchy and determined a default access type
|
||||
// there cannot be any super entity classes (otherwise it would be a configuration error)
|
||||
// but there might be mapped super classes
|
||||
// Also note, that if two different class hierarchies with different access types ave a common
|
||||
// mapped super class, the access type of the mapped super class will be the one of the last
|
||||
// hierarchy processed. The result is not determined which is od with the spec
|
||||
setDefaultAccessTypeForMappedSuperclassesInHierarchy( superClass, defaultAccessType, context );
|
||||
|
||||
// we found a default access type, o need to look further
|
||||
break;
|
||||
}
|
||||
else {
|
||||
defaultAccessType = getDefaultAccessForHierarchy( superClass, context );
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
while ( superClass != null );
|
||||
return defaultAccessType;
|
||||
}
|
||||
|
||||
private static void setDefaultAccessTypeForMappedSuperclassesInHierarchy(TypeElement element, AccessType defaultAccessType, Context context) {
|
||||
TypeElement superClass = element;
|
||||
do {
|
||||
superClass = TypeUtils.getSuperclassTypeElement( superClass );
|
||||
if ( superClass != null ) {
|
||||
String fqcn = superClass.getQualifiedName().toString();
|
||||
if ( TypeUtils.containsAnnotation( superClass, Constants.MAPPED_SUPERCLASS ) ) {
|
||||
AccessTypeInformation accessTypeInfo;
|
||||
AccessType forcedAccessType = determineAnnotationSpecifiedAccessType( superClass );
|
||||
if ( forcedAccessType != null ) {
|
||||
accessTypeInfo = new AccessTypeInformation( fqcn, null, forcedAccessType );
|
||||
}
|
||||
else {
|
||||
accessTypeInfo = new AccessTypeInformation( fqcn, null, defaultAccessType );
|
||||
}
|
||||
context.addAccessTypeInformation( fqcn, accessTypeInfo );
|
||||
}
|
||||
}
|
||||
}
|
||||
while ( superClass != null );
|
||||
}
|
||||
|
||||
/**
|
||||
* Iterates all elements of a type to check whether they contain the id annotation. If so the placement of this
|
||||
* annotation determines the access type
|
||||
*
|
||||
* @param searchedElement the type to be searched
|
||||
* @param context The global execution context
|
||||
*
|
||||
* @return returns the access type of the element annotated with the id annotation. If no element is annotated
|
||||
* {@code null} is returned.
|
||||
*/
|
||||
private static AccessType getAccessTypeInCaseElementIsRoot(TypeElement searchedElement, Context context) {
|
||||
List<? extends Element> myMembers = searchedElement.getEnclosedElements();
|
||||
for ( Element subElement : myMembers ) {
|
||||
List<? extends AnnotationMirror> entityAnnotations =
|
||||
context.getElementUtils().getAllAnnotationMirrors( subElement );
|
||||
for ( Object entityAnnotation : entityAnnotations ) {
|
||||
AnnotationMirror annotationMirror = (AnnotationMirror) entityAnnotation;
|
||||
if ( isIdAnnotation( annotationMirror ) ) {
|
||||
return getAccessTypeOfIdAnnotation( subElement );
|
||||
}
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
private static AccessType getAccessTypeOfIdAnnotation(Element element) {
|
||||
AccessType accessType = null;
|
||||
final ElementKind kind = element.getKind();
|
||||
if ( kind == ElementKind.FIELD || kind == ElementKind.METHOD ) {
|
||||
accessType = kind == ElementKind.FIELD ? AccessType.FIELD : AccessType.PROPERTY;
|
||||
}
|
||||
return accessType;
|
||||
}
|
||||
|
||||
private static boolean isIdAnnotation(AnnotationMirror annotationMirror) {
|
||||
return TypeUtils.isAnnotationMirrorOfType( annotationMirror, Constants.ID )
|
||||
|| TypeUtils.isAnnotationMirrorOfType( annotationMirror, Constants.EMBEDDED_ID );
|
||||
}
|
||||
|
||||
public static AccessType determineAnnotationSpecifiedAccessType(Element element) {
|
||||
final AnnotationMirror accessAnnotationMirror = TypeUtils.getAnnotationMirror( element, Constants.ACCESS );
|
||||
AccessType forcedAccessType = null;
|
||||
if ( accessAnnotationMirror != null ) {
|
||||
Element accessElement = (Element) TypeUtils.getAnnotationValue(
|
||||
accessAnnotationMirror,
|
||||
DEFAULT_ANNOTATION_PARAMETER_NAME
|
||||
);
|
||||
if ( accessElement.getKind().equals( ElementKind.ENUM_CONSTANT ) ) {
|
||||
if ( accessElement.getSimpleName().toString().equals( AccessType.PROPERTY.toString() ) ) {
|
||||
forcedAccessType = AccessType.PROPERTY;
|
||||
}
|
||||
else if ( accessElement.getSimpleName().toString().equals( AccessType.FIELD.toString() ) ) {
|
||||
forcedAccessType = AccessType.FIELD;
|
||||
}
|
||||
}
|
||||
}
|
||||
return forcedAccessType;
|
||||
}
|
||||
|
||||
public static ElementKind getElementKindForAccessType(AccessType accessType) {
|
||||
if ( AccessType.FIELD.equals( accessType ) ) {
|
||||
return ElementKind.FIELD;
|
||||
}
|
||||
else {
|
||||
return ElementKind.METHOD;
|
||||
}
|
||||
}
|
||||
|
||||
public static String getKeyType(DeclaredType t, Context context) {
|
||||
List<? extends TypeMirror> typeArguments = t.getTypeArguments();
|
||||
if ( typeArguments.size() == 0 ) {
|
||||
context.logMessage( Diagnostic.Kind.ERROR, "Unable to determine type argument for " + t );
|
||||
}
|
||||
return extractClosestRealTypeAsString( typeArguments.get( 0 ), context );
|
||||
}
|
||||
|
||||
static class EmbeddedAttributeVisitor extends SimpleTypeVisitor6<String, Element> {
|
||||
private Context context;
|
||||
|
||||
EmbeddedAttributeVisitor(Context context) {
|
||||
this.context = context;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String visitDeclared(DeclaredType declaredType, Element element) {
|
||||
TypeElement returnedElement = (TypeElement) context.getTypeUtils().asElement( declaredType );
|
||||
String fqNameOfReturnType = null;
|
||||
if ( containsAnnotation( returnedElement, Constants.EMBEDDABLE ) ) {
|
||||
fqNameOfReturnType = returnedElement.getQualifiedName().toString();
|
||||
}
|
||||
return fqNameOfReturnType;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String visitExecutable(ExecutableType t, Element p) {
|
||||
if ( !p.getKind().equals( ElementKind.METHOD ) ) {
|
||||
return null;
|
||||
}
|
||||
|
||||
String string = p.getSimpleName().toString();
|
||||
if ( !StringUtil.isPropertyName( string ) ) {
|
||||
return null;
|
||||
}
|
||||
|
||||
TypeMirror returnType = t.getReturnType();
|
||||
return returnType.accept( this, p );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -14,7 +14,7 @@
|
|||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package org.hibernate.jpamodelgen.test.inheritance;
|
||||
package org.hibernate.jpamodelgen.test.inheritance.basic;
|
||||
|
||||
import javax.persistence.GeneratedValue;
|
||||
import javax.persistence.Id;
|
|
@ -14,7 +14,7 @@
|
|||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package org.hibernate.jpamodelgen.test.inheritance;
|
||||
package org.hibernate.jpamodelgen.test.inheritance.basic;
|
||||
|
||||
import javax.persistence.MappedSuperclass;
|
||||
|
|
@ -14,7 +14,7 @@
|
|||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package org.hibernate.jpamodelgen.test.inheritance;
|
||||
package org.hibernate.jpamodelgen.test.inheritance.basic;
|
||||
|
||||
import java.sql.Date;
|
||||
import javax.persistence.MappedSuperclass;
|
|
@ -14,7 +14,7 @@
|
|||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package org.hibernate.jpamodelgen.test.inheritance;
|
||||
package org.hibernate.jpamodelgen.test.inheritance.basic;
|
||||
|
||||
import javax.persistence.Entity;
|
||||
|
|
@ -14,7 +14,7 @@
|
|||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package org.hibernate.jpamodelgen.test.inheritance;
|
||||
package org.hibernate.jpamodelgen.test.inheritance.basic;
|
||||
|
||||
import javax.persistence.Entity;
|
||||
import javax.persistence.Id;
|
|
@ -14,7 +14,7 @@
|
|||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package org.hibernate.jpamodelgen.test.inheritance;
|
||||
package org.hibernate.jpamodelgen.test.inheritance.basic;
|
||||
|
||||
import org.testng.annotations.Test;
|
||||
|
|
@ -14,7 +14,7 @@
|
|||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package org.hibernate.jpamodelgen.test.inheritance;
|
||||
package org.hibernate.jpamodelgen.test.inheritance.basic;
|
||||
|
||||
import javax.persistence.Entity;
|
||||
|
|
@ -14,7 +14,7 @@
|
|||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package org.hibernate.jpamodelgen.test.inheritance;
|
||||
package org.hibernate.jpamodelgen.test.inheritance.basic;
|
||||
|
||||
import javax.persistence.Entity;
|
||||
import javax.persistence.Id;
|
|
@ -0,0 +1,53 @@
|
|||
/*
|
||||
* JBoss, Home of Professional Open Source
|
||||
* Copyright 2012, 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.test.inheritance.deep;
|
||||
|
||||
import org.testng.annotations.Test;
|
||||
|
||||
import org.hibernate.jpamodelgen.test.util.CompilationTest;
|
||||
import org.hibernate.jpamodelgen.test.util.TestForIssue;
|
||||
|
||||
import static org.hibernate.jpamodelgen.test.util.TestUtil.assertAttributeTypeInMetaModelFor;
|
||||
import static org.hibernate.jpamodelgen.test.util.TestUtil.assertMetamodelClassGeneratedFor;
|
||||
import static org.hibernate.jpamodelgen.test.util.TestUtil.assertPresenceOfFieldInMetamodelFor;
|
||||
|
||||
/**
|
||||
* Tests a deep class hierarchy mixed with inheritance and a root class that
|
||||
* does not declare an id
|
||||
*
|
||||
* @author Igor Vaynberg
|
||||
*/
|
||||
public class DeepInheritanceTest extends CompilationTest {
|
||||
@Test
|
||||
@TestForIssue(jiraKey = "METAGEN-69")
|
||||
public void testDeepInheritance() throws Exception {
|
||||
assertMetamodelClassGeneratedFor( Plane.class );
|
||||
assertMetamodelClassGeneratedFor( JetPlane.class );
|
||||
assertPresenceOfFieldInMetamodelFor( JetPlane.class, "jets" );
|
||||
assertAttributeTypeInMetaModelFor(
|
||||
JetPlane.class,
|
||||
"jets",
|
||||
Integer.class,
|
||||
"jets should be defined in JetPlane_"
|
||||
);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected String getPackageNameOfCurrentTest() {
|
||||
return DeepInheritanceTest.class.getPackage().getName();
|
||||
}
|
||||
}
|
|
@ -0,0 +1,34 @@
|
|||
/*
|
||||
* JBoss, Home of Professional Open Source
|
||||
* Copyright 2012, 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.test.inheritance.deep;
|
||||
|
||||
import javax.persistence.Basic;
|
||||
import javax.persistence.DiscriminatorValue;
|
||||
import javax.persistence.Entity;
|
||||
|
||||
/**
|
||||
* A {@link Plane} subclass entity that defines extra attributes
|
||||
*
|
||||
* @author Igor Vaynberg
|
||||
*/
|
||||
@Entity
|
||||
@DiscriminatorValue("JetPlane")
|
||||
public class JetPlane extends Plane {
|
||||
@Basic(optional = false)
|
||||
private Integer jets;
|
||||
|
||||
}
|
|
@ -0,0 +1,36 @@
|
|||
/*
|
||||
* JBoss, Home of Professional Open Source
|
||||
* Copyright 2012, 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.test.inheritance.deep;
|
||||
|
||||
import java.util.Date;
|
||||
import javax.persistence.MappedSuperclass;
|
||||
import javax.persistence.PrePersist;
|
||||
|
||||
/**
|
||||
* A mapped super class that does not define an id attribute.
|
||||
*
|
||||
* @author Igor Vaynberg
|
||||
*/
|
||||
@MappedSuperclass
|
||||
public abstract class PersistenceBase {
|
||||
Date created;
|
||||
|
||||
@PrePersist
|
||||
void prePersist() {
|
||||
created = new Date();
|
||||
}
|
||||
}
|
|
@ -0,0 +1,42 @@
|
|||
/*
|
||||
* JBoss, Home of Professional Open Source
|
||||
* Copyright 2012, 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.test.inheritance.deep;
|
||||
|
||||
import javax.persistence.DiscriminatorColumn;
|
||||
import javax.persistence.DiscriminatorType;
|
||||
import javax.persistence.DiscriminatorValue;
|
||||
import javax.persistence.Entity;
|
||||
import javax.persistence.GeneratedValue;
|
||||
import javax.persistence.Id;
|
||||
import javax.persistence.Inheritance;
|
||||
import javax.persistence.InheritanceType;
|
||||
|
||||
/**
|
||||
* A base entity that defines an id attribute. Default access level should be
|
||||
* resolved from this class instead of continuing to {@link PersistenceBase}.
|
||||
*
|
||||
* @author Igor Vaynberg
|
||||
*/
|
||||
@Entity
|
||||
@Inheritance(strategy = InheritanceType.SINGLE_TABLE)
|
||||
@DiscriminatorColumn(name = "planetype", discriminatorType = DiscriminatorType.STRING)
|
||||
@DiscriminatorValue("Plane")
|
||||
public class Plane extends PersistenceBase {
|
||||
@GeneratedValue
|
||||
@Id
|
||||
private Long id;
|
||||
}
|
|
@ -14,7 +14,7 @@
|
|||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package org.hibernate.jpamodelgen.test.unmappedclassinhierarchy;
|
||||
package org.hibernate.jpamodelgen.test.inheritance.unmappedclassinhierarchy;
|
||||
|
||||
import javax.persistence.Access;
|
||||
import javax.persistence.AccessType;
|
|
@ -14,7 +14,7 @@
|
|||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package org.hibernate.jpamodelgen.test.unmappedclassinhierarchy;
|
||||
package org.hibernate.jpamodelgen.test.inheritance.unmappedclassinhierarchy;
|
||||
|
||||
import java.util.Date;
|
||||
import javax.persistence.Access;
|
|
@ -14,7 +14,7 @@
|
|||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package org.hibernate.jpamodelgen.test.unmappedclassinhierarchy;
|
||||
package org.hibernate.jpamodelgen.test.inheritance.unmappedclassinhierarchy;
|
||||
|
||||
public class NormalExtendsEntity extends BaseEntity {
|
||||
public String doSomething(String s) {
|
|
@ -14,7 +14,7 @@
|
|||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package org.hibernate.jpamodelgen.test.unmappedclassinhierarchy;
|
||||
package org.hibernate.jpamodelgen.test.inheritance.unmappedclassinhierarchy;
|
||||
|
||||
public class NormalExtendsMapped extends MappedBase {
|
||||
public String doSomething(String s) {
|
|
@ -14,7 +14,7 @@
|
|||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package org.hibernate.jpamodelgen.test.unmappedclassinhierarchy;
|
||||
package org.hibernate.jpamodelgen.test.inheritance.unmappedclassinhierarchy;
|
||||
|
||||
import javax.persistence.Access;
|
||||
import javax.persistence.AccessType;
|
|
@ -14,7 +14,7 @@
|
|||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package org.hibernate.jpamodelgen.test.unmappedclassinhierarchy;
|
||||
package org.hibernate.jpamodelgen.test.inheritance.unmappedclassinhierarchy;
|
||||
|
||||
import javax.persistence.Access;
|
||||
import javax.persistence.AccessType;
|
|
@ -14,7 +14,7 @@
|
|||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package org.hibernate.jpamodelgen.test.unmappedclassinhierarchy;
|
||||
package org.hibernate.jpamodelgen.test.inheritance.unmappedclassinhierarchy;
|
||||
|
||||
import org.testng.annotations.Test;
|
||||
|
|
@ -16,7 +16,7 @@
|
|||
*/
|
||||
|
||||
// $Id:$
|
||||
package org.hibernate.jpamodelgen.test.embeddablemappedsuperclass;
|
||||
package org.hibernate.jpamodelgen.test.mappedsuperclass.embeddablemappedsuperclass;
|
||||
|
||||
import javax.persistence.Embeddable;
|
||||
import javax.persistence.MappedSuperclass;
|
|
@ -16,7 +16,7 @@
|
|||
*/
|
||||
|
||||
// $Id: BlobTest.java 20721 2010-09-27 12:40:10Z hardy.ferentschik $
|
||||
package org.hibernate.jpamodelgen.test.embeddablemappedsuperclass;
|
||||
package org.hibernate.jpamodelgen.test.mappedsuperclass.embeddablemappedsuperclass;
|
||||
|
||||
import org.testng.annotations.Test;
|
||||
|
|
@ -14,7 +14,7 @@
|
|||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package org.hibernate.jpamodelgen.test.mappedsuperclasswithoutid;
|
||||
package org.hibernate.jpamodelgen.test.mappedsuperclass.mappedsuperclasswithoutid;
|
||||
|
||||
import javax.persistence.Entity;
|
||||
import javax.persistence.Id;
|
|
@ -14,7 +14,7 @@
|
|||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package org.hibernate.jpamodelgen.test.mappedsuperclasswithoutid;
|
||||
package org.hibernate.jpamodelgen.test.mappedsuperclass.mappedsuperclasswithoutid;
|
||||
|
||||
import org.testng.annotations.Test;
|
||||
|
|
@ -14,7 +14,7 @@
|
|||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package org.hibernate.jpamodelgen.test.mappedsuperclasswithoutid;
|
||||
package org.hibernate.jpamodelgen.test.mappedsuperclass.mappedsuperclasswithoutid;
|
||||
|
||||
import javax.persistence.ManyToOne;
|
||||
import javax.persistence.MappedSuperclass;
|
|
@ -14,7 +14,7 @@
|
|||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package org.hibernate.jpamodelgen.test.mappedsuperclasswithoutid;
|
||||
package org.hibernate.jpamodelgen.test.mappedsuperclass.mappedsuperclasswithoutid;
|
||||
|
||||
import javax.persistence.Entity;
|
||||
import javax.persistence.Id;
|
|
@ -14,7 +14,7 @@
|
|||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package org.hibernate.jpamodelgen.test.typedmappedsuperclass;
|
||||
package org.hibernate.jpamodelgen.test.mappedsuperclass.typedmappedsuperclass;
|
||||
|
||||
import java.util.Set;
|
||||
import javax.persistence.Id;
|
|
@ -14,7 +14,7 @@
|
|||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package org.hibernate.jpamodelgen.test.typedmappedsuperclass;
|
||||
package org.hibernate.jpamodelgen.test.mappedsuperclass.typedmappedsuperclass;
|
||||
|
||||
import javax.persistence.Entity;
|
||||
|
|
@ -14,7 +14,7 @@
|
|||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package org.hibernate.jpamodelgen.test.typedmappedsuperclass;
|
||||
package org.hibernate.jpamodelgen.test.mappedsuperclass.typedmappedsuperclass;
|
||||
|
||||
|
||||
import javax.persistence.MappedSuperclass;
|
|
@ -14,7 +14,7 @@
|
|||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package org.hibernate.jpamodelgen.test.typedmappedsuperclass;
|
||||
package org.hibernate.jpamodelgen.test.mappedsuperclass.typedmappedsuperclass;
|
||||
|
||||
import javax.persistence.Entity;
|
||||
|
|
@ -14,7 +14,7 @@
|
|||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package org.hibernate.jpamodelgen.test.typedmappedsuperclass;
|
||||
package org.hibernate.jpamodelgen.test.mappedsuperclass.typedmappedsuperclass;
|
||||
|
||||
import javax.persistence.MappedSuperclass;
|
||||
|
|
@ -14,7 +14,7 @@
|
|||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package org.hibernate.jpamodelgen.test.typedmappedsuperclass;
|
||||
package org.hibernate.jpamodelgen.test.mappedsuperclass.typedmappedsuperclass;
|
||||
|
||||
import org.testng.annotations.Test;
|
||||
|
|
@ -14,7 +14,7 @@
|
|||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package org.hibernate.jpamodelgen.test.typedmappedsuperclass;
|
||||
package org.hibernate.jpamodelgen.test.mappedsuperclass.typedmappedsuperclass;
|
||||
|
||||
import javax.persistence.Entity;
|
||||
|
Loading…
Reference in New Issue