You are viewing a plain text version of this content. The canonical link for it is here.
Posted to java-commits@lucene.apache.org by do...@apache.org on 2007/06/05 18:29:42 UTC

svn commit: r544546 [1/2] - in /lucene/java/trunk: ./ src/java/org/apache/lucene/search/ src/java/org/apache/lucene/search/function/ src/java/org/apache/lucene/util/ src/test/org/apache/lucene/search/function/

Author: doronc
Date: Tue Jun  5 09:29:35 2007
New Revision: 544546

URL: http://svn.apache.org/viewvc?view=rev&rev=544546
Log:
LUCENE-446: Added Solr's search.function for scores based on field 
values, plus CustomScoreQuery for simple score (post) customization.

Added:
    lucene/java/trunk/src/java/org/apache/lucene/search/function/
    lucene/java/trunk/src/java/org/apache/lucene/search/function/ByteFieldSource.java   (with props)
    lucene/java/trunk/src/java/org/apache/lucene/search/function/CustomScoreQuery.java   (with props)
    lucene/java/trunk/src/java/org/apache/lucene/search/function/DocValues.java   (with props)
    lucene/java/trunk/src/java/org/apache/lucene/search/function/FieldCacheSource.java   (with props)
    lucene/java/trunk/src/java/org/apache/lucene/search/function/FieldScoreQuery.java   (with props)
    lucene/java/trunk/src/java/org/apache/lucene/search/function/FloatFieldSource.java   (with props)
    lucene/java/trunk/src/java/org/apache/lucene/search/function/IntFieldSource.java   (with props)
    lucene/java/trunk/src/java/org/apache/lucene/search/function/OrdFieldSource.java   (with props)
    lucene/java/trunk/src/java/org/apache/lucene/search/function/ReverseOrdFieldSource.java   (with props)
    lucene/java/trunk/src/java/org/apache/lucene/search/function/ShortFieldSource.java   (with props)
    lucene/java/trunk/src/java/org/apache/lucene/search/function/ValueSource.java   (with props)
    lucene/java/trunk/src/java/org/apache/lucene/search/function/ValueSourceQuery.java   (with props)
    lucene/java/trunk/src/java/org/apache/lucene/search/function/package.html   (with props)
    lucene/java/trunk/src/test/org/apache/lucene/search/function/
    lucene/java/trunk/src/test/org/apache/lucene/search/function/FunctionTestSetup.java   (with props)
    lucene/java/trunk/src/test/org/apache/lucene/search/function/TestCustomScoreQuery.java   (with props)
    lucene/java/trunk/src/test/org/apache/lucene/search/function/TestFieldScoreQuery.java   (with props)
    lucene/java/trunk/src/test/org/apache/lucene/search/function/TestOrdValues.java   (with props)
Modified:
    lucene/java/trunk/CHANGES.txt
    lucene/java/trunk/src/java/org/apache/lucene/search/FieldCache.java
    lucene/java/trunk/src/java/org/apache/lucene/search/FieldCacheImpl.java
    lucene/java/trunk/src/java/org/apache/lucene/util/ToStringUtils.java

Modified: lucene/java/trunk/CHANGES.txt
URL: http://svn.apache.org/viewvc/lucene/java/trunk/CHANGES.txt?view=diff&rev=544546&r1=544545&r2=544546
==============================================================================
--- lucene/java/trunk/CHANGES.txt (original)
+++ lucene/java/trunk/CHANGES.txt Tue Jun  5 09:29:35 2007
@@ -186,6 +186,10 @@
     on the remote side of the RMI connection.
     (Matt Ericson via Otis Gospodnetic)
 
+ 8. LUCENE-446: Added Solr's search.function for scores based on field 
+    values, plus CustomScoreQuery for simple score (post) customization.
+    (Yonik Seeley, Doron Cohen)
+ 
 Optimizations
 
  1. LUCENE-761: The proxStream is now cloned lazily in SegmentTermPositions

Modified: lucene/java/trunk/src/java/org/apache/lucene/search/FieldCache.java
URL: http://svn.apache.org/viewvc/lucene/java/trunk/src/java/org/apache/lucene/search/FieldCache.java?view=diff&rev=544546&r1=544545&r2=544546
==============================================================================
--- lucene/java/trunk/src/java/org/apache/lucene/search/FieldCache.java (original)
+++ lucene/java/trunk/src/java/org/apache/lucene/search/FieldCache.java Tue Jun  5 09:29:35 2007
@@ -53,6 +53,22 @@
     }
   }
 
+  /** Interface to parse bytes from document fields.
+   * @see FieldCache#getBytes(IndexReader, String, FieldCache.ByteParser)
+   */
+  public interface ByteParser {
+    /** Return a single Byte representation of this field's value. */
+    public byte parseByte(String string);
+  }
+
+  /** Interface to parse shorts from document fields.
+   * @see FieldCache#getShorts(IndexReader, String, FieldCache.ShortParser)
+   */
+  public interface ShortParser {
+    /** Return a short representation of this field's value. */
+    public short parseShort(String string);
+  }
+
   /** Interface to parse ints from document fields.
    * @see FieldCache#getInts(IndexReader, String, FieldCache.IntParser)
    */
@@ -71,6 +87,56 @@
 
   /** Expert: The cache used internally by sorting and range query classes. */
   public static FieldCache DEFAULT = new FieldCacheImpl();
