Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

introduce include/exclude options for HibernateProcessor #8179

Merged
merged 3 commits into from
May 7, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -25,5 +25,5 @@
@Target({PACKAGE, TYPE})
@Retention(CLASS)
@Incubating
public @interface Suppress {
public @interface Exclude {
}
Original file line number Diff line number Diff line change
Expand Up @@ -10,12 +10,12 @@
import jakarta.persistence.Entity;
import jakarta.persistence.Id;
import jakarta.persistence.OneToOne;
import org.hibernate.annotations.processing.Suppress;
import org.hibernate.annotations.processing.Exclude;

/**
* @author Emmanuel Bernard
*/
@Suppress
@Exclude
@Entity
public class ShowDescription {
@Id
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,7 @@

import static java.lang.Boolean.parseBoolean;
import static java.util.Collections.emptyList;
import static org.hibernate.internal.util.collections.ArrayHelper.EMPTY_STRING_ARRAY;

/**
* @author Max Andersen
Expand Down Expand Up @@ -98,6 +99,9 @@ public final class Context {
private boolean usesQuarkusOrm = false;
private boolean usesQuarkusReactive = false;

private String[] includes = {"*"};
private String[] excludes = {};

public Context(ProcessingEnvironment processingEnvironment) {
this.processingEnvironment = processingEnvironment;

Expand Down Expand Up @@ -412,4 +416,36 @@ public void setUsesQuarkusReactive(boolean b) {
public boolean usesQuarkusReactive() {
return usesQuarkusReactive;
}

public void setInclude(String include) {
includes = include.split(",\\s*");
}

public void setExclude(String exclude) {
excludes = exclude.isBlank()
? EMPTY_STRING_ARRAY
: exclude.split(",\\s*");
}

public boolean isIncluded(String typeName) {
for (String include : includes) {
if ( matches(typeName, include) ) {
for (String exclude : excludes) {
if ( matches(typeName, exclude) ) {
return false;
}
}
return true;
}
}
return false;
}

private boolean matches(String name, String pattern) {
return "*".equals(pattern)
|| name.equals( pattern )
|| pattern.endsWith("*") && name.startsWith( pattern.substring(0, pattern.length()-1) )
|| pattern.startsWith("*") && name.endsWith( pattern.substring(1) )
|| pattern.startsWith("*") && pattern.endsWith("*") && name.contains( pattern.substring(1, pattern.length()-1) );
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@
import org.hibernate.processor.annotation.AnnotationMetaEntity;
import org.hibernate.processor.annotation.AnnotationMetaPackage;
import org.hibernate.processor.model.Metamodel;
import org.hibernate.processor.util.Constants;
import org.hibernate.processor.xml.JpaDescriptorParser;

import javax.annotation.processing.AbstractProcessor;
Expand Down Expand Up @@ -138,6 +139,22 @@ public class HibernateProcessor extends AbstractProcessor {
*/
public static final String SUPPRESS_JAKARTA_DATA_METAMODEL = "suppressJakartaDataMetamodel";

/**
* Option to include only certain types, according to a list of patterns.
* The wildcard character is {@code *}, and patterns are comma-separated.
* For example: {@code *.entity.*,*Repository}. The default include is
* simply {@code *}, meaning that all types are included.
*/
public static final String INCLUDE = "include";

/**
* Option to exclude certain types, according to a list of patterns.
* The wildcard character is {@code *}, and patterns are comma-separated.
* For example: {@code *.framework.*,*$$}. The default exclude is
* empty.
*/
public static final String EXCLUDE = "exclude";

private static final boolean ALLOW_OTHER_PROCESSORS_TO_CLAIM_ANNOTATIONS = false;

private Context context;
Expand Down Expand Up @@ -228,6 +245,9 @@ private boolean handleSettings(ProcessingEnvironment environment) {
}
}

context.setInclude( options.getOrDefault( INCLUDE, "*" ) );
context.setExclude( options.getOrDefault( EXCLUDE, "" ) );

return parseBoolean( options.get( FULLY_ANNOTATION_CONFIGURED_OPTION ) );
}

Expand Down Expand Up @@ -276,6 +296,16 @@ else if ( context.isFullyXmlConfigured() ) {
return ALLOW_OTHER_PROCESSORS_TO_CLAIM_ANNOTATIONS;
}

private boolean included(Element element) {
if ( element instanceof TypeElement) {
final TypeElement typeElement = (TypeElement) element;
return context.isIncluded( typeElement.getQualifiedName().toString() );
}
else {
return false;
}
}

