All Downloads are FREE. Search and download functionalities are using the official Maven repository.

com.browseengine.bobo.facets.impl.CombinedDoubleFacetIterator Maven / Gradle / Ivy

Go to download

Bobo is a Faceted Search implementation written purely in Java, an extension of Apache Lucene

The newest version!
package com.browseengine.bobo.facets.impl;

import java.util.List;
import java.util.NoSuchElementException;

import com.browseengine.bobo.api.DoubleFacetIterator;
import com.browseengine.bobo.facets.data.TermDoubleList;

public class CombinedDoubleFacetIterator extends DoubleFacetIterator {

  public double facet;

  private static class DoubleIteratorNode {
    public DoubleFacetIterator _iterator;
    public double _curFacet;
    public int _curFacetCount;

    public DoubleIteratorNode(DoubleFacetIterator iterator) {
      _iterator = iterator;
      _curFacet = TermDoubleList.VALUE_MISSING;
      _curFacetCount = 0;
    }

    public boolean fetch(int minHits) {
      if (minHits > 0) minHits = 1;
      if ((_curFacet = _iterator.nextDouble(minHits)) != TermDoubleList.VALUE_MISSING) {
        _curFacetCount = _iterator.count;
        return true;
      }
      _curFacet = TermDoubleList.VALUE_MISSING;
      _curFacetCount = 0;
      return false;
    }
  }

  private final DoubleFacetPriorityQueue _queue;

  private List _iterators;

  private CombinedDoubleFacetIterator(final int length) {
    _queue = new DoubleFacetPriorityQueue();
    _queue.initialize(length);
  }

  public CombinedDoubleFacetIterator(final List iterators) {
    this(iterators.size());
    _iterators = iterators;
    for (DoubleFacetIterator iterator : iterators) {
      DoubleIteratorNode node = new DoubleIteratorNode(iterator);
      if (node.fetch(1)) _queue.add(node);
    }
    facet = TermDoubleList.VALUE_MISSING;
    count = 0;
  }

  public CombinedDoubleFacetIterator(final List iterators, int minHits) {
    this(iterators.size());
    _iterators = iterators;
    for (DoubleFacetIterator iterator : iterators) {
      DoubleIteratorNode node = new DoubleIteratorNode(iterator);
      if (node.fetch(minHits)) _queue.add(node);
    }
    facet = TermDoubleList.VALUE_MISSING;
    count = 0;
  }

  /*
   * (non-Javadoc)
   * @see com.browseengine.bobo.api.FacetIterator#getFacet()
   */
  public String getFacet() {
    if (facet == TermDoubleList.VALUE_MISSING) return null;
    return format(facet);
  }

  @Override
  public String format(double val) {
    return _iterators.get(0).format(val);
  }

  @Override
  public String format(Object val) {
    return _iterators.get(0).format(val);
  }

  /*
   * (non-Javadoc)
   * @see com.browseengine.bobo.api.FacetIterator#getFacetCount()
   */
  public int getFacetCount() {
    return count;
  }

  /*
   * (non-Javadoc)
   * @see com.browseengine.bobo.api.FacetIterator#next()
   */
  @Override
  public String next() {
    if (!hasNext()) throw new NoSuchElementException("No more facets in this iteration");

    DoubleIteratorNode node = _queue.top();

    facet = node._curFacet;
    double next = TermDoubleList.VALUE_MISSING;
    count = 0;
    while (hasNext()) {
      node = _queue.top();
      next = node._curFacet;
      if ((next != TermDoubleList.VALUE_MISSING) && (next != facet)) {
        return format(facet);
      }
      count += node._curFacetCount;
      if (node.fetch(1)) _queue.updateTop();
      else _queue.pop();
    }
    return null;
  }

  /**
   * This version of the next() method applies the minHits from the facet spec
   * before returning the facet and its hitcount
   *
   * @param minHits
   *          the minHits from the facet spec for CombinedFacetAccessible
   * @return The next facet that obeys the minHits
   */
  @Override
  public String next(int minHits) {
    int qsize = _queue.size();
    if (qsize == 0) {
      facet = TermDoubleList.VALUE_MISSING;
      count = 0;
      return null;
    }

    DoubleIteratorNode node = _queue.top();
    facet = node._curFacet;
    count = node._curFacetCount;
    while (true) {
      if (node.fetch(minHits)) {
        node = _queue.updateTop();
      } else {
        _queue.pop();
        if (--qsize > 0) {
          node = _queue.top();
        } else {
          // we reached the end. check if this facet obeys the minHits
          if (count < minHits) {
            facet = TermDoubleList.VALUE_MISSING;
            count = 0;
            return null;
          }
          break;
        }
      }
      double next = node._curFacet;
      if (next != facet) {
        // check if this facet obeys the minHits
        if (count >= minHits) break;
        // else, continue iterating to the next facet
        facet = next;
        count = node._curFacetCount;
      } else {
        count += node._curFacetCount;
      }
    }
    return format(facet);
  }

  /*
   * (non-Javadoc)
   * @see java.util.Iterator#hasNext()
   */
  @Override
  public boolean hasNext() {
    return (_queue.size() > 0);
  }

