diff --git a/metamodel/generator-plugin/pom.xml b/metamodel/generator-plugin/pom.xml new file mode 100644 index 00000000000..c5b584394aa --- /dev/null +++ b/metamodel/generator-plugin/pom.xml @@ -0,0 +1,109 @@ + + 4.0.0 + + org.hibernate.search + hibernate-search-parent-public + 7.2.0-SNAPSHOT + ../../build/parents/public + + hibernate-search-metamodel-generator-plugin + maven-plugin + + Hibernate Search Metamodel Generator Plugin + Hibernate Search Metamodel Generator Plugin, creates static metamodel classes + + + + false + true + org.hibernate.search.metamodel.generator.plugin + + + + + org.hibernate.search + hibernate-search-engine + + + org.hibernate.search + hibernate-search-mapper-orm + true + + + org.hibernate.search + hibernate-search-mapper-pojo-standalone + true + + + org.jboss.logging + jboss-logging + + + org.jboss.logging + jboss-logging-annotations + + + + org.hibernate.search + hibernate-search-util-internal-integrationtest-mapper-orm + + + + org.apache.maven + maven-plugin-api + ${maven.min.version} + + + org.apache.maven + maven-core + ${maven.min.version} + + + org.apache.maven.plugin-tools + maven-plugin-annotations + 3.13.0 + provided + + + org.codehaus.plexus + plexus-utils + 3.5.1 + + + + org.hibernate.search + hibernate-search-util-internal-test-common + + + org.hibernate.search + hibernate-search-util-internal-integrationtest-backend-lucene + + + + com.h2database + h2 + + + + + + + org.apache.maven.plugins + maven-compiler-plugin + + + org.moditect + moditect-maven-plugin + + + add-module-infos + + none + + + + + + diff --git a/metamodel/generator-plugin/src/main/java/org/hibernate/search/metamodel/generator/plugin/HibernateSearchMetamodelGeneratorMojo.java b/metamodel/generator-plugin/src/main/java/org/hibernate/search/metamodel/generator/plugin/HibernateSearchMetamodelGeneratorMojo.java new file mode 100644 index 00000000000..7ed7ee193cf --- /dev/null +++ b/metamodel/generator-plugin/src/main/java/org/hibernate/search/metamodel/generator/plugin/HibernateSearchMetamodelGeneratorMojo.java @@ -0,0 +1,135 @@ +/* + * Hibernate Search, full-text search for your domain model + * + * License: GNU Lesser General Public License (LGPL), version 2.1 or later + * See the lgpl.txt file in the root directory or . + */ +package org.hibernate.search.metamodel.generator.plugin; + +import java.io.FileOutputStream; +import java.io.IOException; +import java.nio.charset.StandardCharsets; +import java.nio.file.Files; +import java.nio.file.Path; +import java.util.Collection; +import java.util.List; +import java.util.Objects; +import java.util.Properties; + +import org.hibernate.SessionFactory; +import org.hibernate.search.engine.backend.metamodel.IndexDescriptor; +import org.hibernate.search.engine.backend.metamodel.IndexFieldDescriptor; +import org.hibernate.search.mapper.orm.Search; +import org.hibernate.search.mapper.orm.entity.SearchIndexedEntity; +import org.hibernate.search.mapper.orm.mapping.SearchMapping; +import org.hibernate.search.util.impl.integrationtest.backend.lucene.LuceneBackendConfiguration; +import org.hibernate.search.util.impl.integrationtest.mapper.orm.OrmSetupHelper; + +import org.apache.maven.model.Dependency; +import org.apache.maven.plugin.AbstractMojo; +import org.apache.maven.plugin.MojoExecutionException; +import org.apache.maven.plugin.MojoFailureException; +import org.apache.maven.plugins.annotations.LifecyclePhase; +import org.apache.maven.plugins.annotations.Mojo; +import org.apache.maven.plugins.annotations.Parameter; +import org.apache.maven.project.MavenProject; + +@Mojo(name = "generate-metamodel", defaultPhase = LifecyclePhase.GENERATE_SOURCES) +public class HibernateSearchMetamodelGeneratorMojo extends AbstractMojo { + + @Parameter(defaultValue = "${project}", required = true, readonly = true) + MavenProject project; + + @Parameter(property = "annotatedTypes") + List annotatedTypes; + + @Parameter(property = "properties") + Properties properties; + + @Override + public void execute() throws MojoExecutionException, MojoFailureException { + getLog().info( "Hibernate Search Metamodel Generator" ); + getLog().info( "Dependencies: " + project.getDependencies() ); + + if ( hasOrmMapper( project.getDependencies() ) ) { + getLog().info( "Sources: " + project.getCompileSourceRoots() ); + OrmSetupHelper.SetupContext setupContext = + OrmSetupHelper.withSingleBackend( new LuceneBackendConfiguration() ).start(); + + properties.forEach( (k, v) -> setupContext.withProperty( Objects.toString( k ), v ) ); + + Path generatedMetamodelLocation = + Path.of( project.getBuild().getOutputDirectory() ).resolveSibling( "generated-metamodel-sources" ); + project.addCompileSourceRoot( generatedMetamodelLocation.toString() ); + + + try ( SessionFactory sessionFactory = setupContext.setup( annotatedTypes() ) ) { + SearchMapping mapping = Search.mapping( sessionFactory ); + + Collection> indexedEntities = mapping.allIndexedEntities(); + + for ( SearchIndexedEntity indexedEntity : indexedEntities ) { + createClass( indexedEntity, generatedMetamodelLocation ); + } + + getLog().info( "Indexed entities: " + indexedEntities ); + + } + + } + } + + private void createClass(SearchIndexedEntity indexedEntity, Path root) { + getLog().info( "Creating class for entity: " + indexedEntity.jpaName() ); + + IndexDescriptor descriptor = indexedEntity.indexManager().descriptor(); + + StringBuilder fields = new StringBuilder(); + + for ( IndexFieldDescriptor staticField : descriptor.staticFields() ) { + fields.append( '\n' ) + .append( '\t' ).append( "public String " ).append( staticField.relativeName() ).append( ";" ); + } + + try { + Class javaClass = indexedEntity.javaClass(); + Path pckg = root.resolve( Path.of( javaClass.getPackageName().replace( '.', '/' ) ) ); + Files.createDirectories( pckg ); + try ( FileOutputStream os = + new FileOutputStream( pckg.resolve( javaClass.getSimpleName() + ".java" ).toFile() ); ) { + os.write( new StringBuilder().append( "package " ).append( javaClass.getPackageName() ).append( ";\n\n" ) + .append( "class " ).append( javaClass.getSimpleName() ).append( "__ {\n" ) + .append( fields ) + .append( "\t\n}" ) + .toString().getBytes( StandardCharsets.UTF_8 ) ); + } + + } + catch (IOException e) { + throw new RuntimeException( e ); + } + + } + + private Class[] annotatedTypes() { + try { + Class[] types = new Class[annotatedTypes.size()]; + for ( int i = 0; i < annotatedTypes.size(); i++ ) { + types[i] = Class.forName( annotatedTypes.get( i ) ); + } + return types; + } + catch (ClassNotFoundException e) { + throw new RuntimeException( e ); + } + } + + private boolean hasOrmMapper(List dependencies) { + for ( Dependency dependency : dependencies ) { + if ( "hibernate-search-mapper-orm".equals( dependency.getArtifactId() ) ) { + return true; + } + } + return false; + } +} diff --git a/metamodel/generator-test/generation/pom.xml b/metamodel/generator-test/generation/pom.xml new file mode 100644 index 00000000000..7ace37ce175 --- /dev/null +++ b/metamodel/generator-test/generation/pom.xml @@ -0,0 +1,82 @@ + + 4.0.0 + + org.hibernate.search + hibernate-search-metamodel-generator-test-parent + 7.2.0-SNAPSHOT + .. + + hibernate-search-metamodel-generator-test-generation + + Hibernate Search Metamodel Generator TEST + + + + false + org.hibernate.search.metamodel.generator.test + h2 + + + + + org.hibernate.search + hibernate-search-metamodel-generator-model + ${project.version} + + + org.hibernate.search + hibernate-search-mapper-orm + + + + + + + org.hibernate.search + hibernate-search-metamodel-generator-plugin + ${project.version} + + + generate + + generate-metamodel + + generate-sources + + + org.hibernate.search.metamodel.generator.model.MyEntity + org.hibernate.search.metamodel.generator.model.MyProgrammaticEntity + + + org.hibernate.search.metamodel.generator.model.MyConfigurer + + + + + + + org.hibernate.search + hibernate-search-metamodel-generator-model + ${project.version} + + + + + org.apache.maven.plugins + maven-compiler-plugin + + + org.moditect + moditect-maven-plugin + + + add-module-infos + + none + + + + + + diff --git a/metamodel/generator-test/model/pom.xml b/metamodel/generator-test/model/pom.xml new file mode 100644 index 00000000000..69b0abaae2a --- /dev/null +++ b/metamodel/generator-test/model/pom.xml @@ -0,0 +1,70 @@ + + 4.0.0 + + org.hibernate.search + hibernate-search-metamodel-generator-test-parent + 7.2.0-SNAPSHOT + .. + + hibernate-search-metamodel-generator-model + + Hibernate Search Metamodel Generator Model + + + + false + org.hibernate.search.metamodel.generator + + + + + org.hibernate.search + hibernate-search-engine + + + org.hibernate.search + hibernate-search-mapper-orm + true + + + org.hibernate.search + hibernate-search-mapper-pojo-standalone + true + + + org.jboss.logging + jboss-logging + + + org.jboss.logging + jboss-logging-annotations + + + + org.hibernate.search + hibernate-search-util-internal-test-common + test + + + + + + + org.apache.maven.plugins + maven-compiler-plugin + + + org.moditect + moditect-maven-plugin + + + add-module-infos + + none + + + + + + diff --git a/metamodel/generator-test/model/src/main/java/org/hibernate/search/metamodel/generator/model/MyConfigurer.java b/metamodel/generator-test/model/src/main/java/org/hibernate/search/metamodel/generator/model/MyConfigurer.java new file mode 100644 index 00000000000..b2a031f0156 --- /dev/null +++ b/metamodel/generator-test/model/src/main/java/org/hibernate/search/metamodel/generator/model/MyConfigurer.java @@ -0,0 +1,28 @@ +/* + * Hibernate Search, full-text search for your domain model + * + * License: GNU Lesser General Public License (LGPL), version 2.1 or later + * See the lgpl.txt file in the root directory or . + */ +package org.hibernate.search.metamodel.generator.model; + +import org.hibernate.search.engine.backend.types.Projectable; +import org.hibernate.search.engine.backend.types.Sortable; +import org.hibernate.search.mapper.orm.mapping.HibernateOrmMappingConfigurationContext; +import org.hibernate.search.mapper.orm.mapping.HibernateOrmSearchMappingConfigurer; +import org.hibernate.search.mapper.pojo.mapping.definition.programmatic.ProgrammaticMappingConfigurationContext; +import org.hibernate.search.mapper.pojo.mapping.definition.programmatic.TypeMappingStep; + +public class MyConfigurer implements HibernateOrmSearchMappingConfigurer { + @Override + public void configure(HibernateOrmMappingConfigurationContext context) { + ProgrammaticMappingConfigurationContext mapping = context.programmaticMapping(); + TypeMappingStep bookMapping = mapping.type( MyProgrammaticEntity.class ); + bookMapping.indexed(); + bookMapping.property( "text" ) + .fullTextField() + .projectable( Projectable.YES ); + bookMapping.property( "number" ) + .genericField().sortable( Sortable.YES ); + } +} diff --git a/metamodel/generator-test/model/src/main/java/org/hibernate/search/metamodel/generator/model/MyEntity.java b/metamodel/generator-test/model/src/main/java/org/hibernate/search/metamodel/generator/model/MyEntity.java new file mode 100644 index 00000000000..04d9416076b --- /dev/null +++ b/metamodel/generator-test/model/src/main/java/org/hibernate/search/metamodel/generator/model/MyEntity.java @@ -0,0 +1,23 @@ +/* + * Hibernate Search, full-text search for your domain model + * + * License: GNU Lesser General Public License (LGPL), version 2.1 or later + * See the lgpl.txt file in the root directory or . + */ +package org.hibernate.search.metamodel.generator.model; + +import jakarta.persistence.Entity; +import jakarta.persistence.Id; + +import org.hibernate.search.mapper.pojo.mapping.definition.annotation.FullTextField; +import org.hibernate.search.mapper.pojo.mapping.definition.annotation.Indexed; + +@Indexed +@Entity +public class MyEntity { + @Id + Long id; + + @FullTextField + String text; +} diff --git a/metamodel/generator-test/model/src/main/java/org/hibernate/search/metamodel/generator/model/MyProgrammaticEntity.java b/metamodel/generator-test/model/src/main/java/org/hibernate/search/metamodel/generator/model/MyProgrammaticEntity.java new file mode 100644 index 00000000000..3d715e2da4e --- /dev/null +++ b/metamodel/generator-test/model/src/main/java/org/hibernate/search/metamodel/generator/model/MyProgrammaticEntity.java @@ -0,0 +1,20 @@ +/* + * Hibernate Search, full-text search for your domain model + * + * License: GNU Lesser General Public License (LGPL), version 2.1 or later + * See the lgpl.txt file in the root directory or . + */ +package org.hibernate.search.metamodel.generator.model; + +import jakarta.persistence.Entity; +import jakarta.persistence.Id; + +@Entity +public class MyProgrammaticEntity { + @Id + Long id; + + String text; + + Integer number; +} diff --git a/metamodel/generator-test/pom.xml b/metamodel/generator-test/pom.xml new file mode 100644 index 00000000000..dc1884f4985 --- /dev/null +++ b/metamodel/generator-test/pom.xml @@ -0,0 +1,21 @@ + + 4.0.0 + + org.hibernate.search + hibernate-search-parent-public + 7.2.0-SNAPSHOT + ../../build/parents/public + + pom + hibernate-search-metamodel-generator-test-parent + + + false + + + + model + generation + + diff --git a/pom.xml b/pom.xml index 6e977aeb25d..456950cda08 100644 --- a/pom.xml +++ b/pom.xml @@ -187,6 +187,8 @@ build/parents/integrationtest build/parents/springtest integrationtest + metamodel/generator-test + metamodel/generator-plugin documentation diff --git a/util/internal/integrationtest/common/src/main/java/org/hibernate/search/util/impl/integrationtest/common/TestConfigurationProvider.java b/util/internal/integrationtest/common/src/main/java/org/hibernate/search/util/impl/integrationtest/common/TestConfigurationProvider.java index b94a2d09493..36a7fa76e25 100644 --- a/util/internal/integrationtest/common/src/main/java/org/hibernate/search/util/impl/integrationtest/common/TestConfigurationProvider.java +++ b/util/internal/integrationtest/common/src/main/java/org/hibernate/search/util/impl/integrationtest/common/TestConfigurationProvider.java @@ -38,7 +38,7 @@ public final class TestConfigurationProvider private static final String STARTUP_TIMESTAMP = new SimpleDateFormat( "yyyy-MM-dd-HH-mm-ss.SSS", Locale.ROOT ) .format( new Date() ); - private String testId; + private String testId = UUID.randomUUID().toString(); @Override public void afterAll(ExtensionContext context) { diff --git a/util/internal/integrationtest/mapper/orm/src/main/java/org/hibernate/search/util/impl/integrationtest/mapper/orm/DatabaseContainer.java b/util/internal/integrationtest/mapper/orm/src/main/java/org/hibernate/search/util/impl/integrationtest/mapper/orm/DatabaseContainer.java index 399c3662fa1..0077c60328f 100644 --- a/util/internal/integrationtest/mapper/orm/src/main/java/org/hibernate/search/util/impl/integrationtest/mapper/orm/DatabaseContainer.java +++ b/util/internal/integrationtest/mapper/orm/src/main/java/org/hibernate/search/util/impl/integrationtest/mapper/orm/DatabaseContainer.java @@ -50,7 +50,7 @@ private DatabaseContainer() { static { - String name = System.getProperty( "org.hibernate.search.integrationtest.orm.database.kind", "" ); + String name = System.getProperty( "org.hibernate.search.integrationtest.orm.database.kind", "h2" ); Path containers = Path.of( System.getProperty( "org.hibernate.search.integrationtest.container.directory", "" ) ); DATABASE = SupportedDatabase.from( name );