Package com.tigertext.lucene.ext

Source Code of com.tigertext.lucene.ext.ErlangFilter

package com.tigertext.lucene.ext;

import java.io.IOException;
import java.util.HashMap;
import java.util.Map;
import java.util.logging.Logger;

import org.apache.lucene.index.IndexReader;
import org.apache.lucene.search.DocIdSet;
import org.apache.lucene.search.FieldCache;
import org.apache.lucene.search.Filter;
import org.apache.lucene.util.FixedBitSet;

import com.ericsson.otp.erlang.OtpErlangAtom;
import com.ericsson.otp.erlang.OtpErlangBinary;
import com.ericsson.otp.erlang.OtpErlangDecodeException;
import com.ericsson.otp.erlang.OtpErlangDouble;
import com.ericsson.otp.erlang.OtpErlangException;
import com.ericsson.otp.erlang.OtpErlangExit;
import com.ericsson.otp.erlang.OtpErlangFloat;
import com.ericsson.otp.erlang.OtpErlangInt;
import com.ericsson.otp.erlang.OtpErlangList;
import com.ericsson.otp.erlang.OtpErlangLong;
import com.ericsson.otp.erlang.OtpErlangObject;
import com.ericsson.otp.erlang.OtpErlangString;
import com.ericsson.otp.erlang.OtpErlangTuple;
import com.ericsson.otp.stdlib.OtpGenServer;
import com.tigertext.lucene.DocumentTranslator.FieldType;
import com.tigertext.lucene.LuceneNode;

/**
* Erlang filter: filters results according to an erlang module and function and
* keeps them cached for further use
*
* @author Fernando Benavides <elbrujohalcon@inaka.net>
*/
public class ErlangFilter extends Filter {
  private static final Logger    jlog        = Logger.getLogger(ErlangFilter.class
                                .getName());

  private static final long    serialVersionUID  = 892972394357766013L;
  private final OtpErlangAtom    mod;
  private final OtpErlangAtom    fun;
  private final String      fieldName;
  private Map<Integer, Double>  scores;
  private int            nextDocBase;

  private FieldType        fieldType;

  private OtpErlangString      arg;

  /**
   * Default constructor
   *
   * @param mod
   *            Erlang module
   * @param fun
   *            Erlang function
   * @param arg
   *            First argument(s) on the call to mod:fun. They're written like
   *            io_lib:format(...). They'll be parsed on the Erlang side before
   *            calling mod:fun
   * @param fieldName
   *            Lucene field to consider
   * @param fieldType
   *            Type of the values to find in fieldName
   */
  public ErlangFilter(String mod, String fun, String arg, String fieldName,
      FieldType fieldType) {
    this.mod = new OtpErlangAtom(mod);
    this.fun = new OtpErlangAtom(fun);
    this.arg = new OtpErlangString(arg);
    this.fieldName = fieldName;
    this.fieldType = fieldType;

    /* store calculated scores for reuse by other components */
    this.scores = new HashMap<Integer, Double>();
  }

  @Override
  public DocIdSet getDocIdSet(IndexReader reader) throws IOException {
    final int docBase = this.nextDocBase;
    this.nextDocBase += reader.maxDoc();

    final OtpErlangObject[] docValues;

    switch (this.fieldType) {
    case ATOM:
      docValues = getAtoms(reader);
      break;
    case DOUBLE:
      docValues = getDoubles(reader);
      break;
    case FLOAT:
      docValues = getFloats(reader);
      break;
    case GEO:
      docValues = getGeos(reader);
      break;
    case INT:
      docValues = getInts(reader);
      break;
    case LONG:
      docValues = getLongs(reader);
      break;
    default:
      docValues = getStrings(reader);
      break;
    }

    final FixedBitSet bits = new FixedBitSet(reader.maxDoc());

    // {Mod, Fun, [Values]}
    OtpErlangTuple call = new OtpErlangTuple(new OtpErlangObject[] {
        this.mod, this.fun, this.arg, new OtpErlangList(docValues) });
    try {
      jlog.fine("Calling lucene @ " + LuceneNode.PEER + ":\n\t"
          + this.mod + ":" + this.fun);
      OtpErlangObject response = OtpGenServer.call(LuceneNode.NODE,
          "lucene", LuceneNode.PEER, call);

      if (response == null) {
        jlog.warning("The rpc call to " + this.mod + ":" + this.fun
            + " timed out. No results will be returned");
      } else if (response instanceof OtpErlangList) {
        OtpErlangList results = (OtpErlangList) response;
        for (int docid = 0; docid < docValues.length; docid++) {
          OtpErlangObject result = results.elementAt(docid);
          if (result instanceof OtpErlangDouble) {
            scores.put(docid + docBase,
                ((OtpErlangDouble) result).doubleValue());
            bits.set(docid);
          } else {
            bits.clear(docid);
          }
        }
      } else {
        jlog.severe("The rpc call to " + this.mod + ":" + this.fun
            + " failed: " + response
            + ". No results will be returned");
      }
    } catch (OtpErlangExit e) {
      jlog.severe("The rpc call to " + this.mod + ":" + this.fun
          + " failed: " + e.getMessage()
          + ". No results will be returned");
      e.printStackTrace();
    } catch (OtpErlangDecodeException e) {
      jlog.severe("The rpc call to " + this.mod + ":" + this.fun
          + " failed: " + e.getMessage()
          + ". No results will be returned");
      e.printStackTrace();
    } catch (OtpErlangException e) {
      jlog.severe("The rpc call to " + this.mod + ":" + this.fun
          + " failed: " + e.getMessage()
          + ". No results will be returned");
      e.printStackTrace();
    }

    jlog.finer("Bits: " + bits.getBits());
    return bits;
  }