+
+  /** Checks the internal cache for an appropriate entry, and if none is
+   * found, reads the terms in <code>field</code> as a single byte and returns an array
+   * of size <code>reader.maxDoc()</code> of the value each document
+   * has in the given field.
+   * @param reader  Used to get field values.
+   * @param field   Which field contains the single byte values.
+   * @return The values in the given field for each document.
+   * @throws IOException  If any error occurs.
+   */
+  public byte[] getBytes (IndexReader reader, String field)
+  throws IOException;
+
+  /** Checks the internal cache for an appropriate entry, and if none is found,
+   * reads the terms in <code>field</code> as bytes and returns an array of
+   * size <code>reader.maxDoc()</code> of the value each document has in the
+   * given field.
+   * @param reader  Used to get field values.
+   * @param field   Which field contains the bytes.
+   * @param parser  Computes byte for string values.
+   * @return The values in the given field for each document.
+   * @throws IOException  If any error occurs.
+   */
+  public byte[] getBytes (IndexReader reader, String field, ByteParser parser)
+  throws IOException;
+
+  /** Checks the internal cache for an appropriate entry, and if none is
+   * found, reads the terms in <code>field</code> as shorts and returns an array
+   * of size <code>reader.maxDoc()</code> of the value each document
+   * has in the given field.
+   * @param reader  Used to get field values.
+   * @param field   Which field contains the shorts.
+   * @return The values in the given field for each document.
+   * @throws IOException  If any error occurs.
+   */
+  public short[] getShorts (IndexReader reader, String field)
+  throws IOException;
+
+  /** Checks the internal cache for an appropriate entry, and if none is found,
+   * reads the terms in <code>field</code> as shorts and returns an array of
+   * size <code>reader.maxDoc()</code> of the value each document has in the
+   * given field.
+   * @param reader  Used to get field values.
+   * @param field   Which field contains the shorts.
+   * @param parser  Computes short for string values.
+   * @return The values in the given field for each document.
+   * @throws IOException  If any error occurs.
+   */
+  public short[] getShorts (IndexReader reader, String field, ShortParser parser)
+  throws IOException;
 
   /** Checks the internal cache for an appropriate entry, and if none is
    * found, reads the terms in <code>field</code> as integers and returns an array

Modified: lucene/java/trunk/src/java/org/apache/lucene/search/FieldCacheImpl.java
URL: http://svn.apache.org/viewvc/lucene/java/trunk/src/java/org/apache/lucene/search/FieldCacheImpl.java?view=diff&rev=544546&r1=544545&r2=544546
==============================================================================
--- lucene/java/trunk/src/java/org/apache/lucene/search/FieldCacheImpl.java (original)
+++ lucene/java/trunk/src/java/org/apache/lucene/search/FieldCacheImpl.java Tue Jun  5 09:29:35 2007
@@ -131,18 +131,108 @@
     }
   }
 
+  private static final ByteParser BYTE_PARSER = new ByteParser() {
+    public byte parseByte(String value) {
+      return Byte.parseByte(value);
+    }
+  };
+
+  private static final ShortParser SHORT_PARSER = new ShortParser() {
+    public short parseShort(String value) {
+      return Short.parseShort(value);
+    }
+  };
+
   private static final IntParser INT_PARSER = new IntParser() {
       public int parseInt(String value) {
         return Integer.parseInt(value);
       }
-    };
+  };
 
   private static final FloatParser FLOAT_PARSER = new FloatParser() {
       public float parseFloat(String value) {
         return Float.parseFloat(value);
       }
-    };
+  };
+
+  // inherit javadocs
+  public byte[] getBytes (IndexReader reader, String field) throws IOException {
+    return getBytes(reader, field, BYTE_PARSER);
+  }
+
+  // inherit javadocs
+  public byte[] getBytes(IndexReader reader, String field, ByteParser parser)
+      throws IOException {
+    return (byte[]) bytesCache.get(reader, new Entry(field, parser));
+  }
+
+  Cache bytesCache = new Cache() {
+
+    protected Object createValue(IndexReader reader, Object entryKey)
+        throws IOException {
+      Entry entry = (Entry) entryKey;
+      String field = entry.field;
+      ByteParser parser = (ByteParser) entry.custom;
+      final byte[] retArray = new byte[reader.maxDoc()];
+      TermDocs termDocs = reader.termDocs();
+      TermEnum termEnum = reader.terms (new Term (field, ""));
+      try {
+        do {
+          Term term = termEnum.term();
+          if (term==null || term.field() != field) break;
+          byte termval = parser.parseByte(term.text());
+          termDocs.seek (termEnum);
+          while (termDocs.next()) {
+            retArray[termDocs.doc()] = termval;
+          }
+        } while (termEnum.next());
+      } finally {
+        termDocs.close();
+        termEnum.close();
+      }
+      return retArray;
+    }
+  };
+  
+  // inherit javadocs
+  public short[] getShorts (IndexReader reader, String field) throws IOException {
+    return getShorts(reader, field, SHORT_PARSER);
+  }
+
+  // inherit javadocs
+  public short[] getShorts(IndexReader reader, String field, ShortParser parser)
+      throws IOException {
+    return (short[]) shortsCache.get(reader, new Entry(field, parser));
+  }
 
+  Cache shortsCache = new Cache() {
+
+    protected Object createValue(IndexReader reader, Object entryKey)
+        throws IOException {
+      Entry entry = (Entry) entryKey;
+      String field = entry.field;
+      ShortParser parser = (ShortParser) entry.custom;
+      final short[] retArray = new short[reader.maxDoc()];
+      TermDocs termDocs = reader.termDocs();
+      TermEnum termEnum = reader.terms (new Term (field, ""));
+      try {
+        do {
+          Term term = termEnum.term();
+          if (term==null || term.field() != field) break;
+          short termval = parser.parseShort(term.text());
+          termDocs.seek (termEnum);
+          while (termDocs.next()) {
+            retArray[termDocs.doc()] = termval;
+          }
+        } while (termEnum.next());
+      } finally {
+        termDocs.close();
+        termEnum.close();
+      }
+      return retArray;
+    }
+  };
+  
   // inherit javadocs
   public int[] getInts (IndexReader reader, String field) throws IOException {
     return getInts(reader, field, INT_PARSER);

Added: lucene/java/trunk/src/java/org/apache/lucene/search/function/ByteFieldSource.java
URL: http://svn.apache.org/viewvc/lucene/java/trunk/src/java/org/apache/lucene/search/function/ByteFieldSource.java?view=auto&rev=544546
==============================================================================
--- lucene/java/trunk/src/java/org/apache/lucene/search/function/ByteFieldSource.java (added)
+++ lucene/java/trunk/src/java/org/apache/lucene/search/function/ByteFieldSource.java Tue Jun  5 09:29:35 2007
@@ -0,0 +1,105 @@
+package org.apache.lucene.search.function;
+
+/**
+ * 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.
+ */
+
+import org.apache.lucene.index.IndexReader;
+import org.apache.lucene.search.FieldCache;
+import org.apache.lucene.search.function.DocValues;
+
+import java.io.IOException;
+
+/**
+ * Expert: obtains single byte field values from the 
+ * {@link org.apache.lucene.search.FieldCache FieldCache}
+ * using <code>getBytes()</code> and makes those values 
+ * available as other numeric types, casting as needed.
+ * 
+ * <p><font color="#FF0000">
+ * WARNING: The status of the <b>search.function</b> package is experimental. 
+ * The APIs introduced here might change in the future and will not be 
+ * supported anymore in such a case.</font>
+ * 
+ * @see org.apache.lucene.search.function.FieldCacheSource for requirements 
+ * on the field. 
+ */
+public class ByteFieldSource extends FieldCacheSource {
+  private FieldCache.ByteParser parser;
+
+  /**
+   * Create a cached byte field source with default string-to-byte parser. 
+   */
+  public ByteFieldSource(String field) {
+    this(field, null);
+  }
+
+  /**
+   * Create a cached byte field source with a specific string-to-byte parser. 
+   */
+  public ByteFieldSource(String field, FieldCache.ByteParser parser) {
+    super(field);
+    this.parser = parser;
+  }
+
+  /*(non-Javadoc) @see org.apache.lucene.search.function.ValueSource#description() */
+  public String description() {
+    return "byte(" + super.description() + ')';
+  }
+
+  /*(non-Javadoc) @see org.apache.lucene.search.function.FieldCacheSource#getCachedValues(org.apache.lucene.search.FieldCache, java.lang.String, org.apache.lucene.index.IndexReader) */
+  public DocValues getCachedFieldValues (FieldCache cache, String field, IndexReader reader) throws IOException {
+    final byte[] arr = (parser==null) ?  
+      cache.getBytes(reader, field) : 
+      cache.getBytes(reader, field, parser);
+    return new DocValues(reader.maxDoc()) {
+      /*(non-Javadoc) @see org.apache.lucene.search.function.DocValues#floatVal(int) */
+      public float floatVal(int doc) { 
+        return (float) arr[doc]; 
+      }
+      /*(non-Javadoc) @see org.apache.lucene.search.function.DocValues#intVal(int) */
+      public  int intVal(int doc) { 
+        return arr[doc]; 
+      }
+      /*(non-Javadoc) @see org.apache.lucene.search.function.DocValues#toString(int) */
+      public String toString(int doc) { 
+        return  description() + '=' + intVal(doc);  
+      }
+      /*(non-Javadoc) @see org.apache.lucene.search.function.DocValues#getInnerArray() */
+      Object getInnerArray() {
+        return arr;
+      }
+    };
+  }
+
+  /*(non-Javadoc) @see org.apache.lucene.search.function.FieldCacheSource#cachedFieldSourceEquals(org.apache.lucene.search.function.FieldCacheSource) */
+  public boolean cachedFieldSourceEquals(FieldCacheSource o) {
+    if (o.getClass() !=  ByteFieldSource.class) {
+      return false;
+    }
+    ByteFieldSource other = (ByteFieldSource)o;
+    return this.parser==null ? 
+      other.parser==null :
+      this.parser.getClass() == other.parser.getClass();
+  }
+
+  /*(non-Javadoc) @see org.apache.lucene.search.function.FieldCacheSource#cachedFieldSourceHashCode() */
+  public int cachedFieldSourceHashCode() {
+    return parser==null ? 
+      Byte.class.hashCode() : parser.getClass().hashCode();
+  }
+
+}

Propchange: lucene/java/trunk/src/java/org/apache/lucene/search/function/ByteFieldSource.java
------------------------------------------------------------------------------
    svn:eol-style = native

