org.hibernate.search.engine.spi.SearchMappingHelper Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of hibernate-search-engine Show documentation
Show all versions of hibernate-search-engine Show documentation
Core of the Object/Lucene mapper, query engine and index management
/*
* 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.engine.spi;
import java.lang.reflect.Method;
import org.hibernate.search.exception.SearchException;
import org.hibernate.search.cfg.Environment;
import org.hibernate.search.cfg.SearchMapping;
import org.hibernate.search.cfg.spi.SearchConfiguration;
import org.hibernate.search.annotations.Factory;
import org.hibernate.search.engine.service.classloading.spi.ClassLoaderService;
import org.hibernate.search.engine.service.classloading.spi.ClassLoadingException;
import org.hibernate.search.util.impl.ReflectionHelper;
import org.hibernate.search.util.logging.impl.Log;
import org.hibernate.search.util.logging.impl.LoggerFactory;
import java.lang.invoke.MethodHandles;
/**
* Helper to extract the programmatic SearchMapping from a configuration object
*/
public class SearchMappingHelper {
private static final Log LOG = LoggerFactory.make( MethodHandles.lookup() );
private SearchMappingHelper() {
}
/**
* This factory method takes a SearchConfiguration object
* and returns a SearchMapping object which defines
* the programmatic model for indexing entities and fields.
*
* Throws SearchException:
* 1) No @Factory found
* 2) Multiple @Factory found
* 3) hibernate.search.model_mapping defines a class that cannot be found
* 4) Cannot invoke the @Factory method to get new instance of SearchMapping
*
* @param cfg the search configuration
* @return SearchMapping
*/
public static SearchMapping extractSearchMapping(SearchConfiguration cfg) {
// try SearchConfiguration object first and then properties
Object modelMappingProperty = cfg.getProgrammaticMapping();
if ( modelMappingProperty == null ) {
modelMappingProperty = cfg.getProperties().get( Environment.MODEL_MAPPING );
}
if ( modelMappingProperty == null ) {
return null;
}
SearchMapping mapping = null;
Object programmaticConfig = modelMappingProperty;
if ( programmaticConfig instanceof SearchMapping ) {
mapping = (SearchMapping) programmaticConfig;
return mapping;
}
// TODO - It would be nice to get the class loader service from the service manager, instead of directly from
// the SearchConfiguration. However, with the current bootstrapping approach that is not possible.
// Maybe this can be addressed with a refactoring of the bootstrap process. (HF)
Class> clazz = getProgrammaticMappingClass( programmaticConfig, cfg.getClassLoaderService() );
Method[] methods = clazz.getDeclaredMethods();
int count = 0;
for ( Method method : methods ) {
if ( method.isAnnotationPresent( Factory.class ) ) {
count++;
ReflectionHelper.setAccessible( method );
mapping = getNewInstanceOfSearchMapping( clazz, method );
}
}
validateMappingFactoryDefinition( count, clazz );
return mapping;
}
private static SearchMapping getNewInstanceOfSearchMapping(Class> clazz, Method method) {
SearchMapping mapping;
try {
LOG.debugf( "invoking factory method [ %s.%s ] to get search mapping instance", clazz.getName(), method.getName() );
Object instance = clazz.newInstance();
mapping = (SearchMapping) method.invoke( instance );
}
catch (Exception e) {
throw new SearchException( "Unable to call the factory method: " + clazz.getName() + "." + method.getName(), e );
}
return mapping;
}
private static void validateMappingFactoryDefinition(int count, Class> factory) {
if ( count == 0 ) {
throw new SearchException( "No @Factory method defined for building programmatic api on " + factory );
}
if ( count > 1 ) {
throw new SearchException( "Multiple @Factory methods defined. Only one factory method required. " + factory );
}
}
private static Class> getProgrammaticMappingClass(Object programmaticConfig, ClassLoaderService classLoaderService) {
Class> clazz;
if ( programmaticConfig instanceof String ) {
final String className = (String) programmaticConfig;
try {
clazz = classLoaderService.classForName( className );
}
catch (ClassLoadingException e) {
throw new SearchException( "Unable to find " + Environment.MODEL_MAPPING + "=" + className, e );
}
}
else if ( programmaticConfig instanceof Class ) {
clazz = (Class>) programmaticConfig;
}
else {
throw new SearchException( Environment.MODEL_MAPPING + " is of an unknown type: " + programmaticConfig.getClass() );
}
if ( clazz == null ) {
throw new SearchException( "No programmatic factory defined" );
}
return clazz;
}
}
© 2015 - 2025 Weber Informatics LLC | Privacy Policy