  /*
   * (non-Javadoc)
   * @see java.util.Iterator#remove()
   */
  @Override
  public void remove() {
    throw new UnsupportedOperationException("remove() method not supported for Facet Iterators");
  }

  /**
   * Lucene PriorityQueue
   *
   */
  public static class DoubleFacetPriorityQueue {
    private int size;
    private int maxSize;
    protected DoubleIteratorNode[] heap;

    /** Subclass constructors must call this. */
    protected final void initialize(int maxSize) {
      size = 0;
      int heapSize;
      if (0 == maxSize)
      // We allocate 1 extra to avoid if statement in top()
      heapSize = 2;
      else heapSize = maxSize + 1;
      heap = new DoubleIteratorNode[heapSize];
      this.maxSize = maxSize;
    }

    public final void put(DoubleIteratorNode element) {
      size++;
      heap[size] = element;
      upHeap();
    }

    public final DoubleIteratorNode add(DoubleIteratorNode element) {
      size++;
      heap[size] = element;
      upHeap();
      return heap[1];
    }

    public boolean insert(DoubleIteratorNode element) {
      return insertWithOverflow(element) != element;
    }

    public DoubleIteratorNode insertWithOverflow(DoubleIteratorNode element) {
      if (size < maxSize) {
        put(element);
        return null;
      } else if (size > 0 && !(element._curFacet < heap[1]._curFacet)) {
        DoubleIteratorNode ret = heap[1];
        heap[1] = element;
        adjustTop();
        return ret;
      } else {
        return element;
      }
    }

    /** Returns the least element of the PriorityQueue in constant time. */
    public final DoubleIteratorNode top() {
      // We don't need to check size here: if maxSize is 0,
      // then heap is length 2 array with both entries null.
      // If size is 0 then heap[1] is already null.
      return heap[1];
    }

    /**
     * Removes and returns the least element of the PriorityQueue in log(size)
     * time.
     */
    public final DoubleIteratorNode pop() {
      if (size > 0) {
        DoubleIteratorNode result = heap[1]; // save first value
        heap[1] = heap[size]; // move last to first
        heap[size] = null; // permit GC of objects
        size--;
        downHeap(); // adjust heap
        return result;
      } else return null;
    }

    public final void adjustTop() {
      downHeap();
    }

    public final DoubleIteratorNode updateTop() {
      downHeap();
      return heap[1];
    }

    /** Returns the number of elements currently stored in the PriorityQueue. */
    public final int size() {
      return size;
    }

    /** Removes all entries from the PriorityQueue. */
    public final void clear() {
      for (int i = 0; i <= size; i++) {
        heap[i] = null;
      }
      size = 0;
    }

    private final void upHeap() {
      int i = size;
      DoubleIteratorNode node = heap[i]; // save bottom node
      int j = i >>> 1;
      while (j > 0 && (node._curFacet < heap[j]._curFacet)) {
        heap[i] = heap[j]; // shift parents down
        i = j;
        j = j >>> 1;
      }
      heap[i] = node; // install saved node
    }

    private final void downHeap() {
      int i = 1;
      DoubleIteratorNode node = heap[i]; // save top node
      int j = i << 1; // find smaller child
      int k = j + 1;
      if (k <= size && (heap[k]._curFacet < heap[j]._curFacet)) {
        j = k;
      }
      while (j <= size && (heap[j]._curFacet < node._curFacet)) {
        heap[i] = heap[j]; // shift up child
        i = j;
        j = i << 1;
        k = j + 1;
        if (k <= size && (heap[k]._curFacet < heap[j]._curFacet)) {
          j = k;
        }
      }
      heap[i] = node; // install saved node
    }
  }

  @Override
  public double nextDouble() {
    if (!hasNext()) throw new NoSuchElementException("No more facets in this iteration");

    DoubleIteratorNode node = _queue.top();

    facet = node._curFacet;
    double next = TermDoubleList.VALUE_MISSING;
    count = 0;
    while (hasNext()) {
      node = _queue.top();
      next = node._curFacet;
      if ((next != TermDoubleList.VALUE_MISSING) && (next != facet)) {
        return facet;
      }
      count += node._curFacetCount;
      if (node.fetch(1)) _queue.updateTop();
      else _queue.pop();
    }
    return TermDoubleList.VALUE_MISSING;
  }

  @Override
  public double nextDouble(int minHits) {
    int qsize = _queue.size();
    if (qsize == 0) {
      facet = TermDoubleList.VALUE_MISSING;
      count = 0;
      return TermDoubleList.VALUE_MISSING;
    }

    DoubleIteratorNode node = _queue.top();
    facet = node._curFacet;
    count = node._curFacetCount;
    while (true) {
      if (node.fetch(minHits)) {
        node = _queue.updateTop();
      } else {
        _queue.pop();
        if (--qsize > 0) {
          node = _queue.top();
        } else {
          // we reached the end. check if this facet obeys the minHits
          if (count < minHits) {
            facet = TermDoubleList.VALUE_MISSING;
            count = 0;
          }
          break;
        }
      }
      double next = node._curFacet;
      if (next != facet) {
        // check if this facet obeys the minHits
        if (count >= minHits) break;
        // else, continue iterating to the next facet
        facet = next;
        count = node._curFacetCount;
      } else {
        count += node._curFacetCount;
      }
    }
    return facet;
  }
}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy