Home » lucene-3.0.1-src » org.apache » lucene » search » spans » [javadoc | source]

    1   package org.apache.lucene.search.spans;
    2   
    3   /**
    4    * Licensed to the Apache Software Foundation (ASF) under one or more
    5    * contributor license agreements.  See the NOTICE file distributed with
    6    * this work for additional information regarding copyright ownership.
    7    * The ASF licenses this file to You under the Apache License, Version 2.0
    8    * (the "License"); you may not use this file except in compliance with
    9    * the License.  You may obtain a copy of the License at
   10    *
   11    *     http://www.apache.org/licenses/LICENSE-2.0
   12    *
   13    * Unless required by applicable law or agreed to in writing, software
   14    * distributed under the License is distributed on an "AS IS" BASIS,
   15    * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
   16    * See the License for the specific language governing permissions and
   17    * limitations under the License.
   18    */
   19   
   20   import org.apache.lucene.index.IndexReader;
   21   import org.apache.lucene.index.Term;
   22   import org.apache.lucene.search.Query;
   23   import org.apache.lucene.util.ToStringUtils;
   24   
   25   import java.io.IOException;
   26   import java.util.ArrayList;
   27   import java.util.Collection;
   28   import java.util.Set;
   29   
   30   /** Removes matches which overlap with another SpanQuery. */
   31   public class SpanNotQuery extends SpanQuery implements Cloneable {
   32     private SpanQuery include;
   33     private SpanQuery exclude;
   34   
   35     /** Construct a SpanNotQuery matching spans from <code>include</code> which
   36      * have no overlap with spans from <code>exclude</code>.*/
   37     public SpanNotQuery(SpanQuery include, SpanQuery exclude) {
   38       this.include = include;
   39       this.exclude = exclude;
   40   
   41       if (!include.getField().equals(exclude.getField()))
   42         throw new IllegalArgumentException("Clauses must have same field.");
   43     }
   44   
   45     /** Return the SpanQuery whose matches are filtered. */
   46     public SpanQuery getInclude() { return include; }
   47   
   48     /** Return the SpanQuery whose matches must not overlap those returned. */
   49     public SpanQuery getExclude() { return exclude; }
   50   
   51     @Override
   52     public String getField() { return include.getField(); }
   53   
   54     @Override
   55     public void extractTerms(Set<Term> terms) { include.extractTerms(terms); }
   56   
   57     @Override
   58     public String toString(String field) {
   59       StringBuilder buffer = new StringBuilder();
   60       buffer.append("spanNot(");
   61       buffer.append(include.toString(field));
   62       buffer.append(", ");
   63       buffer.append(exclude.toString(field));
   64       buffer.append(")");
   65       buffer.append(ToStringUtils.boost(getBoost()));
   66       return buffer.toString();
   67     }
   68   
   69     @Override
   70     public Object clone() {
   71       SpanNotQuery spanNotQuery = new SpanNotQuery((SpanQuery)include.clone(),(SpanQuery) exclude.clone());
   72       spanNotQuery.setBoost(getBoost());
   73       return  spanNotQuery;
   74     }
   75   
   76     @Override
   77     public Spans getSpans(final IndexReader reader) throws IOException {
   78       return new Spans() {
   79           private Spans includeSpans = include.getSpans(reader);
   80           private boolean moreInclude = true;
   81   
   82           private Spans excludeSpans = exclude.getSpans(reader);
   83           private boolean moreExclude = excludeSpans.next();
   84   
   85           @Override
   86           public boolean next() throws IOException {
   87             if (moreInclude)                        // move to next include
   88               moreInclude = includeSpans.next();
   89   
   90             while (moreInclude && moreExclude) {
   91   
   92               if (includeSpans.doc() > excludeSpans.doc()) // skip exclude
   93                 moreExclude = excludeSpans.skipTo(includeSpans.doc());
   94   
   95               while (moreExclude                    // while exclude is before
   96                      && includeSpans.doc() == excludeSpans.doc()
   97                      && excludeSpans.end() <= includeSpans.start()) {
   98                 moreExclude = excludeSpans.next();  // increment exclude
   99               }
  100   
  101               if (!moreExclude                      // if no intersection
  102                   || includeSpans.doc() != excludeSpans.doc()
  103                   || includeSpans.end() <= excludeSpans.start())
  104                 break;                              // we found a match
  105   
  106               moreInclude = includeSpans.next();    // intersected: keep scanning
  107             }
  108             return moreInclude;
  109           }
  110   
  111           @Override
  112           public boolean skipTo(int target) throws IOException {
  113             if (moreInclude)                        // skip include
  114               moreInclude = includeSpans.skipTo(target);
  115   
  116             if (!moreInclude)
  117               return false;
  118   
  119             if (moreExclude                         // skip exclude
  120                 && includeSpans.doc() > excludeSpans.doc())
  121               moreExclude = excludeSpans.skipTo(includeSpans.doc());
  122   
  123             while (moreExclude                      // while exclude is before
  124                    && includeSpans.doc() == excludeSpans.doc()
  125                    && excludeSpans.end() <= includeSpans.start()) {
  126               moreExclude = excludeSpans.next();    // increment exclude
  127             }
  128   
  129             if (!moreExclude                      // if no intersection
  130                   || includeSpans.doc() != excludeSpans.doc()
  131                   || includeSpans.end() <= excludeSpans.start())
  132               return true;                          // we found a match
  133   
  134             return next();                          // scan to next match
  135           }
  136   
  137           @Override
  138           public int doc() { return includeSpans.doc(); }
  139           @Override
  140           public int start() { return includeSpans.start(); }
  141           @Override
  142           public int end() { return includeSpans.end(); }
  143   
  144         // TODO: Remove warning after API has been finalized
  145         @Override
  146         public Collection<byte[]> getPayload() throws IOException {
  147           ArrayList<byte[]> result = null;
  148           if (includeSpans.isPayloadAvailable()) {
  149             result = new ArrayList<byte[]>(includeSpans.getPayload());
  150           }
  151           return result;
  152         }
  153   
  154         // TODO: Remove warning after API has been finalized
  155         @Override
  156         public boolean isPayloadAvailable() {
  157           return includeSpans.isPayloadAvailable();
  158         }
  159   
  160         @Override
  161         public String toString() {
  162             return "spans(" + SpanNotQuery.this.toString() + ")";
  163           }
  164   
  165         };
  166     }
  167   
  168     @Override
  169     public Query rewrite(IndexReader reader) throws IOException {
  170       SpanNotQuery clone = null;
  171   
  172       SpanQuery rewrittenInclude = (SpanQuery) include.rewrite(reader);
  173       if (rewrittenInclude != include) {
  174         clone = (SpanNotQuery) this.clone();
  175         clone.include = rewrittenInclude;
  176       }
  177       SpanQuery rewrittenExclude = (SpanQuery) exclude.rewrite(reader);
  178       if (rewrittenExclude != exclude) {
  179         if (clone == null) clone = (SpanNotQuery) this.clone();
  180         clone.exclude = rewrittenExclude;
  181       }
  182   
  183       if (clone != null) {
  184         return clone;                        // some clauses rewrote
  185       } else {
  186         return this;                         // no clauses rewrote
  187       }
  188     }
  189   
  190       /** Returns true iff <code>o</code> is equal to this. */
  191     @Override
  192     public boolean equals(Object o) {
  193       if (this == o) return true;
  194       if (!(o instanceof SpanNotQuery)) return false;
  195   
  196       SpanNotQuery other = (SpanNotQuery)o;
  197       return this.include.equals(other.include)
  198               && this.exclude.equals(other.exclude)
  199               && this.getBoost() == other.getBoost();
  200     }
  201   
  202     @Override
  203     public int hashCode() {
  204       int h = include.hashCode();
  205       h = (h<<1) | (h >>> 31);  // rotate left
  206       h ^= exclude.hashCode();
  207       h = (h<<1) | (h >>> 31);  // rotate left
  208       h ^= Float.floatToRawIntBits(getBoost());
  209       return h;
  210     }
  211   
  212   }

Home » lucene-3.0.1-src » org.apache » lucene » search » spans » [javadoc | source]