Added: lucene/java/trunk/src/java/org/apache/lucene/search/function/CustomScoreQuery.java
URL: http://svn.apache.org/viewvc/lucene/java/trunk/src/java/org/apache/lucene/search/function/CustomScoreQuery.java?view=auto&rev=544546
==============================================================================
--- lucene/java/trunk/src/java/org/apache/lucene/search/function/CustomScoreQuery.java (added)
+++ lucene/java/trunk/src/java/org/apache/lucene/search/function/CustomScoreQuery.java Tue Jun  5 09:29:35 2007
@@ -0,0 +1,344 @@
+package org.apache.lucene.search.function;
+
+/**
+ * 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.
+ */
+
+import java.io.IOException;
+import java.util.Set;
+
+import org.apache.lucene.index.IndexReader;
+import org.apache.lucene.search.ComplexExplanation;
+import org.apache.lucene.search.Explanation;
+import org.apache.lucene.search.Query;
+import org.apache.lucene.search.Scorer;
+import org.apache.lucene.search.Searcher;
+import org.apache.lucene.search.Similarity;
+import org.apache.lucene.search.Weight;
+import org.apache.lucene.util.ToStringUtils;
+
+/**
+ * Query that sets document score as a programmatic function of (up to) two (sub) scores.
+ * <ol>
+ *    <li>the score of its subQuery (any query)</li>
+ *    <li>(optional) the score of its ValueSourtceQuery,
+ *        for most simple/convineient use case this query would be a 
+ *        {@link org.apache.lucene.search.function.FieldScoreQuery FieldScoreQuery}</li>
+ * </ol>
+ * Subclasses can modify the computation by overriding {@link #customScore(int, float, float)}.
+ * 
+ * <p><font color="#FF0000">
+ * WARNING: The status of the <b>search.function</b> package is experimental. 
+ * The APIs introduced here might change in the future and will not be 
+ * supported anymore in such a case.</font>
+ */
+public class CustomScoreQuery extends Query {
+
+  private Query subQuery;
+  private ValueSourceQuery valSrcQuery; // optional, can be null
+  private boolean strict = false; // if true, valueSource part of query does not take part in weights normalization.  
+  
+  /**
+   * Create a CustomScoreQuery over input subQuery.
+   * @param subQuery the sub query whose scored is being customed. Must not be null. 
+   */
+  public CustomScoreQuery(Query subQuery) {
+    this(subQuery,null);
+  }
+
+  /**
+   * Create a CustomScoreQuery over input subQuery and a {@link ValueSourceQuery}.
+   * @param subQuery the sub query whose score is being customed. Must not be null.
+   * @param valSrcQuery a value source query whose scores are used in the custom score
+   * computation. For most simple/convineient use case this would be a 
+   * {@link org.apache.lucene.search.function.FieldScoreQuery FieldScoreQuery}.
+   * This parameter is optional - it can be null.
+   */
+  public CustomScoreQuery(Query subQuery, ValueSourceQuery valSrcQuery) {
+    super();
+    this.subQuery = subQuery;
+    this.valSrcQuery = valSrcQuery;
+    if (subQuery == null) throw new IllegalArgumentException("<subqyery> must not be null!");
+  }
+
+  /*(non-Javadoc) @see org.apache.lucene.search.Query#rewrite(org.apache.lucene.index.IndexReader) */
+  public Query rewrite(IndexReader reader) throws IOException {
+    subQuery = subQuery.rewrite(reader);
+    if (valSrcQuery!=null) {
+      valSrcQuery = (ValueSourceQuery) valSrcQuery.rewrite(reader);
+    }
+    return this;
+  }
+
+  /*(non-Javadoc) @see org.apache.lucene.search.Query#extractTerms(java.util.Set) */
+  public void extractTerms(Set terms) {
+    subQuery.extractTerms(terms);
+    if (valSrcQuery!=null) {
+      valSrcQuery.extractTerms(terms);
+    }
+  }
+
+  /*(non-Javadoc) @see org.apache.lucene.search.Query#clone() */
+  public Object clone() {
+    CustomScoreQuery clone = (CustomScoreQuery)super.clone();
+    clone.subQuery = (Query) subQuery.clone();
+    if (valSrcQuery!=null) {
+      clone.valSrcQuery = (ValueSourceQuery) valSrcQuery.clone();
+    }
+    return clone;
+  }
+
+  /* (non-Javadoc) @see org.apache.lucene.search.Query#toString(java.lang.String) */
+  public String toString(String field) {
+    StringBuffer sb = new StringBuffer(name()).append("(");
+    sb.append(subQuery.toString(field));
+    if (valSrcQuery!=null) {
+      sb.append(", ").append(valSrcQuery.toString(field));
+    }
+    sb.append(")");
+    sb.append(strict?" STRICT" : "");
+    return sb.toString() + ToStringUtils.boost(getBoost());
+  }
+
+  /** Returns true if <code>o</code> is equal to this. */
+  public boolean equals(Object o) {
+    if (getClass() != o.getClass()) {
+      return false;
+    }
+    CustomScoreQuery other = (CustomScoreQuery)o;
+    return this.getBoost() == other.getBoost()
+           && this.subQuery.equals(other.subQuery)
+           && (this.valSrcQuery==null ? other.valSrcQuery==null 
+               : this.valSrcQuery.equals(other.valSrcQuery));
+  }
+
+  /** Returns a hash code value for this object. */
+  public int hashCode() {
+    int valSrcHash = valSrcQuery==null ? 0 : valSrcQuery.hashCode();
+    return (getClass().hashCode() + subQuery.hashCode() + valSrcHash) ^ Float.floatToIntBits(getBoost());
+  }  
+  
+  /**
+   * Compute a custom score by the subQuery score and the ValueSourceQuery score.
+   * <p> 
+   * Subclasses can override this method to modify the custom score.
+   * <p>
+   * The default computation herein is:
+   * <pre>
+   *     ModifiedScore = valSrcScore * subQueryScore.
+   * </pre>
+   * 
+   * @param doc id of scored doc. 
+   * @param subQueryScore score of that doc by the subQuery.
+   * @param valSrcScore score of that doc by the ValueSourceQuery.
+   * @return custom score.
+   */
+  public float customScore(int doc, float subQueryScore, float valSrcScore) {
+    return valSrcScore * subQueryScore;
+  }
+
+  /**
+   * Explain the custom score.
+   * Whenever overriding {@link #customScore(int, float, float)}, 
+   * this method should also be overriden to provide the correct explanation
+   * for the part of the custom scoring. 
+   * @param doc doc being explained.
+   * @param subQueryExpl explanation for the sub-query part.
+   * @param valSrcExpl explanation for the value source part.
+   * @return an explanation for the custom score
+   */
+  public Explanation customExplain(int doc, Explanation subQueryExpl, Explanation valSrcExpl) {
+    float valSrcScore = valSrcExpl==null ? 1 : valSrcExpl.getValue();
+    Explanation exp = new Explanation( valSrcScore * subQueryExpl.getValue(), "custom score: product of:");
+    exp.addDetail(subQueryExpl);
+    if (valSrcExpl != null) {
+      exp.addDetail(valSrcExpl);
+    }
+    return exp;
+  }
+  //=========================== W E I G H T ============================
+  
+  private class CustomWeight implements Weight {
+    Searcher searcher;
+    Weight subQueryWeight;
+    Weight valSrcWeight; // optional
+    boolean qStrict;
+
+    public CustomWeight(Searcher searcher) throws IOException {
+      this.searcher = searcher;
+      this.subQueryWeight = subQuery.weight(searcher); 
+      if (valSrcQuery!=null) {
+        this.valSrcWeight = valSrcQuery.createWeight(searcher);
+      }
+      this.qStrict = strict;
+    }
+
+    /*(non-Javadoc) @see org.apache.lucene.search.Weight#getQuery() */
+    public Query getQuery() {
+      return CustomScoreQuery.this;
+    }
+
+    /*(non-Javadoc) @see org.apache.lucene.search.Weight#getValue() */
+    public float getValue() {
+      return getBoost();
+    }
+
+    /*(non-Javadoc) @see org.apache.lucene.search.Weight#sumOfSquaredWeights() */
+    public float sumOfSquaredWeights() throws IOException {
+      float sum = subQueryWeight.sumOfSquaredWeights();
+      if (valSrcWeight!=null) {
+        if (qStrict) {
+          valSrcWeight.sumOfSquaredWeights(); // do not include ValueSource part in the query normalization
+        } else {
+          sum += valSrcWeight.sumOfSquaredWeights();
+        }
+      }
+      sum *= getBoost() * getBoost(); // boost each sub-weight
+      return sum ;
+    }
+
+    /*(non-Javadoc) @see org.apache.lucene.search.Weight#normalize(float) */
+    public void normalize(float norm) {
+      norm *= getBoost(); // incorporate boost
+      subQueryWeight.normalize(norm);
+      if (valSrcWeight!=null) {
+        if (qStrict) {
+          valSrcWeight.normalize(1); // do not normalize the ValueSource part
+        } else {
+          valSrcWeight.normalize(norm);
+        }
+      }
+    }
+
+    /*(non-Javadoc) @see org.apache.lucene.search.Weight#scorer(org.apache.lucene.index.IndexReader) */
+    public Scorer scorer(IndexReader reader) throws IOException {
+      Scorer subQueryScorer = subQueryWeight.scorer(reader);
+      Scorer valSrcScorer = (valSrcWeight==null ? null : valSrcWeight.scorer(reader));
+      return new CustomScorer(getSimilarity(searcher), reader, this, subQueryScorer, valSrcScorer);
+    }
+
+    /*(non-Javadoc) @see org.apache.lucene.search.Weight#explain(org.apache.lucene.index.IndexReader, int) */
+    public Explanation explain(IndexReader reader, int doc) throws IOException {
+      return scorer(reader).explain(doc);
+    }
+  }
+
+
+  //=========================== S C O R E R ============================
+  
+  /**
+   * A scorer that applies a (callback) function on scores of the subQuery.
+   */
+  private class CustomScorer extends Scorer {
+    private final CustomWeight weight;
+    private final float qWeight;
+    private Scorer subQueryScorer;
+    private Scorer valSrcScorer; // optional
+    private IndexReader reader;
+
+    // constructor
+    private CustomScorer(Similarity similarity, IndexReader reader, CustomWeight w,
+        Scorer subQueryScorer, Scorer valSrcScorer) throws IOException {
+      super(similarity);
+      this.weight = w;
+      this.qWeight = w.getValue();
+      this.subQueryScorer = subQueryScorer;
+      this.valSrcScorer = valSrcScorer;
+      this.reader = reader;
+    }
+
+    /*(non-Javadoc) @see org.apache.lucene.search.Scorer#next() */
+    public boolean next() throws IOException {
+      boolean hasNext = subQueryScorer.next();
+      if (valSrcScorer!=null && hasNext) {
+        valSrcScorer.skipTo(subQueryScorer.doc());
+      }
+      return hasNext;
+    }
+
+    /*(non-Javadoc) @see org.apache.lucene.search.Scorer#doc() */
+    public int doc() {
+      return subQueryScorer.doc();
+    }
+
+    /*(non-Javadoc) @see org.apache.lucene.search.Scorer#score() */
+    public float score() throws IOException {
+      float valSrcScore = (valSrcScorer==null ? 1 : valSrcScorer.score());
+      return qWeight * customScore(subQueryScorer.doc(), subQueryScorer.score(), valSrcScore);
+    }
+
+    /*(non-Javadoc) @see org.apache.lucene.search.Scorer#skipTo(int) */
+    public boolean skipTo(int target) throws IOException {
+      boolean hasNext = subQueryScorer.skipTo(target);
+      if (valSrcScorer!=null && hasNext) {
+        valSrcScorer.skipTo(subQueryScorer.doc());
+      }
+      return hasNext;
+    }
+
+    /*(non-Javadoc) @see org.apache.lucene.search.Scorer#explain(int) */
+    public Explanation explain(int doc) throws IOException {
+      Explanation subQueryExpl = weight.subQueryWeight.explain(reader,doc);
+      if (!subQueryExpl.isMatch()) {
+        return subQueryExpl;
+      }
+      // match
+      Explanation valSrcExpl = valSrcScorer==null ? null : valSrcScorer.explain(doc);
+      Explanation customExp = customExplain(doc,subQueryExpl,valSrcExpl);
+      float sc = qWeight * customExp.getValue();
+      Explanation res = new ComplexExplanation(
+        true, sc, CustomScoreQuery.this.toString() + ", product of:");
+      res.addDetail(customExp);
+      res.addDetail(new Explanation(qWeight, "queryBoost")); // actually using the q boost as q weight (== weight value)
+      return res;
+    }
+  }
+
+  /*(non-Javadoc) @see org.apache.lucene.search.Query#createWeight(org.apache.lucene.search.Searcher) */
+  protected Weight createWeight(Searcher searcher) throws IOException {
+    return new CustomWeight(searcher);
+  }
+
+  /**
+   * Checks if this is strict custom scoring.
+   * In strict custom scoring, the ValueSource part of does not participate in weight normalization.
+   * This may be useful when one wants full control over how scores are modified, and does 
+   * not care about normalizing by the ValueSource part.
+   * One particular case where this is useful if for testing this query.   
+   * <P>
+   * Note: only has effect when the ValueSource part is not null.
+   */
+  public boolean isStrict() {
+    return strict;
+  }
+
+  /**
+   * Set the strict mode of this query. 
+   * @param strict The strict mode to set.
+   * @see #isStrict()
+   */
+  public void setStrict(boolean strict) {
+    this.strict = strict;
+  }
+
+  /**
+   * A short name of this query, used in {@link #toString(String)}.
+   */
+  public String name() {
+    return "custom";
+  }
+
+}

Propchange: lucene/java/trunk/src/java/org/apache/lucene/search/function/CustomScoreQuery.java
------------------------------------------------------------------------------
    svn:eol-style = native

Propchange: lucene/java/trunk/src/java/org/apache/lucene/search/function/CustomScoreQuery.java
------------------------------------------------------------------------------
    svn:executable = *

Added: lucene/java/trunk/src/java/org/apache/lucene/search/function/DocValues.java
URL: http://svn.apache.org/viewvc/lucene/java/trunk/src/java/org/apache/lucene/search/function/DocValues.java?view=auto&rev=544546
==============================================================================
--- lucene/java/trunk/src/java/org/apache/lucene/search/function/DocValues.java (added)
+++ lucene/java/trunk/src/java/org/apache/lucene/search/function/DocValues.java Tue Jun  5 09:29:35 2007
@@ -0,0 +1,176 @@
+package org.apache.lucene.search.function;
+
+/**
+ * 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.
+ */
+
+import org.apache.lucene.search.Explanation;
+
+/**
+ * Expert: represents field values as different types.
+ * Normally created via a 
+ * {@link org.apache.lucene.search.function.ValueSource ValueSuorce} 
+ * for a particular field and reader.
+ *
+ * <p><font color="#FF0000">
+ * WARNING: The status of the <b>search.function</b> package is experimental. 
+ * The APIs introduced here might change in the future and will not be 
+ * supported anymore in such a case.</font>
+ * 
+ * @author yonik
+ */
+public abstract class DocValues {
+  /*
+   * DocValues is distinct from ValueSource because
+   * there needs to be an object created at query evaluation time that
+   * is not referenced by the query itself because:
+   * - Query objects should be MT safe
+   * - For caching, Query objects are often used as keys... you don't
+   *   want the Query carrying around big objects
+   */
+
+  private int nVals;
+  
+  /**
+   * Constructor with input number of values(docs).
+   * @param nVals
+   */
+  public DocValues (int nVals) {
+    this.nVals = nVals;
+  }
+  
+  // prevent using this constructor
+  private DocValues () {
+    
+  }
+  /**
+   * Return doc value as a float. 
+   * <P>Mandatory: every DocValues implementation must implement at least this method. 
+   * @param doc document whose float value is requested. 
+   */
+  public abstract float floatVal(int doc);
+  
+  /**
+   * Return doc value as an int. 
+   * <P>Optional: DocValues implementation can (but don't have to) override this method. 
+   * @param doc document whose int value is requested.
+   */
+  public int intVal(int doc) { 
+    return (int) floatVal(doc);
+  }
+  
+  /**
+   * Return doc value as a long. 
+   * <P>Optional: DocValues implementation can (but don't have to) override this method. 
+   * @param doc document whose long value is requested.
+   */
+  public long longVal(int doc) {
+    return (long) floatVal(doc);
+  }
+
+  /**
+   * Return doc value as a double. 
+   * <P>Optional: DocValues implementation can (but don't have to) override this method. 
+   * @param doc document whose double value is requested.
+   */
+  public double doubleVal(int doc) {
+    return (double) floatVal(doc);
+  }
+  
+  /**
+   * Return doc value as a string. 
+   * <P>Optional: DocValues implementation can (but don't have to) override this method. 
+   * @param doc document whose string value is requested.
+   */
+  public String strVal(int doc) {
+    return Float.toString(floatVal(doc));
+  }
+  
+  /**
+   * Return a string representation of a doc value, as reuired for Explanations.
+   */
+  public abstract String toString(int doc);
+  
+  /**
+   * Explain the scoring value for the input doc.
+   */
+  public Explanation explain(int doc) {
+    return new Explanation(floatVal(doc), toString(doc));
+  }
+  
+  /**
+   * Expert: for test purposes only, return the inner array of values, or null if not applicable.
+   * <p>
+   * Allows tests to verify that loaded values are:
+   * <ol>
+   *   <li>indeed cached/reused.</li>
+   *   <li>stored in the expected size/type (byte/short/int/float).</li>
+   * </ol>
+   * Note: Tested implementations of DocValues must override this method for the test to pass!
+   */
+  Object getInnerArray() {
+    return new Object[0];
+  }
+
+  // --- some simple statistics on values
+  private float minVal;
+  private float maxVal;
+  private float avgVal;
+  private boolean computed=false;
+  // compute optional values
+  private void compute () {
+    if (computed) {
+      return;
+    }
+    minVal = Float.MAX_VALUE;
+    maxVal = 0;
+    float sum = 0;
+    for (int i=0; i<nVals; i++) {
+      float val = floatVal(i); 
+      sum += val;
+      minVal = Math.min(minVal,val);
+      maxVal = Math.max(maxVal,val);
+    }
+    avgVal = sum / nVals;
+    computed = true;
+  }
+  /**
+   * Optional op.
+   * Returns the minimum of all values.
+   */
+  public float getMinValue () {
+    compute();
+    return minVal;
+  }
+  
+  /**
+   * Optional op.
+   * Returns the maximum of all values. 
+   */
+  public float getMaxValue () {
+    compute();
+    return maxVal;
+  }
+  
+  /**
+   * Returns the average of all values. 
+   */
+  public float getAverageValue () {
+    compute();
+    return avgVal;
+  }
+
+}

Propchange: lucene/java/trunk/src/java/org/apache/lucene/search/function/DocValues.java
------------------------------------------------------------------------------
    svn:eol-style = native

Propchange: lucene/java/trunk/src/java/org/apache/lucene/search/function/DocValues.java
------------------------------------------------------------------------------
    svn:executable = *

Added: lucene/java/trunk/src/java/org/apache/lucene/search/function/FieldCacheSource.java
URL: http://svn.apache.org/viewvc/lucene/java/trunk/src/java/org/apache/lucene/search/function/FieldCacheSource.java?view=auto&rev=544546
==============================================================================
--- lucene/java/trunk/src/java/org/apache/lucene/search/function/FieldCacheSource.java (added)
+++ lucene/java/trunk/src/java/org/apache/lucene/search/function/FieldCacheSource.java Tue Jun  5 09:29:35 2007
@@ -0,0 +1,105 @@
+package org.apache.lucene.search.function;
+
+/**
+ * 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.
+ */
+
+import java.io.IOException;
+
+import org.apache.lucene.index.IndexReader;
+import org.apache.lucene.search.FieldCache;
+
+/**
+ * Expert: A base class for ValueSource implementations that retrieve values for
+ * a single field from the {@link org.apache.lucene.search.FieldCache FieldCache}.
+ * <p>
+ * Fields used herein nust be indexed (doesn't matter if these fields are stored or not).
+ * <p> 
+ * It is assumed that each such indexed field is untokenized, or at least has a single token in a document.
+ * For documents with multiple tokens of the same field, behavior is undefined (It is likely that current 
+ * code would use the value of one of these tokens, but this is not guaranteed).
+ * <p>
+ * Document with no tokens in this field are assigned the <code>Zero</code> value.    
+ * 
+ * <p><font color="#FF0000">
+ * WARNING: The status of the <b>search.function</b> package is experimental. 
+ * The APIs introduced here might change in the future and will not be 
+ * supported anymore in such a case.</font>
+ * 
+ * @author yonik
+ */
+public abstract class FieldCacheSource extends ValueSource {
+  private String field;
+  private FieldCache cache = FieldCache.DEFAULT;
+
+  /**
+   * Create a cached field source for the input field.  
+   */
+  public FieldCacheSource(String field) {
+    this.field=field;
+  }
+
+  /* (non-Javadoc) @see org.apache.lucene.search.function.ValueSource#getValues(org.apache.lucene.index.IndexReader) */
+  public final DocValues getValues(IndexReader reader) throws IOException {
+    return getCachedFieldValues(cache, field, reader);
+  }
+
+  /* (non-Javadoc) @see org.apache.lucene.search.function.ValueSource#description() */
+  public String description() {
+    return field;
+  }
+
+  /**
+   * Return cached DocValues for input field and reader.
+   * @param cache FieldCache so that values of a field are loaded once per reader (RAM allowing)
+   * @param field Field for which values are required.
+   * @see ValueSource
+   */
+  public abstract DocValues getCachedFieldValues(FieldCache cache, String field, IndexReader reader) throws IOException;
+
+  /*(non-Javadoc) @see java.lang.Object#equals(java.lang.Object) */
+  public final boolean equals(Object o) {
+    if (!(o instanceof FieldCacheSource)) {
+      return false;
+    }
+    FieldCacheSource other = (FieldCacheSource) o;
+    return 
+      this.cache == other.cache &&
+      this.field.equals(other.field) && 
+      cachedFieldSourceEquals(other);
+  }
+
+  /*(non-Javadoc) @see java.lang.Object#hashCode() */
+  public final int hashCode() {
+    return 
+      cache.hashCode() + 
+      field.hashCode() +
+      cachedFieldSourceHashCode();
+  }
+
+  /**
+   * Check if equals to another {@link FieldCacheSource}, already knowing that cache and field are equal.  
+   * @see Object#equals(java.lang.Object)
+   */
+  public abstract boolean cachedFieldSourceEquals(FieldCacheSource other);
+
+  /**
+   * Return a hash code of a {@link FieldCacheSource}, without the hash-codes of the field 
+   * and the cache (those are taken care of elsewhere).  
+   * @see Object#hashCode()
+   */
+  public abstract int cachedFieldSourceHashCode();
+}

