content: /**
   * Licensed to the Apache Software Foundation (ASF) under one or more
   * contributor license agreements.  See the NOTICE file distributed with
   * this work for additional information regarding copyright ownership.
   * The ASF licenses this file to You under the Apache License, Version 2.0
   * (the "License"); you may not use this file except in compliance with
   * the License.  You may obtain a copy of the License at
   *
   *     http://www.apache.org/licenses/LICENSE-2.0
   *
   * Unless required by applicable law or agreed to in writing, software
   * distributed under the License is distributed on an "AS IS" BASIS,
   * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
   * See the License for the specific language governing permissions and
   * limitations under the License.
   */
  
  package org.apache.solr.search;
  
  /**
   * <code>DocSlice</code> implements DocList as an array of docids and optional scores.
   *
   * @version $Id: DocSlice.java 790938 2009-07-03 15:09:21Z yonik $
   * @since solr 0.9
   */
  public class DocSlice extends DocSetBase implements DocList {
    final int offset;    // starting position of the docs (zero based)
    final int len;       // number of positions used in arrays
    final int[] docs;    // a slice of documents (docs 0-100 of the query)
  
    final float[] scores;  // optional score list
    final int matches;
    final float maxScore;
    final double sum;
    final double max;
    final double min;
  
    /**
     * Primary constructor for a DocSlice instance.
     *
     * @param offset  starting offset for this range of docs
     * @param len     length of results
     * @param docs    array of docids starting at position 0
     * @param scores  array of scores that corresponds to docs, may be null
     * @param matches total number of matches for the query
     */
    public DocSlice(int offset, int len, int[] docs, float[] scores,
    			 int matches, float maxScore, double sum, double max, double min) {
      this.offset=offset;
      this.len=len;
      this.docs=docs;
      this.scores=scores;
      this.matches=matches;
      this.maxScore=maxScore;
  	this.sum = sum;
  	this.max = max;
  	this.min = min;
    }
  
    public DocList subset(int offset, int len) {
      if (this.offset == offset && this.len==len) return this;
  
      // if we didn't store enough (and there was more to store)
      // then we can't take a subset.
      int requestedEnd = offset + len;
      if (requestedEnd > docs.length && this.matches > docs.length) return null;
      int realEndDoc = Math.min(requestedEnd, docs.length);
      int realLen = Math.max(realEndDoc-offset,0);
      if (this.offset == offset && this.len == realLen) return this;
      return new DocSlice(offset, realLen, docs, scores,
  						 matches, maxScore, sum, max, min);
    }
  
    public boolean hasScores() {
      return scores!=null;
    }
  
    public float maxScore() {
      return maxScore;
    }
    
    public double sum() { return sum; }
    public double max() { return max; }
    public double min() { return min; }
  
    public int offset()  { return offset; }
    public int size()    { return len; }
    public int matches() { return matches; }
  
  
    public long memSize() {
      return (docs.length<<2)
              + (scores==null ? 0 : (scores.length<<2))
              + 24;
    }
  
  
    public boolean exists(int doc) {
      int end = offset+len;
      for (int i=offset; i<end; i++) {
        if (docs[i]==doc) return true;
      }
      return false;
    }
  
    // Hmmm, maybe I could have reused the scorer interface here...
    // except that it carries Similarity baggage...
    public DocIterator iterator() {
      return new DocIterator() {
        int pos=offset;
        final int end=offset+len;
        public boolean hasNext() {
          return pos < end;
        }
  
        public Integer next() {
          return nextDoc();
        }
  
        /**
         * The remove  operation is not supported by this Iterator.
         */
        public void remove() {
          throw new UnsupportedOperationException("The remove  operation is not supported by this Iterator.");
        }
  
        public int nextDoc() {
          return docs[pos++];
        }
  
        public float score() {
          return scores[pos-1];
        }
      };
    }
  
  
    @Override
    public DocSet intersection(DocSet other) {
      if (other instanceof SortedIntDocSet || other instanceof HashDocSet) {
        return other.intersection(this);
      }
      HashDocSet h = new HashDocSet(docs,offset,len);
      return h.intersection(other);
    }
  
    @Override
    public int intersectionSize(DocSet other) {
      if (other instanceof SortedIntDocSet || other instanceof HashDocSet) {
        return other.intersectionSize(this);
      }
      HashDocSet h = new HashDocSet(docs,offset,len);
      return h.intersectionSize(other);  
    }
  
  
  }
  