Package org.hibernate.search.query.engine.impl

Source Code of org.hibernate.search.query.engine.impl.ReusableDocumentStoredFieldVisitor$ChainedFieldAcceptor

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

import java.io.IOException;
import java.util.Set;

import org.apache.lucene.document.Document;
import org.apache.lucene.document.Field;
import org.apache.lucene.document.FieldType;
import org.apache.lucene.document.StoredField;
import org.apache.lucene.document.TextField;
import org.apache.lucene.index.FieldInfo;
import org.apache.lucene.index.StoredFieldVisitor;

/**
* Inspired by Lucene's DocumentStoredFieldVisitor, with the difference that we want
* to reuse the same FieldVisitor to load multiple Document instances.
* Also the accepted fields are kept in a linked-list like structure, to optimize
* for small amounts of accepted fields.
*
* A ReusableDocumentStoredFieldVisitor is NOT threadsafe: in case you need one
* for multiple threads make a clone for each thread.
*
* @see org.apache.lucene.document.DocumentStoredFieldVisitor
* @author Sanne Grinovero
*/
public final class ReusableDocumentStoredFieldVisitor extends StoredFieldVisitor {

  private static final FieldAcceptor NOT_ACCEPT = new DenyingFieldAcceptor();

  private final FieldAcceptor rootAcceptor;
  private Document doc = null;

  public ReusableDocumentStoredFieldVisitor(Set<String> fieldsToLoad) {
    FieldAcceptor previous = NOT_ACCEPT;
    for ( String fieldName : fieldsToLoad ) {
      previous = new ChainedFieldAcceptor( previous, fieldName );
    }
    this.rootAcceptor = previous;
  }

  @Override
  public void binaryField(FieldInfo fieldInfo, byte[] value) throws IOException {
    getDocument().add( new StoredField( fieldInfo.name, value ) );
  }

  @Override
  public void stringField(FieldInfo fieldInfo, String value) throws IOException {
    final FieldType ft = new FieldType( TextField.TYPE_STORED );
    ft.setStoreTermVectors( fieldInfo.hasVectors() );
    ft.setIndexed( fieldInfo.isIndexed() );
    ft.setOmitNorms( fieldInfo.omitsNorms() );
    ft.setIndexOptions( fieldInfo.getIndexOptions() );
    getDocument().add( new Field( fieldInfo.name, value, ft ) );
  }

  @Override
  public void intField(FieldInfo fieldInfo, int value) {
    getDocument().add( new StoredField( fieldInfo.name, value ) );
  }

  @Override
  public void longField(FieldInfo fieldInfo, long value) {
    getDocument().add( new StoredField( fieldInfo.name, value ) );
  }

  @Override
  public void floatField(FieldInfo fieldInfo, float value) {
    getDocument().add( new StoredField( fieldInfo.name, value ) );
  }

  @Override
  public void doubleField(FieldInfo fieldInfo, double value) {
    getDocument().add( new StoredField( fieldInfo.name, value ) );
  }

  @Override
  public Status needsField(FieldInfo fieldInfo) throws IOException {
    return rootAcceptor.acceptField( fieldInfo.name );
  }

  /**
   * Useful for tests
   * @return the amount of accepted fields
   */
  public int countAcceptedFields() {
    FieldAcceptor acceptor = rootAcceptor;
    int count = 0;
    while ( acceptor != NOT_ACCEPT ) {
      //If it's not negative it has to be positive:
      ChainedFieldAcceptor positiveAcceptor = (ChainedFieldAcceptor) acceptor;
      acceptor = positiveAcceptor.next;
      count++;
    }
    return count;
  }

  /**
   * Retrieve the visited document, and resets the instance to be reused by creating a new Document
   * internally.
   *
   * @return Document populated with stored fields.
   */
  public Document getDocumentAndReset() {
    final Document localDoc = this.doc;
    if ( localDoc == null ) {
      return new Document();
    }
    else {
      this.doc = null;
      return localDoc;
    }
  }

  private Document getDocument() {
    Document localDoc = this.doc;
    if ( localDoc == null ) {
      localDoc = new Document();
      this.doc = localDoc;
    }
    return localDoc;
  }

  /* The structure below shapes a chain of accepted field names:
   * you could think of it as a linked list. */

  private interface FieldAcceptor {
    Status acceptField(String fieldName);
  }

  private static final class DenyingFieldAcceptor implements FieldAcceptor {
    public Status acceptField(final String fieldName) {
      return Status.NO;
    }
  }

  private static final class ChainedFieldAcceptor implements FieldAcceptor {
    final FieldAcceptor next;
    final String acceptedFieldName;
    ChainedFieldAcceptor(FieldAcceptor next, String acceptedFieldName) {
      this.next = next;
      this.acceptedFieldName = acceptedFieldName;
    }
    public Status acceptField(final String fieldName) {
      if ( acceptedFieldName.equals( fieldName ) ) {
        return Status.YES;
      }
      else {
        return next.acceptField( fieldName );
      }
    }
  }

}
TOP

Related Classes of org.hibernate.search.query.engine.impl.ReusableDocumentStoredFieldVisitor$ChainedFieldAcceptor

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.