Propchange: lucene/java/trunk/src/java/org/apache/lucene/search/function/FieldCacheSource.java
------------------------------------------------------------------------------
    svn:eol-style = native

Added: lucene/java/trunk/src/java/org/apache/lucene/search/function/FieldScoreQuery.java
URL: http://svn.apache.org/viewvc/lucene/java/trunk/src/java/org/apache/lucene/search/function/FieldScoreQuery.java?view=auto&rev=544546
==============================================================================
--- lucene/java/trunk/src/java/org/apache/lucene/search/function/FieldScoreQuery.java (added)
+++ lucene/java/trunk/src/java/org/apache/lucene/search/function/FieldScoreQuery.java Tue Jun  5 09:29:35 2007
@@ -0,0 +1,127 @@
+package org.apache.lucene.search.function;
+
+/**
+ * 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.
+ */
+
+/**
+ * A query that scores each document as the value of the numeric input field.
+ * <p> 
+ * The query matches all documents, and scores each document according to the numeric 
+ * value of that field. 
+ * <p>
+ * It is assumed, and expected, that:
+ * <ul>
+ *  <li>The field used here is indexed, and has exactly 
+ *      one token in every scored document.</li> 
+ *  <li>Best if this field is un_tokenized.</li>
+ *  <li>That token is parsable to the selected type.</li>
+ * </ul>
+ * <p>  
+ * Combining this query in a FunctionQuery allows much freedom in affecting document scores.
+ * Note, that with this freedom comes responsibility: it is more than likely that the
+ * default Lucene scoring is superior in quality to scoring modified as explained here.
+ * However, in some cases, and certainly for research experiments, this capability may turn useful.
+ * <p>
+ * When contructing this query, select the appropriate type. That type should match the data stored in the
+ * field. So in fact the "right" type should be selected before indexing. Type selection
+ * has effect on the RAM usage: 
+ * <ul>
+ *   <li>{@link Type#BYTE} consumes 1 * maxDocs bytes.</li>
+ *   <li>{@link Type#SHORT} consumes 2 * maxDocs bytes.</li>
+ *   <li>{@link Type#INT} consumes 4 * maxDocs bytes.</li>
+ *   <li>{@link Type#FLOAT} consumes 8 * maxDocs bytes.</li>
+ * </ul>
+ * <p>
+ * <b>Caching:</b>
+ * Values for the numeric field are loaded once and cached in memory for further use with the same IndexReader. 
+ * To take advantage of this, it is extremely important to reuse index-readers or index-searchers, 
+ * otherwise, for instance if for each query a new index reader is opened, large penalties would be 
+ * payd for loading the field values into memory over and over again!
+ * 
+ * <p><font color="#FF0000">
+ * WARNING: The status of the <b>search.function</b> package is experimental. 
+ * The APIs introduced here might change in the future and will not be 
+ * supported anymore in such a case.</font>
+ */
+public class FieldScoreQuery extends ValueSourceQuery {
+
+  /**
+   * Type of score field, indicating how field values are interpreted/parsed.  
+   * <p>
+   * The type selected at search search time should match the data stored in the field. 
+   * Different types have different RAM requirements: 
+   * <ul>
+   *   <li>{@link #BYTE} consumes 1 * maxDocs bytes.</li>
+   *   <li>{@link #SHORT} consumes 2 * maxDocs bytes.</li>
+   *   <li>{@link #INT} consumes 4 * maxDocs bytes.</li>
+   *   <li>{@link #FLOAT} consumes 8 * maxDocs bytes.</li>
+   * </ul>
+   */
+  public static class Type {
+    
+    /** field values are interpreted as numeric byte values. */
+    public static final Type BYTE = new Type("byte"); 
+
+    /** field values are interpreted as numeric short values. */
+    public static final Type SHORT = new Type("short"); 
+
+    /** field values are interpreted as numeric int values. */
+    public static final Type INT = new Type("int"); 
+
+    /** field values are interpreted as numeric float values. */
+    public static final Type FLOAT = new Type("float"); 
+
+    private String typeName;
+    private Type (String name) {
+      this.typeName = name;
+    }
+    /*(non-Javadoc) @see java.lang.Object#toString() */
+    public String toString() {
+      return getClass().getName()+"::"+typeName;
+    }
+  }
+  
+  /**
+   * Create a FieldScoreQuery - a query that scores each document as the value of the numeric input field.
+   * <p>
+   * The <code>type</code> param tells how to parse the field string values into a numeric score value.
+   * @param field the numeric field to be used.
+   * @param type the type of the field: either
+   * {@link Type#BYTE}, {@link Type#SHORT}, {@link Type#INT}, or {@link Type#FLOAT}. 
+   */
+  public FieldScoreQuery(String field, Type type) {
+    super(getValueSource(field,type));
+  }
+
+  // create the appropriate (cached) field value source.  
+  private static ValueSource getValueSource(String field, Type type) {
+    if (type == Type.BYTE) {
+      return new ByteFieldSource(field);
+    }
+    if (type == Type.SHORT) {
+      return new ShortFieldSource(field);
+    }
+    if (type == Type.INT) {
+      return new IntFieldSource(field);
+    }
+    if (type == Type.FLOAT) {
+      return new FloatFieldSource(field);
+    }
+    throw new IllegalArgumentException(type+" is not a known Field Score Query Type!");
+  }
+
+}

Propchange: lucene/java/trunk/src/java/org/apache/lucene/search/function/FieldScoreQuery.java
------------------------------------------------------------------------------
    svn:eol-style = native

Propchange: lucene/java/trunk/src/java/org/apache/lucene/search/function/FieldScoreQuery.java
------------------------------------------------------------------------------
    svn:executable = *

Added: lucene/java/trunk/src/java/org/apache/lucene/search/function/FloatFieldSource.java
URL: http://svn.apache.org/viewvc/lucene/java/trunk/src/java/org/apache/lucene/search/function/FloatFieldSource.java?view=auto&rev=544546
==============================================================================
--- lucene/java/trunk/src/java/org/apache/lucene/search/function/FloatFieldSource.java (added)
+++ lucene/java/trunk/src/java/org/apache/lucene/search/function/FloatFieldSource.java Tue Jun  5 09:29:35 2007
@@ -0,0 +1,102 @@
+package org.apache.lucene.search.function;
+
+/**
+ * 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.
+ */
+
+import org.apache.lucene.index.IndexReader;
+import org.apache.lucene.search.FieldCache;
+import org.apache.lucene.search.function.DocValues;
+
+import java.io.IOException;
+
+/**
+ * Expert: obtains float field values from the 
+ * {@link org.apache.lucene.search.FieldCache FieldCache}
+ * using <code>getFloats()</code> and makes those values 
+ * available as other numeric types, casting as needed.
+ * 
+ * <p><font color="#FF0000">
+ * WARNING: The status of the <b>search.function</b> package is experimental. 
+ * The APIs introduced here might change in the future and will not be 
+ * supported anymore in such a case.</font>
+ * 
+ * @see org.apache.lucene.search.function.FieldCacheSource for requirements 
+ * on the field.
+ *  
+ * @author yonik
+ */
+public class FloatFieldSource extends FieldCacheSource {
+  private FieldCache.FloatParser parser;
+
+  /**
+   * Create a cached float field source with default string-to-float parser. 
+   */
+  public FloatFieldSource(String field) {
+    this(field, null);
+  }
+
+  /**
+   * Create a cached float field source with a specific string-to-float parser. 
+   */
+  public FloatFieldSource(String field, FieldCache.FloatParser parser) {
+    super(field);
+    this.parser = parser;
+  }
+
+  /*(non-Javadoc) @see org.apache.lucene.search.function.ValueSource#description() */
+  public String description() {
+    return "float(" + super.description() + ')';
+  }
+
+  /*(non-Javadoc) @see org.apache.lucene.search.function.FieldCacheSource#getCachedValues(org.apache.lucene.search.FieldCache, java.lang.String, org.apache.lucene.index.IndexReader) */
+  public DocValues getCachedFieldValues (FieldCache cache, String field, IndexReader reader) throws IOException {
+    final float[] arr = (parser==null) ?
+      cache.getFloats(reader, field) :
+      cache.getFloats(reader, field, parser);
+    return new DocValues(reader.maxDoc()) {
+      /*(non-Javadoc) @see org.apache.lucene.search.function.DocValues#floatVal(int) */
+      public float floatVal(int doc) {
+        return arr[doc];      
+      }
+      /*(non-Javadoc) @see org.apache.lucene.search.function.DocValues#toString(int) */
+      public String toString(int doc) { 
+        return  description() + '=' + arr[doc];  
+      }
+      /*(non-Javadoc) @see org.apache.lucene.search.function.DocValues#getInnerArray() */
+      Object getInnerArray() {
+        return arr;
+      }
+    };
+  }
+
+  /*(non-Javadoc) @see org.apache.lucene.search.function.FieldCacheSource#cachedFieldSourceEquals(org.apache.lucene.search.function.FieldCacheSource) */
+  public boolean cachedFieldSourceEquals(FieldCacheSource o) {
+    if (o.getClass() !=  FloatFieldSource.class) {
+      return false;
+    }
+    FloatFieldSource other = (FloatFieldSource)o;
+    return this.parser==null ? 
+      other.parser==null :
+      this.parser.getClass() == other.parser.getClass();
+  }
+
+  /*(non-Javadoc) @see org.apache.lucene.search.function.FieldCacheSource#cachedFieldSourceHashCode() */
+  public int cachedFieldSourceHashCode() {
+    return parser==null ? 
+      Float.class.hashCode() : parser.getClass().hashCode();
+  }
+}
\ No newline at end of file

