Package org.hibernate.sql.ast.origin.hql.resolve

Source Code of org.hibernate.sql.ast.origin.hql.resolve.LuceneJPQLWalker

/*
* Hibernate, Relational Persistence for Idiomatic Java
*
* JBoss, Home of Professional Open Source
* Copyright 2011 Red Hat Inc. and/or its affiliates and other contributors
* as indicated by the @authors tag. All rights reserved.
* See the copyright.txt in the distribution for a
* full listing of individual contributors.
*
* This copyrighted material is made available to anyone wishing to use,
* modify, copy, or redistribute it subject to the terms and conditions
* of the GNU Lesser General Public License, v. 2.1.
* This program is distributed in the hope that it will be useful, but WITHOUT A
* WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A
* PARTICULAR PURPOSE.  See the GNU Lesser General Public License for more details.
* You should have received a copy of the GNU Lesser General Public License,
* v.2.1 along with this distribution; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
* MA  02110-1301, USA.
*/
package org.hibernate.sql.ast.origin.hql.resolve;

import java.util.Collections;
import java.util.HashMap;
import java.util.Map;
import java.util.Stack;

import org.antlr.runtime.tree.Tree;
import org.antlr.runtime.tree.TreeNodeStream;
import org.apache.lucene.index.Term;
import org.apache.lucene.search.BooleanClause.Occur;
import org.apache.lucene.search.BooleanQuery;
import org.apache.lucene.search.MatchAllDocsQuery;
import org.apache.lucene.search.Query;
import org.apache.lucene.search.TermQuery;
import org.hibernate.search.engine.spi.SearchFactoryImplementor;
import org.hibernate.search.query.dsl.impl.ConnectedQueryContextBuilder;
import org.hibernate.sql.ast.common.JoinType;
import org.hibernate.sql.ast.origin.hql.resolve.path.PathedPropertyReference;
import org.hibernate.sql.ast.origin.hql.resolve.path.PathedPropertyReferenceSource;

/**
* This extends the ANTLR generated AST walker to transform a parsed tree
* into a Lucene Query and collect the target entity types of the query.
* <br/>
* <b>TODO:</b>
*   <li>It is currently human-written but should evolve into another ANTLR
* generated tree walker, not extending GeneratedHQLResolver but using its
* output as a generic normalization AST transformer.</li>
*   <li>We are assembling the Lucene Query directly, but this doesn't take
*   into account parameter types which might need some transformation;
*   the Hibernate Search provided {@link QueryBuilder} could do this.</li>
*   <li>Implement more predicates</li>
*   <li>Support multiple types being targeted by the Query</li>
*   <li>Support positional parameters (currently only consumed named parameters)<li>
*
* @author Sanne Grinovero <sanne@hibernate.org> (C) 2011 Red Hat Inc.
*/
public class LuceneJPQLWalker extends GeneratedHQLResolver {

  /**
   * Persister space: keep track of aliases and entity names.
   */
  private final Map<String, String> aliasToEntityType = new HashMap<String, String>();

  /**
   * Set to true when we are walking in the tree area defining a SELECT type/options
   */
  private boolean definingSelectStrategy;

  /**
   * We refer to a SearchFactor to build queries
   */
  private final SearchFactoryImplementor searchFactory;

  /**
   * Map predicate and searchConditions to the root query context
   */
  private final ConnectedQueryContextBuilder queryBuildContext;

  /**
   * How to resolve entity names to class instances
   */
  private final EntityNamesResolver entityNames;

//  private QueryBuilder queryBuilder = null;
  private Class targetType = null;

  private BooleanQuery booleanQuery;
  private Stack<BooleanQuery> booleanQueryStack = new Stack<BooleanQuery>();
  private Stack<Occur> booleanQueryModeStack = new Stack<Occur>();

  private Occur booleanMode;

  private String propertyName;

  private Query rootQuery = new MatchAllDocsQuery();

  private final Map<String, Object> namedParameters;

  public LuceneJPQLWalker(TreeNodeStream input, SearchFactoryImplementor searchFactory,
      EntityNamesResolver entityNames) {
    this( input, searchFactory, entityNames, Collections.EMPTY_MAP );
  }

  public LuceneJPQLWalker(TreeNodeStream input, SearchFactoryImplementor searchFactory,
      EntityNamesResolver entityNames, Map<String,Object> namedParameters) {
    super( input );
    this.searchFactory = searchFactory;
    this.entityNames = entityNames;
    this.namedParameters = namedParameters;
    this.queryBuildContext = new ConnectedQueryContextBuilder( searchFactory );
  }

  /**
   * See rule entityName
   */
  protected void registerPersisterSpace(Tree entityName, Tree alias) {
    String put = aliasToEntityType.put( alias.getText(), entityName.getText() );
    if ( put != null && !put.equalsIgnoreCase( entityName.getText() ) ) {
      throw new UnsupportedOperationException(
          "Alias reuse currently not supported: alias " + alias.getText()
              + " already assigned to type " + put );
    }
    Class targetedType = entityNames.getClassFromName( entityName.getText() );
    if ( targetedType == null ) {
      throw new IllegalStateException( "Unknown entity name " + entityName.getText() );
    }
    if ( targetType != null ) {
      throw new IllegalStateException( "Can't target multiple types: " + targetType + " already selected before " + targetedType );
    }
    targetType = targetedType;
//    queryBuilder = queryBuildContext.forEntity( targetedType ).get();
  }

  protected boolean isUnqualifiedPropertyReference() {
    return true; // TODO - very likely always true for our supported use cases
  }

  protected PathedPropertyReferenceSource normalizeUnqualifiedPropertyReference(Tree property) {
    this.propertyName = property.getText();
    return null;// return value is ignored anyway
  }

  protected boolean isPersisterReferenceAlias() {
    if ( aliasToEntityType.size() == 1 ) {
      return true; // should be safe
    }
    else {
      throw new UnsupportedOperationException( "Unexpected use case: not implemented yet?" );
    }
  }

  protected PathedPropertyReferenceSource normalizeUnqualifiedRoot(Tree identifier382) {
    throw new UnsupportedOperationException( "must be overridden!" );
  }

  protected PathedPropertyReferenceSource normalizeQualifiedRoot(Tree identifier381) {
    return new PathedPropertyReference( identifier381.getText(), aliasToEntityType );
  }

  protected PathedPropertyReferenceSource normalizePropertyPathIntermediary(
      PathedPropertyReferenceSource source, Tree propertyName) {
    throw new UnsupportedOperationException( "must be overridden!" );
  }

  protected PathedPropertyReferenceSource normalizeIntermediateIndexOperation(
      PathedPropertyReferenceSource propertyReferenceSource, Tree collectionProperty, Tree selector) {
    throw new UnsupportedOperationException( "must be overridden!" );
  }

  protected void normalizeTerminalIndexOperation(
      PathedPropertyReferenceSource propertyReferenceSource, Tree collectionProperty, Tree selector) {
    throw new UnsupportedOperationException( "must be overridden!" );
  }

  protected PathedPropertyReferenceSource normalizeUnqualifiedPropertyReferenceSource(Tree identifier394) {
    throw new UnsupportedOperationException( "must be overridden!" );
  }

  protected Tree normalizePropertyPathTerminus(PathedPropertyReferenceSource source, Tree propertyNameNode) {
    // receives the property name on a specific entity reference _source_
    this.propertyName = propertyNameNode.toString();
    return null;
  }

  protected void pushFromStrategy(
      JoinType joinType,
      Tree assosiationFetchTree,
      Tree propertyFetchTree,
      Tree alias) {
    throw new UnsupportedOperationException( "must be overridden!" );
  }

  protected void pushSelectStrategy() {
    definingSelectStrategy = true;
  }

  protected void popStrategy() {
    definingSelectStrategy = false;
  }

  public Class getTargetEntity() {
    return targetType;
  }

  protected void activateOR() {
    activateBoolean();
    booleanQuery = new BooleanQuery();
    booleanMode = Occur.SHOULD;
  }

  protected void activateAND() {
    activateBoolean();
    booleanQuery = new BooleanQuery();
    booleanMode = Occur.MUST;
  }

  protected void activateNOT() {
    activateBoolean();
    booleanQuery = new BooleanQuery();
    booleanMode = Occur.MUST_NOT;
  }

  /**
   * This implements the equality predicate; the comparison
   * predicate could be a constant, a subfunction or
   * some random type parameter.
   * The tree node has all details but with current tree rendering
   * it just passes it's text so we have to figure out the options again.
   */
  protected void predicateEquals(final String comparativePredicate) {
    final Object comparison = fromNamedQuery( comparativePredicate );
    String comparisonTerm = valueToString( comparison );
    TermQuery predicate = new TermQuery( new Term( propertyName, comparisonTerm ) );
    if ( booleanQuery != null ) {
      booleanQuery.add( predicate, booleanMode );
    }
    else {
      rootQuery = predicate;
    }
  }

  private String valueToString(Object comparison) {
    return comparison.toString();
  }

  private Object fromNamedQuery(String comparativePredicate) {
    if ( comparativePredicate.startsWith( ":" ) ) {
      return namedParameters.get( comparativePredicate.substring( 1 ) );
    }
    else {
      return comparativePredicate;
    }
  }

  private void activateBoolean() {
    booleanQueryStack.push( booleanQuery );
    booleanQueryModeStack.push( booleanMode );
  }

  protected void deactivateBoolean() {
    BooleanQuery currentBoolean = booleanQuery;
    booleanQuery = booleanQueryStack.pop();
    booleanMode = booleanQueryModeStack.pop();
    if ( booleanQuery == null ) {
      this.rootQuery = currentBoolean;
    }
    else {
      booleanQuery.add( currentBoolean, booleanMode );
    }
  }

  public String toString() {
    return rootQuery.toString();
  }

  public Query getLuceneQuery() {
    return rootQuery;
  }
}
TOP

Related Classes of org.hibernate.sql.ast.origin.hql.resolve.LuceneJPQLWalker

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.