Package org.hibernate.search.impl

Source Code of org.hibernate.search.impl.SearchMappingBuilder

/*
* 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.impl;

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;

/**
* package class extracting the SearchMappingFactory if needed
*/
public class SearchMappingBuilder {
  private static final Log LOG = LoggerFactory.make();

  private SearchMappingBuilder() {
  }

  /**
   * 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 getSearchMapping(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;
  }
}
TOP

Related Classes of org.hibernate.search.impl.SearchMappingBuilder

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.