Propchange: lucene/java/trunk/src/java/org/apache/lucene/search/function/FloatFieldSource.java
------------------------------------------------------------------------------
    svn:eol-style = native

Added: lucene/java/trunk/src/java/org/apache/lucene/search/function/IntFieldSource.java
URL: http://svn.apache.org/viewvc/lucene/java/trunk/src/java/org/apache/lucene/search/function/IntFieldSource.java?view=auto&rev=544546
==============================================================================
--- lucene/java/trunk/src/java/org/apache/lucene/search/function/IntFieldSource.java (added)
+++ lucene/java/trunk/src/java/org/apache/lucene/search/function/IntFieldSource.java Tue Jun  5 09:29:35 2007
@@ -0,0 +1,107 @@
+package org.apache.lucene.search.function;
+
+/**
+ * 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.
+ */
+
+import org.apache.lucene.index.IndexReader;
+import org.apache.lucene.search.FieldCache;
+import org.apache.lucene.search.function.DocValues;
+
+import java.io.IOException;
+
+/**
+ * Expert: obtains int field values from the 
+ * {@link org.apache.lucene.search.FieldCache FieldCache}
+ * using <code>getInts()</code> and makes those values 
+ * available as other numeric types, casting as needed.
+ * 
+ * <p><font color="#FF0000">
+ * WARNING: The status of the <b>search.function</b> package is experimental. 
+ * The APIs introduced here might change in the future and will not be 
+ * supported anymore in such a case.</font>
+ * 
+ * @see org.apache.lucene.search.function.FieldCacheSource for requirements 
+ * on the field.
+ *
+ * @author yonik
+ */
+public class IntFieldSource extends FieldCacheSource {
+  private FieldCache.IntParser parser;
+
+  /**
+   * Create a cached int field source with default string-to-int parser. 
+   */
+  public IntFieldSource(String field) {
+    this(field, null);
+  }
+
+  /**
+   * Create a cached int field source with a specific string-to-int parser. 
+   */
+  public IntFieldSource(String field, FieldCache.IntParser parser) {
+    super(field);
+    this.parser = parser;
+  }
+
+  /*(non-Javadoc) @see org.apache.lucene.search.function.ValueSource#description() */
+  public String description() {
+    return "int(" + super.description() + ')';
+  }
+
+  /*(non-Javadoc) @see org.apache.lucene.search.function.FieldCacheSource#getCachedValues(org.apache.lucene.search.FieldCache, java.lang.String, org.apache.lucene.index.IndexReader) */
+  public DocValues getCachedFieldValues (FieldCache cache, String field, IndexReader reader) throws IOException {
+    final int[] arr = (parser==null) ?  
+      cache.getInts(reader, field) : 
+      cache.getInts(reader, field, parser);
+    return new DocValues(reader.maxDoc()) {
+      /*(non-Javadoc) @see org.apache.lucene.search.function.DocValues#floatVal(int) */
+      public float floatVal(int doc) { 
+        return (float) arr[doc]; 
+      }
+      /*(non-Javadoc) @see org.apache.lucene.search.function.DocValues#intVal(int) */
+      public  int intVal(int doc) { 
+        return arr[doc]; 
+      }
+      /*(non-Javadoc) @see org.apache.lucene.search.function.DocValues#toString(int) */
+      public String toString(int doc) { 
+        return  description() + '=' + intVal(doc);  
+      }
+      /*(non-Javadoc) @see org.apache.lucene.search.function.DocValues#getInnerArray() */
+      Object getInnerArray() {
+        return arr;
+      }
+    };
+  }
+
+  /*(non-Javadoc) @see org.apache.lucene.search.function.FieldCacheSource#cachedFieldSourceEquals(org.apache.lucene.search.function.FieldCacheSource) */
+  public boolean cachedFieldSourceEquals(FieldCacheSource o) {
+    if (o.getClass() !=  IntFieldSource.class) {
+      return false;
+    }
+    IntFieldSource other = (IntFieldSource)o;
+    return this.parser==null ? 
+      other.parser==null :
+      this.parser.getClass() == other.parser.getClass();
+  }
+
+  /*(non-Javadoc) @see org.apache.lucene.search.function.FieldCacheSource#cachedFieldSourceHashCode() */
+  public int cachedFieldSourceHashCode() {
+    return parser==null ? 
+      Integer.class.hashCode() : parser.getClass().hashCode();
+  }
+
+}

Propchange: lucene/java/trunk/src/java/org/apache/lucene/search/function/IntFieldSource.java
------------------------------------------------------------------------------
    svn:eol-style = native

Propchange: lucene/java/trunk/src/java/org/apache/lucene/search/function/IntFieldSource.java
------------------------------------------------------------------------------
    svn:executable = *

Added: lucene/java/trunk/src/java/org/apache/lucene/search/function/OrdFieldSource.java
URL: http://svn.apache.org/viewvc/lucene/java/trunk/src/java/org/apache/lucene/search/function/OrdFieldSource.java?view=auto&rev=544546
==============================================================================
--- lucene/java/trunk/src/java/org/apache/lucene/search/function/OrdFieldSource.java (added)
+++ lucene/java/trunk/src/java/org/apache/lucene/search/function/OrdFieldSource.java Tue Jun  5 09:29:35 2007
@@ -0,0 +1,103 @@
+/**
+ * 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.lucene.search.function;
+
+import org.apache.lucene.index.IndexReader;
+import org.apache.lucene.search.FieldCache;
+
+import java.io.IOException;
+
+/**
+ * Expert: obtains the ordinal of the field value from the default Lucene 
+ * {@link org.apache.lucene.search.FieldCache Fieldcache} using getStringIndex().
+ * <p>
+ * The native lucene index order is used to assign an ordinal value for each field value.
+ * <p
+ * Field values (terms) are lexicographically ordered by unicode value, and numbered starting at 1.
+ * <p>
+ * Example:
+ * <br>If there were only three field values: "apple","banana","pear"
+ * <br>then ord("apple")=1, ord("banana")=2, ord("pear")=3
+ * <p>
+ * WARNING: 
+ * ord() depends on the position in an index and can thus change 
+ * when other documents are inserted or deleted,
+ * or if a MultiSearcher is used. 
+ *
+ * <p><font color="#FF0000">
+ * WARNING: The status of the <b>search.function</b> package is experimental. 
+ * The APIs introduced here might change in the future and will not be 
+ * supported anymore in such a case.</font>
+ * 
+ * @author yonik
+ */
+
+public class OrdFieldSource extends ValueSource {
+  protected String field;
+
+  /** 
+   * Contructor for a certain field.
+   * @param field field whose values order is used.  
+   */
+  public OrdFieldSource(String field) {
+    this.field = field;
+  }
+
+  /*(non-Javadoc) @see org.apache.lucene.search.function.ValueSource#description() */
+  public String description() {
+    return "ord(" + field + ')';
+  }
+
+  /*(non-Javadoc) @see org.apache.lucene.search.function.ValueSource#getValues(org.apache.lucene.index.IndexReader) */
+  public DocValues getValues(IndexReader reader) throws IOException {
+    final int[] arr = FieldCache.DEFAULT.getStringIndex(reader, field).order;
+    return new DocValues(arr.length) {
+      /*(non-Javadoc) @see org.apache.lucene.search.function.DocValues#floatVal(int) */
+      public float floatVal(int doc) {
+        return (float)arr[doc];
+      }
+      /*(non-Javadoc) @see org.apache.lucene.search.function.DocValues#strVal(int) */
+      public String strVal(int doc) {
+        // the string value of the ordinal, not the string itself
+        return Integer.toString(arr[doc]);
+      }
+      /*(non-Javadoc) @see org.apache.lucene.search.function.DocValues#toString(int) */
+      public String toString(int doc) {
+        return description() + '=' + intVal(doc);
+      }
+      /*(non-Javadoc) @see org.apache.lucene.search.function.DocValues#getInnerArray() */
+      Object getInnerArray() {
+        return arr;
+      }
+    };
+  }
+
+  /*(non-Javadoc) @see java.lang.Object#equals(java.lang.Object) */
+  public boolean equals(Object o) {
+    if (o.getClass() !=  OrdFieldSource.class) return false;
+    OrdFieldSource other = (OrdFieldSource)o;
+    return this.field.equals(other.field);
+  }
+
+  private static final int hcode = OrdFieldSource.class.hashCode();
+  
+  /*(non-Javadoc) @see java.lang.Object#hashCode() */
+  public int hashCode() {
+    return hcode + field.hashCode();
+  }
+}

Propchange: lucene/java/trunk/src/java/org/apache/lucene/search/function/OrdFieldSource.java
------------------------------------------------------------------------------
    svn:eol-style = native

