HHH-16633 allow the "session getter" method to not be a getter
add some Javadoc
This commit is contained in:
parent
99d8bf0832
commit
78843fb2a9
|
@ -8,6 +8,7 @@ package org.hibernate.jpamodelgen.annotation;
|
||||||
|
|
||||||
import org.antlr.v4.runtime.RecognitionException;
|
import org.antlr.v4.runtime.RecognitionException;
|
||||||
import org.antlr.v4.runtime.Recognizer;
|
import org.antlr.v4.runtime.Recognizer;
|
||||||
|
import org.hibernate.jpamodelgen.Context;
|
||||||
import org.hibernate.jpamodelgen.model.MetaAttribute;
|
import org.hibernate.jpamodelgen.model.MetaAttribute;
|
||||||
import org.hibernate.jpamodelgen.model.Metamodel;
|
import org.hibernate.jpamodelgen.model.Metamodel;
|
||||||
import org.hibernate.jpamodelgen.util.Constants;
|
import org.hibernate.jpamodelgen.util.Constants;
|
||||||
|
@ -18,6 +19,7 @@ import org.hibernate.query.sqm.tree.select.SqmSelectStatement;
|
||||||
|
|
||||||
import javax.lang.model.element.AnnotationMirror;
|
import javax.lang.model.element.AnnotationMirror;
|
||||||
import javax.lang.model.element.AnnotationValue;
|
import javax.lang.model.element.AnnotationValue;
|
||||||
|
import javax.lang.model.element.Element;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
|
||||||
import static java.util.Collections.emptySet;
|
import static java.util.Collections.emptySet;
|
||||||
|
@ -94,7 +96,8 @@ public abstract class AnnotationMeta implements Metamodel {
|
||||||
// If we are in the scope of @CheckHQL, semantic errors in the
|
// If we are in the scope of @CheckHQL, semantic errors in the
|
||||||
// query result in compilation errors. Otherwise, they only
|
// query result in compilation errors. Otherwise, they only
|
||||||
// result in warnings, so we don't break working code.
|
// result in warnings, so we don't break working code.
|
||||||
new WarningErrorHandler( mirror, value, hql, reportErrors, checkHql ),
|
new WarningErrorHandler( getContext(), getElement(), mirror, value, hql,
|
||||||
|
reportErrors, checkHql ),
|
||||||
ProcessorSessionFactory.create( getContext().getProcessingEnvironment() )
|
ProcessorSessionFactory.create( getContext().getProcessingEnvironment() )
|
||||||
);
|
);
|
||||||
if ( statement instanceof SqmSelectStatement
|
if ( statement instanceof SqmSelectStatement
|
||||||
|
@ -158,12 +161,29 @@ public abstract class AnnotationMeta implements Metamodel {
|
||||||
|
|
||||||
abstract void putMember(String name, MetaAttribute nameMetaAttribute);
|
abstract void putMember(String name, MetaAttribute nameMetaAttribute);
|
||||||
|
|
||||||
private class WarningErrorHandler extends ErrorHandler {
|
/**
|
||||||
|
* Adjusts the severity of validation errors that occur type-checking
|
||||||
|
* a named HQL query, depending on whether we are within the scope
|
||||||
|
* of a {@link org.hibernate.annotations.processing.CheckHQL} annotation.
|
||||||
|
* <p>
|
||||||
|
* We always type-check; but when there's no {@code CheckHQL} in scope,
|
||||||
|
* we report problems as warnings only. This is necessary, since we don't
|
||||||
|
* yet accept absolutely everything that is legal: we don't know about
|
||||||
|
* XML, we don't handle converters, and we don't handle {@code enum}
|
||||||
|
* types very well.
|
||||||
|
*/
|
||||||
|
private static class WarningErrorHandler extends ErrorHandler {
|
||||||
private final boolean reportErrors;
|
private final boolean reportErrors;
|
||||||
private final boolean checkHql;
|
private final boolean checkHql;
|
||||||
|
|
||||||
public WarningErrorHandler(AnnotationMirror mirror, AnnotationValue value, String hql, boolean reportErrors, boolean checkHql) {
|
private WarningErrorHandler(
|
||||||
super( AnnotationMeta.this.getElement(), mirror, value, hql, AnnotationMeta.this.getContext() );
|
Context context,
|
||||||
|
Element element,
|
||||||
|
AnnotationMirror mirror,
|
||||||
|
AnnotationValue value, String hql,
|
||||||
|
boolean reportErrors,
|
||||||
|
boolean checkHql) {
|
||||||
|
super(context, element, mirror, value, hql);
|
||||||
this.reportErrors = reportErrors;
|
this.reportErrors = reportErrors;
|
||||||
this.checkHql = checkHql;
|
this.checkHql = checkHql;
|
||||||
}
|
}
|
||||||
|
@ -188,7 +208,9 @@ public abstract class AnnotationMeta implements Metamodel {
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void syntaxError(Recognizer<?, ?> recognizer, Object offendingSymbol, int line, int charPositionInLine, String message, RecognitionException e) {
|
public void syntaxError(
|
||||||
|
Recognizer<?, ?> recognizer, Object offendingSymbol, int line, int charPositionInLine,
|
||||||
|
String message, RecognitionException e) {
|
||||||
if (reportErrors) {
|
if (reportErrors) {
|
||||||
super.syntaxError( recognizer, offendingSymbol, line, charPositionInLine, message, e );
|
super.syntaxError( recognizer, offendingSymbol, line, charPositionInLine, message, e );
|
||||||
}
|
}
|
||||||
|
|
|
@ -56,6 +56,10 @@ import static org.hibernate.jpamodelgen.util.TypeUtils.getAnnotationValueRef;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Class used to collect meta information about an annotated type (entity, embeddable or mapped superclass).
|
* Class used to collect meta information about an annotated type (entity, embeddable or mapped superclass).
|
||||||
|
* Also repurposed for any type with "auxiliary" annotations like {@code @NamedQuery}, {@code @FetchProfile},
|
||||||
|
* {@code @Find}, or {@code @HQL}. We do not distinguish these two kinds of thing, since an entity class may
|
||||||
|
* {@code @NamedQuery} or {@code @FetchProfile} annotations. Entities may not, however, have methods annotated
|
||||||
|
* {@code @Find} or {@code @HQL}, since entity classes are usually concrete classes.
|
||||||
*
|
*
|
||||||
* @author Max Andersen
|
* @author Max Andersen
|
||||||
* @author Hardy Ferentschik
|
* @author Hardy Ferentschik
|
||||||
|
@ -74,19 +78,19 @@ public class AnnotationMetaEntity extends AnnotationMeta {
|
||||||
/**
|
/**
|
||||||
* Whether the members of this type have already been initialized or not.
|
* Whether the members of this type have already been initialized or not.
|
||||||
* <p>
|
* <p>
|
||||||
* Embeddables and mapped superclasses need to be lazily initialized since the access type may be determined by
|
* Embeddables and mapped superclasses need to be lazily initialized since the access type may be determined
|
||||||
* the class which is embedding or subclassing the entity or superclass. This might not be known until
|
* by the class which is embedding or subclassing the entity or superclass. This might not be known until
|
||||||
* annotations are processed.
|
* annotations are processed.
|
||||||
* <p>
|
* <p>
|
||||||
* Also note, that if two different classes with different access types embed this entity or extend this mapped
|
* 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/superclass will be the one of the last embedding/subclassing
|
* superclass, the access type of the embeddable/superclass will be the one of the last embedding/subclassing
|
||||||
* entity processed. The result is not determined (that's ok according to the spec).
|
* entity processed. The result is not determined (that's ok according to the spec).
|
||||||
*/
|
*/
|
||||||
private boolean initialized;
|
private boolean initialized;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Another meta entity for the same type which should be merged lazily with this meta entity. Doing the merge
|
* Another meta entity for the same type which should be merged lazily with this meta entity. Doing the merge
|
||||||
* lazily is required for embeddedables and mapped supertypes to only pull in those members matching the access
|
* lazily is required for embeddables and mapped supertypes, to only pull in those members matching the access
|
||||||
* type as configured via the embedding entity or subclass (also see METAGEN-85).
|
* type as configured via the embedding entity or subclass (also see METAGEN-85).
|
||||||
*/
|
*/
|
||||||
private Metamodel entityToMerge;
|
private Metamodel entityToMerge;
|
||||||
|
@ -95,6 +99,10 @@ public class AnnotationMetaEntity extends AnnotationMeta {
|
||||||
* True if this "metamodel class" is actually an instantiable DAO-style repository.
|
* True if this "metamodel class" is actually an instantiable DAO-style repository.
|
||||||
*/
|
*/
|
||||||
private boolean dao = false;
|
private boolean dao = false;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The type of the "session getter" method of a DAO-style repository.
|
||||||
|
*/
|
||||||
private String sessionType = Constants.ENTITY_MANAGER;
|
private String sessionType = Constants.ENTITY_MANAGER;
|
||||||
|
|
||||||
public AnnotationMetaEntity(TypeElement element, Context context) {
|
public AnnotationMetaEntity(TypeElement element, Context context) {
|
||||||
|
@ -235,23 +243,16 @@ public class AnnotationMetaEntity extends AnnotationMeta {
|
||||||
final List<ExecutableElement> methodsOfClass = methodsIn( element.getEnclosedElements() );
|
final List<ExecutableElement> methodsOfClass = methodsIn( element.getEnclosedElements() );
|
||||||
final List<ExecutableElement> gettersAndSettersOfClass = new ArrayList<>();
|
final List<ExecutableElement> gettersAndSettersOfClass = new ArrayList<>();
|
||||||
final List<ExecutableElement> queryMethods = new ArrayList<>();
|
final List<ExecutableElement> queryMethods = new ArrayList<>();
|
||||||
for ( ExecutableElement rawMethodOfClass: methodsOfClass ) {
|
for ( ExecutableElement method: methodsOfClass ) {
|
||||||
if ( isGetterOrSetter( rawMethodOfClass ) ) {
|
if ( isGetterOrSetter( method ) ) {
|
||||||
gettersAndSettersOfClass.add( rawMethodOfClass );
|
gettersAndSettersOfClass.add( method );
|
||||||
}
|
}
|
||||||
else if ( containsAnnotation( rawMethodOfClass, Constants.HQL, Constants.SQL, Constants.FIND ) ) {
|
else if ( containsAnnotation( method, Constants.HQL, Constants.SQL, Constants.FIND ) ) {
|
||||||
queryMethods.add( rawMethodOfClass );
|
queryMethods.add( method );
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if ( !containsAnnotation( element, Constants.ENTITY ) ) {
|
findSessionGetter( methodsOfClass );
|
||||||
for ( ExecutableElement getterOrSetter : gettersAndSettersOfClass ) {
|
|
||||||
if ( isSessionGetter( getterOrSetter ) ) {
|
|
||||||
dao = true;
|
|
||||||
sessionType = addDaoConstructor( getterOrSetter );
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
addPersistentMembers( fieldsOfClass, AccessType.FIELD );
|
addPersistentMembers( fieldsOfClass, AccessType.FIELD );
|
||||||
addPersistentMembers( gettersAndSettersOfClass, AccessType.PROPERTY );
|
addPersistentMembers( gettersAndSettersOfClass, AccessType.PROPERTY );
|
||||||
|
@ -265,6 +266,22 @@ public class AnnotationMetaEntity extends AnnotationMeta {
|
||||||
initialized = true;
|
initialized = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private void findSessionGetter(List<ExecutableElement> methodsOfClass) {
|
||||||
|
if ( !containsAnnotation( element, Constants.ENTITY ) ) {
|
||||||
|
for ( ExecutableElement method : methodsOfClass ) {
|
||||||
|
if ( isSessionGetter( method ) ) {
|
||||||
|
dao = true;
|
||||||
|
sessionType = addDaoConstructor( method );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* If there is a session getter method, we generate an instance
|
||||||
|
* variable backing it, together with a constructor that initializes
|
||||||
|
* it.
|
||||||
|
*/
|
||||||
private String addDaoConstructor(ExecutableElement getterOrSetter) {
|
private String addDaoConstructor(ExecutableElement getterOrSetter) {
|
||||||
String name = getterOrSetter.getSimpleName().toString();
|
String name = getterOrSetter.getSimpleName().toString();
|
||||||
String typeName = element.getSimpleName().toString() + '_';
|
String typeName = element.getSimpleName().toString() + '_';
|
||||||
|
@ -274,16 +291,23 @@ public class AnnotationMetaEntity extends AnnotationMeta {
|
||||||
return sessionType;
|
return sessionType;
|
||||||
}
|
}
|
||||||
|
|
||||||
private static boolean isSessionGetter(ExecutableElement getterOrSetter) {
|
/**
|
||||||
final TypeMirror type = getterOrSetter.getReturnType();
|
* The session getter method doesn't have to be a JavaBeans-style
|
||||||
if ( type.getKind() == TypeKind.DECLARED ) {
|
* getter. It can be any method with no parameters and one of the
|
||||||
final DeclaredType declaredType = (DeclaredType) type;
|
* needed return types.
|
||||||
final Element element = declaredType.asElement();
|
*/
|
||||||
if ( element.getKind() == ElementKind.INTERFACE ) {
|
private static boolean isSessionGetter(ExecutableElement method) {
|
||||||
final Name name = ((TypeElement) element).getQualifiedName();
|
if ( method.getParameters().isEmpty() ) {
|
||||||
return name.contentEquals(Constants.HIB_SESSION)
|
final TypeMirror type = method.getReturnType();
|
||||||
|| name.contentEquals(Constants.HIB_STATELESS_SESSION)
|
if ( type.getKind() == TypeKind.DECLARED ) {
|
||||||
|| name.contentEquals(Constants.ENTITY_MANAGER);
|
final DeclaredType declaredType = (DeclaredType) type;
|
||||||
|
final Element element = declaredType.asElement();
|
||||||
|
if ( element.getKind() == ElementKind.INTERFACE ) {
|
||||||
|
final Name name = ((TypeElement) element).getQualifiedName();
|
||||||
|
return name.contentEquals(Constants.HIB_SESSION)
|
||||||
|
|| name.contentEquals(Constants.HIB_STATELESS_SESSION)
|
||||||
|
|| name.contentEquals(Constants.ENTITY_MANAGER);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return false;
|
return false;
|
||||||
|
@ -684,7 +708,7 @@ public class AnnotationMetaEntity extends AnnotationMeta {
|
||||||
hql,
|
hql,
|
||||||
false, true,
|
false, true,
|
||||||
emptySet(), emptySet(),
|
emptySet(), emptySet(),
|
||||||
new ErrorHandler( method, mirror, value, hql, context ),
|
new ErrorHandler(context, method, mirror, value, hql),
|
||||||
ProcessorSessionFactory.create( context.getProcessingEnvironment() )
|
ProcessorSessionFactory.create( context.getProcessingEnvironment() )
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
|
@ -23,6 +23,9 @@ import java.util.BitSet;
|
||||||
import static org.hibernate.query.hql.internal.StandardHqlTranslator.prettifyAntlrError;
|
import static org.hibernate.query.hql.internal.StandardHqlTranslator.prettifyAntlrError;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
* Responsible for forwarding errors from the HQL typechecker to the Java compiler,
|
||||||
|
* via {@link Context#message}.
|
||||||
|
*
|
||||||
* @author Gavin King
|
* @author Gavin King
|
||||||
*/
|
*/
|
||||||
class ErrorHandler implements Validation.Handler {
|
class ErrorHandler implements Validation.Handler {
|
||||||
|
@ -33,11 +36,11 @@ class ErrorHandler implements Validation.Handler {
|
||||||
private final Context context;
|
private final Context context;
|
||||||
private int errorCount;
|
private int errorCount;
|
||||||
|
|
||||||
public ErrorHandler(Element element, AnnotationMirror mirror, AnnotationValue value, String queryString, Context context) {
|
public ErrorHandler(Context context, Element element, AnnotationMirror mirror, AnnotationValue value, String hql) {
|
||||||
this.element = element;
|
this.element = element;
|
||||||
this.mirror = mirror;
|
this.mirror = mirror;
|
||||||
this.value = value;
|
this.value = value;
|
||||||
this.queryString = queryString;
|
this.queryString = hql;
|
||||||
this.context = context;
|
this.context = context;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue