Skip to content

Commit

Permalink
HSEARCH-3319 WIP: maven plugin to generate "metamodel classes"
Browse files Browse the repository at this point in the history
  • Loading branch information
marko-bekhta committed Aug 21, 2024
1 parent b90cef7 commit 8fecef1
Show file tree
Hide file tree
Showing 11 changed files with 492 additions and 2 deletions.
109 changes: 109 additions & 0 deletions metamodel/generator-plugin/pom.xml
Original file line number Diff line number Diff line change
@@ -0,0 +1,109 @@
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>org.hibernate.search</groupId>
<artifactId>hibernate-search-parent-public</artifactId>
<version>7.2.0-SNAPSHOT</version>
<relativePath>../../build/parents/public</relativePath>
</parent>
<artifactId>hibernate-search-metamodel-generator-plugin</artifactId>
<packaging>maven-plugin</packaging>

<name>Hibernate Search Metamodel Generator Plugin</name>
<description>Hibernate Search Metamodel Generator Plugin, creates static metamodel classes</description>

<properties>
<!-- This is a publicly distributed module that should be published: -->
<deploy.skip>false</deploy.skip>
<enforcer.dependencyconvergence.skip>true</enforcer.dependencyconvergence.skip>
<java.module.name>org.hibernate.search.metamodel.generator.plugin</java.module.name>
</properties>

<dependencies>
<dependency>
<groupId>org.hibernate.search</groupId>
<artifactId>hibernate-search-engine</artifactId>
</dependency>
<dependency>
<groupId>org.hibernate.search</groupId>
<artifactId>hibernate-search-mapper-orm</artifactId>
<optional>true</optional>
</dependency>
<dependency>
<groupId>org.hibernate.search</groupId>
<artifactId>hibernate-search-mapper-pojo-standalone</artifactId>
<optional>true</optional>
</dependency>
<dependency>
<groupId>org.jboss.logging</groupId>
<artifactId>jboss-logging</artifactId>
</dependency>
<dependency>
<groupId>org.jboss.logging</groupId>
<artifactId>jboss-logging-annotations</artifactId>
</dependency>

<dependency>
<groupId>org.hibernate.search</groupId>
<artifactId>hibernate-search-util-internal-integrationtest-mapper-orm</artifactId>
</dependency>

<dependency>
<groupId>org.apache.maven</groupId>
<artifactId>maven-plugin-api</artifactId>
<version>${maven.min.version}</version>
</dependency>
<dependency>
<groupId>org.apache.maven</groupId>
<artifactId>maven-core</artifactId>
<version>${maven.min.version}</version>
</dependency>
<dependency>
<groupId>org.apache.maven.plugin-tools</groupId>
<artifactId>maven-plugin-annotations</artifactId>
<version>3.13.0</version>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>org.codehaus.plexus</groupId>
<artifactId>plexus-utils</artifactId>
<version>3.5.1</version>
</dependency>

<dependency>
<groupId>org.hibernate.search</groupId>
<artifactId>hibernate-search-util-internal-test-common</artifactId>
</dependency>
<dependency>
<groupId>org.hibernate.search</groupId>
<artifactId>hibernate-search-util-internal-integrationtest-backend-lucene</artifactId>
</dependency>

<dependency>
<groupId>com.h2database</groupId>
<artifactId>h2</artifactId>
</dependency>
</dependencies>

<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
</plugin>
<plugin>
<groupId>org.moditect</groupId>
<artifactId>moditect-maven-plugin</artifactId>
<executions>
<execution>
<id>add-module-infos</id>
<!-- Do not generate module-info with moditect-maven-plugin:
This module depends on Lucene jars that have split packages module issue. -->
<phase>none</phase>
</execution>
</executions>
</plugin>
</plugins>
</build>
</project>
Original file line number Diff line number Diff line change
@@ -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 <http://www.gnu.org/licenses/lgpl-2.1.html>.
*/
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<String> 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<? extends SearchIndexedEntity<?>> 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<Dependency> dependencies) {
for ( Dependency dependency : dependencies ) {
if ( "hibernate-search-mapper-orm".equals( dependency.getArtifactId() ) ) {
return true;
}
}
return false;
}
}
82 changes: 82 additions & 0 deletions metamodel/generator-test/generation/pom.xml
Original file line number Diff line number Diff line change
@@ -0,0 +1,82 @@
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>org.hibernate.search</groupId>
<artifactId>hibernate-search-metamodel-generator-test-parent</artifactId>
<version>7.2.0-SNAPSHOT</version>
<relativePath>..</relativePath>
</parent>
<artifactId>hibernate-search-metamodel-generator-test-generation</artifactId>