  private OtpErlangObject[] getGeos(IndexReader reader) throws IOException {
    final OtpErlangObject[] docValues;
    final double[] latIndex = FieldCache.DEFAULT.getDoubles(reader,
        this.fieldName + "`lat");
    final double[] lngIndex = FieldCache.DEFAULT.getDoubles(reader,
        this.fieldName + "`lng");
    docValues = new OtpErlangObject[latIndex.length];
    for (int i = 0; i < latIndex.length; i++) {
      docValues[i] = new OtpErlangTuple(new OtpErlangObject[] {
          new OtpErlangAtom("geo"), new OtpErlangDouble(latIndex[i]),
          new OtpErlangDouble(lngIndex[i]) });
    }
    return docValues;
  }

  private OtpErlangObject[] getStrings(IndexReader reader) throws IOException {
    final OtpErlangObject[] docValues;
    String[] origs = FieldCache.DEFAULT.getStrings(reader, this.fieldName);
    docValues = new OtpErlangObject[origs.length];
    for (int i = 0; i < origs.length; i++) {
      if (origs[i] != null) {
        docValues[i] = new OtpErlangBinary(getBytesFast(origs[i]));
      } else {
        docValues[i] = new OtpErlangAtom("undefined");
      }
    }
    return docValues;
  }

  private static byte[] getBytesFast(String str) {
    final char buffer[] = new char[str.length()];
    final int length = str.length();
    str.getChars(0, length, buffer, 0);
    final byte b[] = new byte[length];
    for (int j = 0; j < length; j++)
      b[j] = (byte) buffer[j];
    return b;
  }

  private OtpErlangObject[] getLongs(IndexReader reader) throws IOException {
    final OtpErlangObject[] docValues;
    long[] origs = FieldCache.DEFAULT.getLongs(reader, this.fieldName);
    docValues = new OtpErlangObject[origs.length];
    for (int i = 0; i < origs.length; i++) {
      docValues[i] = new OtpErlangLong(origs[i]);
    }
    return docValues;
  }

  private OtpErlangObject[] getInts(IndexReader reader) throws IOException {
    final OtpErlangObject[] docValues;
    int[] origs = FieldCache.DEFAULT.getInts(reader, this.fieldName);
    docValues = new OtpErlangObject[origs.length];
    for (int i = 0; i < origs.length; i++) {
      docValues[i] = new OtpErlangInt(origs[i]);
    }
    return docValues;
  }

  private OtpErlangObject[] getFloats(IndexReader reader) throws IOException {
    final OtpErlangObject[] docValues;
    float[] origs = FieldCache.DEFAULT.getFloats(reader, this.fieldName);
    docValues = new OtpErlangObject[origs.length];
    for (int i = 0; i < origs.length; i++) {
      if (origs[i] != Float.NaN) {
        docValues[i] = new OtpErlangFloat(origs[i]);
      } else {
        docValues[i] = new OtpErlangAtom("undefined");
      }
    }
    return docValues;
  }

  private OtpErlangObject[] getDoubles(IndexReader reader) throws IOException {
    final OtpErlangObject[] docValues;
    double[] origs = FieldCache.DEFAULT.getDoubles(reader, this.fieldName);
    docValues = new OtpErlangObject[origs.length];
    for (int i = 0; i < origs.length; i++) {
      if (origs[i] != Double.NaN) {
        docValues[i] = new OtpErlangDouble(origs[i]);
      } else {
        docValues[i] = new OtpErlangAtom("undefined");
      }
    }
    return docValues;
  }

  protected OtpErlangObject[] getAtoms(IndexReader reader) throws IOException {
    final OtpErlangObject[] docValues;
    String[] origs = FieldCache.DEFAULT.getStrings(reader, this.fieldName);
    docValues = new OtpErlangObject[origs.length];
    for (int i = 0; i < origs.length; i++) {
      if (origs[i] != null) {
        docValues[i] = new OtpErlangAtom(origs[i]);
      } else {
        docValues[i] = new OtpErlangAtom("undefined");
      }
    }
    return docValues;
  }

  /**
   * The score assigned to the doc
   *
   * @param docid
   *            Id of the doc
   * @return null or the score given by the erlang function
   */
  public Double getScore(int docid) {
    return this.scores.get(docid);
  }

  /*
   * (non-Javadoc)
   *
   * @see java.lang.Object#toString()
   */
  @Override
  public String toString() {
    return this.mod + ":" + this.fun + "(doc." + this.fieldName + ")";
  }
}
TOP

Related Classes of com.tigertext.lucene.ext.ErlangFilter

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.