Added: lucene/java/trunk/src/java/org/apache/lucene/search/function/ReverseOrdFieldSource.java
URL: http://svn.apache.org/viewvc/lucene/java/trunk/src/java/org/apache/lucene/search/function/ReverseOrdFieldSource.java?view=auto&rev=544546
==============================================================================
--- lucene/java/trunk/src/java/org/apache/lucene/search/function/ReverseOrdFieldSource.java (added)
+++ lucene/java/trunk/src/java/org/apache/lucene/search/function/ReverseOrdFieldSource.java Tue Jun  5 09:29:35 2007
@@ -0,0 +1,112 @@
+/**
+ * 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.lucene.search.function;
+
+import org.apache.lucene.index.IndexReader;
+import org.apache.lucene.search.FieldCache;
+
+import java.io.IOException;
+
+/**
+ * Expert: obtains the ordinal of the field value from the default Lucene 
+ * {@link org.apache.lucene.search.FieldCache FieldCache} using getStringIndex()
+ * and reverses the order.
+ * <p>
+ * The native lucene index order is used to assign an ordinal value for each field value.
+ * <p>
+ * Field values (terms) are lexicographically ordered by unicode value, and numbered starting at 1.
+ * <br>
+ * Example of reverse ordinal (rord):
+ * <br>If there were only three field values: "apple","banana","pear"
+ * <br>then rord("apple")=3, rord("banana")=2, ord("pear")=1
+ * <p>
+ * WARNING: 
+ * rord() depends on the position in an index and can thus change 
+ * when other documents are inserted or deleted,
+ * or if a MultiSearcher is used. 
+ * 
+ * <p><font color="#FF0000">
+ * WARNING: The status of the <b>search.function</b> package is experimental. 
+ * The APIs introduced here might change in the future and will not be 
+ * supported anymore in such a case.</font>
+ * 
+ * @author yonik
+ */
+
+public class ReverseOrdFieldSource extends ValueSource {
+  public String field;
+
+  /** 
+   * Contructor for a certain field.
+   * @param field field whose values reverse order is used.  
+   */
+  public ReverseOrdFieldSource(String field) {
+    this.field = field;
+  }
+
+  /*(non-Javadoc) @see org.apache.lucene.search.function.ValueSource#description() */
+  public String description() {
+    return "rord("+field+')';
+  }
+
+  /*(non-Javadoc) @see org.apache.lucene.search.function.ValueSource#getValues(org.apache.lucene.index.IndexReader) */
+  public DocValues getValues(IndexReader reader) throws IOException {
+    final FieldCache.StringIndex sindex = FieldCache.DEFAULT.getStringIndex(reader, field);
+
+    final int arr[] = sindex.order;
+    final int end = sindex.lookup.length;
+
+    return new DocValues(arr.length) {
+      /*(non-Javadoc) @see org.apache.lucene.search.function.DocValues#floatVal(int) */
+      public float floatVal(int doc) {
+        return (float)(end - arr[doc]);
+      }
+      /* (non-Javadoc) @see org.apache.lucene.search.function.DocValues#intVal(int) */
+      public int intVal(int doc) {
+        return end - arr[doc];
+      }
+      /* (non-Javadoc) @see org.apache.lucene.search.function.DocValues#strVal(int) */
+      public String strVal(int doc) {
+        // the string value of the ordinal, not the string itself
+        return Integer.toString(intVal(doc));
+      }
+      /*(non-Javadoc) @see org.apache.lucene.search.function.DocValues#toString(int) */
+      public String toString(int doc) {
+        return description() + '=' + strVal(doc);
+      }
+      /*(non-Javadoc) @see org.apache.lucene.search.function.DocValues#getInnerArray() */
+      Object getInnerArray() {
+        return arr;
+      }
+    };
+  }
+
+  /*(non-Javadoc) @see java.lang.Object#equals(java.lang.Object) */
+  public boolean equals(Object o) {
+    if (o.getClass() !=  ReverseOrdFieldSource.class) return false;
+    ReverseOrdFieldSource other = (ReverseOrdFieldSource)o;
+    return this.field.equals(other.field); 
+  }
+
+  private static final int hcode = ReverseOrdFieldSource.class.hashCode();
+  
+  /*(non-Javadoc) @see java.lang.Object#hashCode() */
+  public int hashCode() {
+    return hcode + field.hashCode();
+  }
+}

Propchange: lucene/java/trunk/src/java/org/apache/lucene/search/function/ReverseOrdFieldSource.java
------------------------------------------------------------------------------
    svn:eol-style = native

Added: lucene/java/trunk/src/java/org/apache/lucene/search/function/ShortFieldSource.java
URL: http://svn.apache.org/viewvc/lucene/java/trunk/src/java/org/apache/lucene/search/function/ShortFieldSource.java?view=auto&rev=544546
==============================================================================
--- lucene/java/trunk/src/java/org/apache/lucene/search/function/ShortFieldSource.java (added)
+++ lucene/java/trunk/src/java/org/apache/lucene/search/function/ShortFieldSource.java Tue Jun  5 09:29:35 2007
@@ -0,0 +1,105 @@
+package org.apache.lucene.search.function;
+
+/**
+ * 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.
+ */
+
+import org.apache.lucene.index.IndexReader;
+import org.apache.lucene.search.FieldCache;
+import org.apache.lucene.search.function.DocValues;
+
+import java.io.IOException;
+
+/**
+ * Expert: obtains short field values from the 
+ * {@link org.apache.lucene.search.FieldCache FieldCache}
+ * using <code>getShorts()</code> and makes those values 
+ * available as other numeric types, casting as needed.
+ * 
+ * <p><font color="#FF0000">
+ * WARNING: The status of the <b>search.function</b> package is experimental. 
+ * The APIs introduced here might change in the future and will not be 
+ * supported anymore in such a case.</font>
+ * 
+ * @see org.apache.lucene.search.function.FieldCacheSource for requirements 
+ * on the field.
+ */
+public class ShortFieldSource extends FieldCacheSource {
+  private FieldCache.ShortParser parser;
+
+  /**
+   * Create a cached short field source with default string-to-short parser. 
+   */
+  public ShortFieldSource(String field) {
+    this(field, null);
+  }
+
+  /**
+   * Create a cached short field source with a specific string-to-short parser. 
+   */
+  public ShortFieldSource(String field, FieldCache.ShortParser parser) {
+    super(field);
+    this.parser = parser;
+  }
+
+  /*(non-Javadoc) @see org.apache.lucene.search.function.ValueSource#description() */
+  public String description() {
+    return "short(" + super.description() + ')';
+  }
+
+  /*(non-Javadoc) @see org.apache.lucene.search.function.FieldCacheSource#getCachedValues(org.apache.lucene.search.FieldCache, java.lang.String, org.apache.lucene.index.IndexReader) */
+  public DocValues getCachedFieldValues (FieldCache cache, String field, IndexReader reader) throws IOException {
+    final short[] arr = (parser==null) ?  
+      cache.getShorts(reader, field) : 
+      cache.getShorts(reader, field, parser);
+    return new DocValues(reader.maxDoc()) {
+      /*(non-Javadoc) @see org.apache.lucene.search.function.DocValues#floatVal(int) */
+      public float floatVal(int doc) { 
+        return (float) arr[doc]; 
+      }
+      /*(non-Javadoc) @see org.apache.lucene.search.function.DocValues#intVal(int) */
+      public  int intVal(int doc) { 
+        return arr[doc]; 
+      }
+      /*(non-Javadoc) @see org.apache.lucene.search.function.DocValues#toString(int) */
+      public String toString(int doc) { 
+        return  description() + '=' + intVal(doc);  
+      }
+      /*(non-Javadoc) @see org.apache.lucene.search.function.DocValues#getInnerArray() */
+      Object getInnerArray() {
+        return arr;
+      }
+    };
+  }
+
+  /*(non-Javadoc) @see org.apache.lucene.search.function.FieldCacheSource#cachedFieldSourceEquals(org.apache.lucene.search.function.FieldCacheSource) */
+  public boolean cachedFieldSourceEquals(FieldCacheSource o) {
+    if (o.getClass() !=  ShortFieldSource.class) {
+      return false;
+    }
+    ShortFieldSource other = (ShortFieldSource)o;
+    return this.parser==null ? 
+      other.parser==null :
+      this.parser.getClass() == other.parser.getClass();
+  }
+
+  /*(non-Javadoc) @see org.apache.lucene.search.function.FieldCacheSource#cachedFieldSourceHashCode() */
+  public int cachedFieldSourceHashCode() {
+    return parser==null ? 
+      Short.class.hashCode() : parser.getClass().hashCode();
+  }
+
+}

Propchange: lucene/java/trunk/src/java/org/apache/lucene/search/function/ShortFieldSource.java
------------------------------------------------------------------------------
    svn:eol-style = native