<name>Hibernate Search Metamodel Generator TEST</name>

<properties>
<!-- This is a publicly distributed module that should be published: -->
<deploy.skip>false</deploy.skip>
<java.module.name>org.hibernate.search.metamodel.generator.test</java.module.name>
<org.hibernate.search.integrationtest.orm.database.kind>h2</org.hibernate.search.integrationtest.orm.database.kind>
</properties>

<dependencies>
<dependency>
<groupId>org.hibernate.search</groupId>
<artifactId>hibernate-search-metamodel-generator-model</artifactId>
<version>${project.version}</version>
</dependency>
<dependency>
<groupId>org.hibernate.search</groupId>
<artifactId>hibernate-search-mapper-orm</artifactId>
</dependency>
</dependencies>

<build>
<plugins>
<plugin>
<groupId>org.hibernate.search</groupId>
<artifactId>hibernate-search-metamodel-generator-plugin</artifactId>
<version>${project.version}</version>
<executions>
<execution>
<id>generate</id>
<goals>
<goal>generate-metamodel</goal>
</goals>
<phase>generate-sources</phase>
<configuration>
<annotatedTypes>
<type>org.hibernate.search.metamodel.generator.model.MyEntity</type>
<type>org.hibernate.search.metamodel.generator.model.MyProgrammaticEntity</type>
</annotatedTypes>
<properties>
<hibernate.search.mapping.configurer>org.hibernate.search.metamodel.generator.model.MyConfigurer</hibernate.search.mapping.configurer>
</properties>
</configuration>
</execution>
</executions>
<dependencies>
<dependency>
<groupId>org.hibernate.search</groupId>
<artifactId>hibernate-search-metamodel-generator-model</artifactId>
<version>${project.version}</version>
</dependency>
</dependencies>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
</plugin>
<plugin>
<groupId>org.moditect</groupId>
<artifactId>moditect-maven-plugin</artifactId>
<executions>
<execution>
<id>add-module-infos</id>
<!-- Do not generate module-info with moditect-maven-plugin -->
<phase>none</phase>
</execution>
</executions>
</plugin>
</plugins>
</build>
</project>
70 changes: 70 additions & 0 deletions metamodel/generator-test/model/pom.xml
Original file line number Diff line number Diff line change
@@ -0,0 +1,70 @@
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>org.hibernate.search</groupId>
<artifactId>hibernate-search-metamodel-generator-test-parent</artifactId>
<version>7.2.0-SNAPSHOT</version>
<relativePath>..</relativePath>
</parent>
<artifactId>hibernate-search-metamodel-generator-model</artifactId>

<name>Hibernate Search Metamodel Generator Model</name>

<properties>
<!-- This is a publicly distributed module that should be published: -->
<deploy.skip>false</deploy.skip>
<java.module.name>org.hibernate.search.metamodel.generator</java.module.name>
</properties>

<dependencies>
<dependency>
<groupId>org.hibernate.search</groupId>
<artifactId>hibernate-search-engine</artifactId>
</dependency>
<dependency>
<groupId>org.hibernate.search</groupId>
<artifactId>hibernate-search-mapper-orm</artifactId>
<optional>true</optional>
</dependency>
<dependency>
<groupId>org.hibernate.search</groupId>
<artifactId>hibernate-search-mapper-pojo-standalone</artifactId>
<optional>true</optional>
</dependency>
<dependency>
<groupId>org.jboss.logging</groupId>
<artifactId>jboss-logging</artifactId>
</dependency>
<dependency>
<groupId>org.jboss.logging</groupId>
<artifactId>jboss-logging-annotations</artifactId>
</dependency>

<dependency>
<groupId>org.hibernate.search</groupId>
<artifactId>hibernate-search-util-internal-test-common</artifactId>
<scope>test</scope>
</dependency>
</dependencies>

<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
</plugin>
<plugin>
<groupId>org.moditect</groupId>
<artifactId>moditect-maven-plugin</artifactId>
<executions>
<execution>
<id>add-module-infos</id>
<!-- Do not generate module-info with moditect-maven-plugin -->
<phase>none</phase>
</execution>
</executions>
</plugin>
</plugins>
</build>
</project>
Loading

0 comments on commit 8fecef1

Please sign in to comment.