Package org.hibernate.ogm.query.impl

Source Code of org.hibernate.ogm.query.impl.FullTextSearchQueryTranslator$CacheKey

/*
* Hibernate OGM, Domain model persistence for NoSQL datastores
*
* 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.ogm.query.impl;

import java.util.Collections;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;
import java.util.concurrent.ConcurrentMap;

import org.hibernate.HibernateException;
import org.hibernate.MappingException;
import org.hibernate.QueryException;
import org.hibernate.ScrollableResults;
import org.hibernate.Session;
import org.hibernate.engine.spi.QueryParameters;
import org.hibernate.engine.spi.SessionFactoryImplementor;
import org.hibernate.engine.spi.SessionImplementor;
import org.hibernate.engine.spi.TypedValue;
import org.hibernate.event.spi.EventSource;
import org.hibernate.hql.QueryParser;
import org.hibernate.hql.lucene.LuceneProcessingChain;
import org.hibernate.hql.lucene.LuceneQueryParsingResult;
import org.hibernate.hql.spi.QueryTranslator;
import org.hibernate.internal.util.collections.BoundedConcurrentHashMap;
import org.hibernate.ogm.service.impl.SessionFactoryEntityNamesResolver;
import org.hibernate.search.FullTextQuery;
import org.hibernate.search.FullTextSession;
import org.hibernate.search.ProjectionConstants;
import org.hibernate.search.Search;
import org.hibernate.search.engine.spi.SearchFactoryImplementor;
import org.hibernate.search.query.DatabaseRetrievalMethod;
import org.hibernate.search.query.ObjectLookupMethod;

/**
* A {@link QueryTranslator} which translates JP-QL queries into equivalent Lucene queries and executes those via
* Hibernate Search.
*
* @author Gunnar Morling
*/
public class FullTextSearchQueryTranslator extends LegacyParserBridgeQueryTranslator {

  private final SessionFactoryEntityNamesResolver entityNamesResolver;

  /**
   * Lucene does not support parameterized queries. As a temporary measure, we therefore cache created queries per set
   * of parameter values. At one point, this should be replaced by caching the AST after validation but before the
   * actual Lucene query is created.
   */
  private final ConcurrentMap<CacheKey, LuceneQueryParsingResult> luceneQueryCache;

  public FullTextSearchQueryTranslator(SessionFactoryImplementor sessionFactory, String queryIdentifier, String query, Map<?, ?> filters) {
    super( sessionFactory, queryIdentifier, query, filters );
    entityNamesResolver = new SessionFactoryEntityNamesResolver( sessionFactory );

    luceneQueryCache = new BoundedConcurrentHashMap<CacheKey, LuceneQueryParsingResult>(
        100,
        20,
        BoundedConcurrentHashMap.Eviction.LIRS
    );
  }

  @Override
  public void doCompile(Map replacements, boolean shallow) throws QueryException, MappingException {
  }

  @Override
  public List<?> list(SessionImplementor session, QueryParameters queryParameters) throws HibernateException {
    FullTextSession fullTextSession = Search.getFullTextSession( (Session) session );

    LuceneQueryParsingResult parsingResult = getLuceneQuery( queryParameters, fullTextSession );

    FullTextQuery fullTextQuery = fullTextSession.createFullTextQuery( parsingResult.getQuery(), parsingResult.getTargetEntity() );

    if ( requiresProjections( parsingResult.getProjections() ) ) {
      fullTextQuery.setProjection( parsingResult.getProjections().toArray( new String[parsingResult.getProjections().size()] ) );
    }

    fullTextQuery.setSort( parsingResult.getSort() );

    // Following options are mandatory to load matching entities without using a query
    // (chicken and egg problem)
    fullTextQuery.initializeObjectsWith( ObjectLookupMethod.SKIP, DatabaseRetrievalMethod.FIND_BY_ID );

    if ( queryParameters.getRowSelection().getFirstRow() != null ) {
      fullTextQuery.setFirstResult( queryParameters.getRowSelection().getFirstRow() );
    }
    if ( queryParameters.getRowSelection().getMaxRows() != null ) {
      fullTextQuery.setMaxResults( queryParameters.getRowSelection().getMaxRows() );
    }

    return fullTextQuery.list();
  }

  private LuceneQueryParsingResult getLuceneQuery(QueryParameters queryParameters, FullTextSession fullTextSession) {
    CacheKey cacheKey = new CacheKey( queryParameters.getNamedParameters() );
    LuceneQueryParsingResult parsingResult = luceneQueryCache.get( cacheKey );

    if ( parsingResult == null ) {
      parsingResult = new QueryParser().parseQuery(
          getQueryString(),
          createProcessingChain( getNamedParameterValues( queryParameters ), fullTextSession )
      );

      LuceneQueryParsingResult cached = luceneQueryCache.putIfAbsent( cacheKey, parsingResult );
      if ( cached != null ) {
        parsingResult = cached;
      }
    }

    return parsingResult;
  }

  @Override
  public Iterator<?> iterate(QueryParameters queryParameters, EventSource session) throws HibernateException {
    throw new UnsupportedOperationException( "Not yet implemented" );
  }

  @Override
  public ScrollableResults scroll(QueryParameters queryParameters, SessionImplementor session) throws HibernateException {
    throw new UnsupportedOperationException( "Not yet implemented" );
  }

  @Override
  public int executeUpdate(QueryParameters queryParameters, SessionImplementor session) throws HibernateException {
    throw new UnsupportedOperationException( "Not yet implemented" );
  }

  private boolean requiresProjections(List<String> projections) {
    if ( projections.size() == 0 ) {
      return false;
    }
    else if ( projections.size() == 1 && ProjectionConstants.THIS.equals( projections.get( 0 ) ) ) {
      return false;
    }
    else {
      return true;
    }
  }

  private LuceneProcessingChain createProcessingChain(Map<String, Object> namedParameters, FullTextSession fullTextSession) {
    SearchFactoryImplementor searchFactory = (SearchFactoryImplementor) fullTextSession.getSearchFactory();

    return new LuceneProcessingChain.Builder( searchFactory, entityNamesResolver )
        .namedParameters( namedParameters )
        .buildProcessingChainForClassBasedEntities();
  }

  private Map<String, Object> getNamedParameterValues(QueryParameters queryParameters) {
    Map<String, Object> parameterValues = new HashMap<String, Object>( queryParameters.getNamedParameters().size() );

    for ( Entry<String, TypedValue> parameter : queryParameters.getNamedParameters().entrySet() ) {
      parameterValues.put( parameter.getKey(), parameter.getValue().getValue() );
    }

    return parameterValues;
  }

  private static class CacheKey {

    private final Map<String, TypedValue> parameters;
    private final int hashCode;

    public CacheKey(Map<String, TypedValue> parameters) {
      this.parameters = Collections.unmodifiableMap( parameters );
      this.hashCode = parameters.hashCode();
    }

    @Override
    public int hashCode() {
      return hashCode;
    }

    @Override
    public boolean equals(Object obj) {
      if ( this == obj ) {
        return true;
      }
      if ( obj == null ) {
        return false;
      }
      if ( getClass() != obj.getClass() ) {
        return false;
      }
      CacheKey other = (CacheKey) obj;
      if ( parameters == null ) {
        if ( other.parameters != null ) {
          return false;
        }
      }
      else if ( !parameters.equals( other.parameters ) ) {
        return false;
      }
      return true;
    }
  }
}
TOP

Related Classes of org.hibernate.ogm.query.impl.FullTextSearchQueryTranslator$CacheKey

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.