Added: lucene/java/trunk/src/java/org/apache/lucene/search/function/ValueSource.java
URL: http://svn.apache.org/viewvc/lucene/java/trunk/src/java/org/apache/lucene/search/function/ValueSource.java?view=auto&rev=544546
==============================================================================
--- lucene/java/trunk/src/java/org/apache/lucene/search/function/ValueSource.java (added)
+++ lucene/java/trunk/src/java/org/apache/lucene/search/function/ValueSource.java Tue Jun  5 09:29:35 2007
@@ -0,0 +1,74 @@
+package org.apache.lucene.search.function;
+
+/**
+ * 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.
+ */
+
+import org.apache.lucene.index.IndexReader;
+import org.apache.lucene.search.function.DocValues;
+import org.apache.lucene.util.ToStringUtils;
+
+import java.io.IOException;
+import java.io.Serializable;
+
+/**
+ * Expert: source of values for basic function queries.
+ * <P>At its default/simplest form, values - one per doc - are used as the score of that doc.
+ * <P>Values are instantiated as 
+ * {@link org.apache.lucene.search.function.DocValues DocValues} for a particular reader.
+ * <P>ValueSource implementations differ in RAM requirements: it would always be a factor
+ * of the number of documents, but for each document the number of bytes can be 1, 2, 4, or 8. 
+ *
+ * <p><font color="#FF0000">
+ * WARNING: The status of the <b>search.function</b> package is experimental. 
+ * The APIs introduced here might change in the future and will not be 
+ * supported anymore in such a case.</font>
+ *
+ * @author yonik
+ */
+public abstract class ValueSource implements Serializable {
+
+  /**
+   * Return the DocValues used by the function query.
+   * @param reader the IndexReader used to read these values.
+   * If any caching is involved, that caching would also be IndexReader based.  
+   * @throws IOException for any error.
+   */
+  public abstract DocValues getValues(IndexReader reader) throws IOException;
+
+  /** 
+   * description of field, used in explain() 
+   */
+  public abstract String description();
+
+  /* (non-Javadoc) @see java.lang.Object#toString() */
+  public String toString() {
+    return description();
+  }
+
+  /**
+   * Needed for possible caching of query results - used by {@link ValueSourceQuery#equals(Object)}.
+   * @see Object#equals(Object)
+   */
+  public abstract boolean equals(Object o);
+
+  /**
+   * Needed for possible caching of query results - used by {@link ValueSourceQuery#hashCode()}.
+   * @see Object#hashCode()
+   */
+  public abstract int hashCode();
+  
+}

Propchange: lucene/java/trunk/src/java/org/apache/lucene/search/function/ValueSource.java
------------------------------------------------------------------------------
    svn:eol-style = native

Propchange: lucene/java/trunk/src/java/org/apache/lucene/search/function/ValueSource.java
------------------------------------------------------------------------------
    svn:executable = *

Added: lucene/java/trunk/src/java/org/apache/lucene/search/function/ValueSourceQuery.java
URL: http://svn.apache.org/viewvc/lucene/java/trunk/src/java/org/apache/lucene/search/function/ValueSourceQuery.java?view=auto&rev=544546
==============================================================================
--- lucene/java/trunk/src/java/org/apache/lucene/search/function/ValueSourceQuery.java (added)
+++ lucene/java/trunk/src/java/org/apache/lucene/search/function/ValueSourceQuery.java Tue Jun  5 09:29:35 2007
@@ -0,0 +1,201 @@
+package org.apache.lucene.search.function;
+
+/**
+ * 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.
+ */
+
+import org.apache.lucene.index.IndexReader;
+import org.apache.lucene.search.*;
+import org.apache.lucene.util.ToStringUtils;
+
+import java.io.IOException;
+import java.util.Set;
+
+/**
+ * Expert: A Query that sets the scores of document to the
+ * values obtained from a {@link org.apache.lucene.search.function.ValueSource ValueSource}.
+ * <p>   
+ * The value source can be based on a (cached) value of an indexd  field, but it
+ * can also be based on an external source, e.g. values read from an external database. 
+ * <p>
+ * Score is set as: Score(doc,query) = query.getBoost()<sup>2</sup> * valueSource(doc).  
+ *
+ * <p><font color="#FF0000">
+ * WARNING: The status of the <b>search.function</b> package is experimental. 
+ * The APIs introduced here might change in the future and will not be 
+ * supported anymore in such a case.</font>
+ * 
+ * @author yonik
+ */
+public class ValueSourceQuery extends Query {
+  ValueSource valSrc;
+
+  /**
+   * Create a value source query
+   * @param valSrc provides the values defines the function to be used for scoring
+   */
+  public ValueSourceQuery(ValueSource valSrc) {
+    this.valSrc=valSrc;
+  }
+
+  /*(non-Javadoc) @see org.apache.lucene.search.Query#rewrite(org.apache.lucene.index.IndexReader) */
+  public Query rewrite(IndexReader reader) throws IOException {
+    return this;
+  }
+
+  /*(non-Javadoc) @see org.apache.lucene.search.Query#extractTerms(java.util.Set) */
+  public void extractTerms(Set terms) {
+    // no terms involved here
+  }
+
+  private class ValueSourceWeight implements Weight {
+    Searcher searcher;
+    float queryNorm;
+    float queryWeight;
+
+    public ValueSourceWeight(Searcher searcher) {
+      this.searcher = searcher;
+    }
+
+    /*(non-Javadoc) @see org.apache.lucene.search.Weight#getQuery() */
+    public Query getQuery() {
+      return ValueSourceQuery.this;
+    }
+
+    /*(non-Javadoc) @see org.apache.lucene.search.Weight#getValue() */
+    public float getValue() {
+      return queryWeight;
+    }
+
+    /*(non-Javadoc) @see org.apache.lucene.search.Weight#sumOfSquaredWeights() */
+    public float sumOfSquaredWeights() throws IOException {
+      queryWeight = getBoost();
+      return queryWeight * queryWeight;
+    }
+
+    /*(non-Javadoc) @see org.apache.lucene.search.Weight#normalize(float) */
+    public void normalize(float norm) {
+      this.queryNorm = norm;
+      queryWeight *= this.queryNorm;
+    }
+
+    /*(non-Javadoc) @see org.apache.lucene.search.Weight#scorer(org.apache.lucene.index.IndexReader) */
+    public Scorer scorer(IndexReader reader) throws IOException {
+      return new ValueSourceScorer(getSimilarity(searcher), reader, this);
+    }
+
+    /*(non-Javadoc) @see org.apache.lucene.search.Weight#explain(org.apache.lucene.index.IndexReader, int) */
+    public Explanation explain(IndexReader reader, int doc) throws IOException {
+      return scorer(reader).explain(doc);
+    }
+  }
+
+  /**
+   * A scorer that (simply) matches all documents, and scores each document with 
+   * the value of the value soure in effect. As an example, if the value source 
+   * is a (cached) field source, then value of that field in that document will 
+   * be used. (assuming field is indexed for this doc, with a single token.)   
+   */
+  private class ValueSourceScorer extends Scorer {
+    private final IndexReader reader;
+    private final ValueSourceWeight weight;
+    private final int maxDoc;
+    private final float qWeight;
+    private int doc=-1;
+    private final DocValues vals;
+
+    // constructor
+    private ValueSourceScorer(Similarity similarity, IndexReader reader, ValueSourceWeight w) throws IOException {
+      super(similarity);
+      this.weight = w;
+      this.qWeight = w.getValue();
+      this.reader = reader;
+      this.maxDoc = reader.maxDoc();
+      // this is when/where the values are first created.
+      vals = valSrc.getValues(reader);
+    }
+
+    /*(non-Javadoc) @see org.apache.lucene.search.Scorer#next() */
+    public boolean next() throws IOException {
+      for(;;) {
+        ++doc;
+        if (doc>=maxDoc) {
+          return false;
+        }
+        if (reader.isDeleted(doc)) {
+          continue;
+        }
+        return true;
+      }
+    }
+
+    /*(non-Javadoc) @see org.apache.lucene.search.Scorer#doc()
+     */
+    public int doc() {
+      return doc;
+    }
+
+    /*(non-Javadoc) @see org.apache.lucene.search.Scorer#score() */
+    public float score() throws IOException {
+      return qWeight * vals.floatVal(doc);
+    }
+
+    /*(non-Javadoc) @see org.apache.lucene.search.Scorer#skipTo(int) */
+    public boolean skipTo(int target) throws IOException {
+      doc=target-1;
+      return next();
+    }
+
+    /*(non-Javadoc) @see org.apache.lucene.search.Scorer#explain(int) */
+    public Explanation explain(int doc) throws IOException {
+      float sc = qWeight * vals.floatVal(doc);
+
+      Explanation result = new ComplexExplanation(
+        true, sc, ValueSourceQuery.this.toString() + ", product of:");
+
+      result.addDetail(vals.explain(doc));
+      result.addDetail(new Explanation(getBoost(), "boost"));
+      result.addDetail(new Explanation(weight.queryNorm,"queryNorm"));
+      return result;
+    }
+  }
+
+  /*(non-Javadoc) @see org.apache.lucene.search.Query#createWeight(org.apache.lucene.search.Searcher) */
+  protected Weight createWeight(Searcher searcher) {
+    return new ValueSourceQuery.ValueSourceWeight(searcher);
+  }
+
+  /* (non-Javadoc) @see org.apache.lucene.search.Query#toString(java.lang.String) */
+  public String toString(String field) {
+    return valSrc.toString() + ToStringUtils.boost(getBoost());
+  }
+
+  /** Returns true if <code>o</code> is equal to this. */
+  public boolean equals(Object o) {
+    if (getClass() != o.getClass()) {
+      return false;
+    }
+    ValueSourceQuery other = (ValueSourceQuery)o;
+    return this.getBoost() == other.getBoost()
+           && this.valSrc.equals(other.valSrc);
+  }
+
+  /** Returns a hash code value for this object. */
+  public int hashCode() {
+    return (getClass().hashCode() + valSrc.hashCode()) ^ Float.floatToIntBits(getBoost());
+  }
+
+}

Propchange: lucene/java/trunk/src/java/org/apache/lucene/search/function/ValueSourceQuery.java
------------------------------------------------------------------------------
    svn:eol-style = native