private void processClasses(RoundEnvironment roundEnvironment) {
for ( CharSequence elementName : new HashSet<>( context.getElementsToRedo() ) ) {
context.logMessage( Diagnostic.Kind.OTHER, "Redoing element '" + elementName + "'" );
Expand All @@ -293,8 +323,9 @@ private void processClasses(RoundEnvironment roundEnvironment) {

for ( Element element : roundEnvironment.getRootElements() ) {
try {
if ( hasAnnotation( element, SUPPRESS)
|| hasAnnotation( context.getElementUtils().getPackageOf(element), SUPPRESS ) ) {
if ( !included( element )
|| hasAnnotation( element, Constants.EXCLUDE )
|| hasAnnotation( context.getElementUtils().getPackageOf(element), Constants.EXCLUDE ) ) {
// skip it completely
}
else if ( isEntityOrEmbeddable( element ) ) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -62,7 +62,7 @@ public final class Constants {
public static final String SQL = "org.hibernate.annotations.processing.SQL";
public static final String FIND = "org.hibernate.annotations.processing.Find";
public static final String PATTERN = "org.hibernate.annotations.processing.Pattern";
public static final String SUPPRESS = "org.hibernate.annotations.processing.Suppress";
public static final String EXCLUDE = "org.hibernate.annotations.processing.Exclude";

public static final String JD_REPOSITORY = "jakarta.data.repository.Repository";
public static final String JD_QUERY = "jakarta.data.repository.Query";
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
package org.hibernate.processor.test.includeexclude;

import jakarta.persistence.Entity;
import jakarta.persistence.Id;

@Entity
public class Bar {
@Id long id;
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
package org.hibernate.processor.test.includeexclude;

import jakarta.persistence.Entity;
import jakarta.persistence.Id;
import org.hibernate.annotations.processing.Exclude;

@Exclude
@Entity
public class Baz {
@Id long id;
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
package org.hibernate.processor.test.includeexclude;

import jakarta.persistence.Entity;
import jakarta.persistence.Id;

@Entity
public class Foo {
@Id long id;
}

Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
package org.hibernate.processor.test.includeexclude;

import org.hibernate.processor.HibernateProcessor;
import org.hibernate.processor.test.util.CompilationTest;
import org.hibernate.processor.test.util.WithClasses;
import org.hibernate.processor.test.util.WithProcessorOption;
import org.junit.Test;

import static org.hibernate.processor.test.util.TestUtil.assertMetamodelClassGeneratedFor;
import static org.hibernate.processor.test.util.TestUtil.assertNoMetamodelClassGeneratedFor;

public class IncludeExcludeTest extends CompilationTest {
@Test
@WithClasses({ Foo.class, Bar.class, Baz.class })
@WithProcessorOption(key = HibernateProcessor.INCLUDE, value = "org.hibernate.processor.test.includeexclude.*")
@WithProcessorOption(key = HibernateProcessor.EXCLUDE, value = "org.hibernate.processor.test.includeexclude.F*")
public void testQueryMethod() {
assertNoMetamodelClassGeneratedFor( Foo.class );
assertMetamodelClassGeneratedFor( Bar.class );
assertNoMetamodelClassGeneratedFor( Baz.class );
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -7,29 +7,26 @@
package org.hibernate.processor.test.util;

import java.lang.annotation.Documented;
import java.lang.annotation.ElementType;
import java.lang.annotation.Repeatable;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;

import static java.lang.annotation.ElementType.ANNOTATION_TYPE;
import static java.lang.annotation.ElementType.CONSTRUCTOR;
import static java.lang.annotation.ElementType.FIELD;
import static java.lang.annotation.ElementType.METHOD;
import static java.lang.annotation.ElementType.PARAMETER;
import static java.lang.annotation.ElementType.TYPE;
import static java.lang.annotation.RetentionPolicy.RUNTIME;

/**
* @author Hardy Ferentschik
*/
@Retention(RetentionPolicy.RUNTIME)
@Target({ ElementType.TYPE, ElementType.METHOD })
@Repeatable(WithProcessorOption.List.class)
@Retention(RUNTIME)
@Target({ TYPE, METHOD })
public @interface WithProcessorOption {
String key();

String value();

@Target({ METHOD, FIELD, ANNOTATION_TYPE, CONSTRUCTOR, PARAMETER })
@Target({ METHOD, TYPE })
@Retention(RUNTIME)
@Documented
@interface List {
Expand Down