Author: klaas
Date: Fri Sep  1 12:22:47 2006
New Revision: 439428

URL: http://svn.apache.org/viewvc?rev=439428&view=rev
Log:
Patch for SOLR-37 (highlighting param changes and new features)

Added:
    incubator/solr/trunk/src/java/org/apache/solr/util/HighlightingUtils.java   
(with props)
Modified:
    
incubator/solr/trunk/src/java/org/apache/solr/request/DisMaxRequestHandler.java
    incubator/solr/trunk/src/java/org/apache/solr/request/SolrParams.java
    
incubator/solr/trunk/src/java/org/apache/solr/request/StandardRequestHandler.java
    incubator/solr/trunk/src/java/org/apache/solr/util/SolrPluginUtils.java
    incubator/solr/trunk/src/test/org/apache/solr/HighlighterTest.java
    incubator/solr/trunk/src/test/test-files/solr/conf/solrconfig.xml
    incubator/solr/trunk/src/webapp/resources/admin/form.jsp

Modified: 
incubator/solr/trunk/src/java/org/apache/solr/request/DisMaxRequestHandler.java
URL: 
http://svn.apache.org/viewvc/incubator/solr/trunk/src/java/org/apache/solr/request/DisMaxRequestHandler.java?rev=439428&r1=439427&r2=439428&view=diff
==============================================================================
--- 
incubator/solr/trunk/src/java/org/apache/solr/request/DisMaxRequestHandler.java 
(original)
+++ 
incubator/solr/trunk/src/java/org/apache/solr/request/DisMaxRequestHandler.java 
Fri Sep  1 12:22:47 2006
@@ -32,6 +32,7 @@
 import org.apache.solr.schema.IndexSchema;
 
 import org.apache.solr.util.NamedList;
+import org.apache.solr.util.HighlightingUtils;
 import org.apache.solr.util.SolrPluginUtils;
 import org.apache.solr.util.DisMaxParams;
 
@@ -337,13 +338,12 @@
       }
 
       /* * * Highlighting/Summarizing  * * */
-      if(U.getBooleanParam(req, SolrParams.HIGHLIGHT, params.highlight)) {
+      if(HighlightingUtils.isHighlightingEnabled(req)) {
 
         BooleanQuery highlightQuery = new BooleanQuery();
         U.flattenBooleanQuery(highlightQuery, query);
-        NamedList sumData = U.doStandardHighlighting(results, highlightQuery, 
-                                                     req, params, 
-                                                     
queryFields.keySet().toArray(new String[0]));
+        NamedList sumData = HighlightingUtils.doHighlighting(results, 
highlightQuery, 
+                                                     req, 
queryFields.keySet().toArray(new String[0]));
         if(sumData != null)
           rsp.add("highlighting", sumData);
       }

Modified: incubator/solr/trunk/src/java/org/apache/solr/request/SolrParams.java
URL: 
http://svn.apache.org/viewvc/incubator/solr/trunk/src/java/org/apache/solr/request/SolrParams.java?rev=439428&r1=439427&r2=439428&view=diff
==============================================================================
--- incubator/solr/trunk/src/java/org/apache/solr/request/SolrParams.java 
(original)
+++ incubator/solr/trunk/src/java/org/apache/solr/request/SolrParams.java Fri 
Sep  1 12:22:47 2006
@@ -95,6 +95,20 @@
     String val = get(param);
     return val==null ? def : parseBool(val);
   }
+  
+  /** Returns the Boolean value of the field param, 
+      or the value for param, or null if neither is set. */
+  public Boolean getFieldBool(String field, String param) {
+    String val = getFieldParam(field, param);
+    return val==null ? null : parseBool(val);
+  }
+  
+  /** Returns the boolean value of the field param, 
+  or the value for param, or def if neither is set. */
+  public boolean getFieldBool(String field, String param, boolean def) {
+    String val = getFieldParam(field, param);
+    return val==null ? def : parseBool(val);
+  }
 
   /** Returns the Integer value of the param, or null if not set */
   public Integer getInt(String param) {

Modified: 
incubator/solr/trunk/src/java/org/apache/solr/request/StandardRequestHandler.java
URL: 
http://svn.apache.org/viewvc/incubator/solr/trunk/src/java/org/apache/solr/request/StandardRequestHandler.java?rev=439428&r1=439427&r2=439428&view=diff
==============================================================================
--- 
incubator/solr/trunk/src/java/org/apache/solr/request/StandardRequestHandler.java
 (original)
+++ 
incubator/solr/trunk/src/java/org/apache/solr/request/StandardRequestHandler.java
 Fri Sep  1 12:22:47 2006
@@ -23,6 +23,7 @@
 
 import org.apache.solr.util.StrUtils;
 import org.apache.solr.util.NamedList;
+import org.apache.solr.util.HighlightingUtils;
 import org.apache.solr.util.SolrPluginUtils;
 import org.apache.solr.search.*;
 import org.apache.solr.core.SolrCore;
@@ -118,7 +119,7 @@
         rsp.add("exception_during_debug", SolrException.toStr(e));
       }
 
-      NamedList sumData = SolrPluginUtils.doStandardHighlighting(
+      NamedList sumData = HighlightingUtils.doHighlighting(
         results, query, req, new String[]{defaultField});
       if(sumData != null)
         rsp.add("highlighting", sumData);

Added: incubator/solr/trunk/src/java/org/apache/solr/util/HighlightingUtils.java
URL: 
http://svn.apache.org/viewvc/incubator/solr/trunk/src/java/org/apache/solr/util/HighlightingUtils.java?rev=439428&view=auto
==============================================================================
--- incubator/solr/trunk/src/java/org/apache/solr/util/HighlightingUtils.java 
(added)
+++ incubator/solr/trunk/src/java/org/apache/solr/util/HighlightingUtils.java 
Fri Sep  1 12:22:47 2006
@@ -0,0 +1,281 @@
+/**
+ * Copyright 2006 The Apache Software Foundation
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.solr.util;
+
+import java.io.IOException;
+import java.io.StringReader;
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.Map;
+
+import org.apache.solr.request.*;
+import org.apache.solr.search.DocIterator;
+import org.apache.solr.search.DocList;
+import org.apache.solr.search.SolrIndexSearcher;
+
+import org.apache.lucene.analysis.TokenStream;
+import org.apache.lucene.document.Document;
+import org.apache.lucene.search.Query;
+import org.apache.lucene.search.highlight.*;
+
+/**
+ * Collection of Utility and Factory methods for Highlighting.
+ */
+public class HighlightingUtils
+{
+   private static final String SIMPLE = "simple";
+   
+   private static final String HIGHLIGHT = "hl";
+   private static final String PREFIX = "hl.";
+   private static final String FIELDS = PREFIX+"fl";
+   private static final String SNIPPETS = PREFIX+"snippets";
+   private static final String FRAGSIZE = PREFIX+"fragsize";
+   private static final String FORMATTER = PREFIX+"formatter";
+   private static final String SIMPLE_PRE = PREFIX+SIMPLE+".pre";
+   private static final String SIMPLE_POST = PREFIX+SIMPLE+".post";
+   private static final String FIELD_MATCH = PREFIX+"requireFieldMatch";
+   
+   private static SolrParams DEFAULTS = null;
+   static
+   {
+      Map<String,String> map = new HashMap<String,String>();
+      map.put(SNIPPETS, "1");
+      map.put(FRAGSIZE, "100");
+      map.put(FORMATTER, SIMPLE);
+      map.put(SIMPLE_PRE, "<em>");
+      map.put(SIMPLE_POST, "</em>");
+      
+      DEFAULTS = new MapSolrParams(map);
+   }
+   
+   /** Combine request parameters with highlighting defaults. */
+   private static SolrParams getParams(SolrQueryRequest request)
+   {
+      return new DefaultSolrParams(request.getParams(), DEFAULTS);
+   }
+   
+   /**
+    * Check whether Highlighting is enabled for this request.
+    * @param request The current SolrQueryRequest
+    * @return <code>true</code> if highlighting enabled, <code>false</code> if 
not.
+    */
+   public static boolean isHighlightingEnabled(SolrQueryRequest request)
+   {
+      return getParams(request).getBool(HIGHLIGHT, false);
+   }
+   
+   /**
+    * Return a Highlighter appropriate for this field.
+    * @param query The current Query
+    * @param fieldName The name of the field
+    * @param request The current SolrQueryRequest
+    */
+   public static Highlighter getHighlighter(Query query, String fieldName, 
SolrQueryRequest request)
+   {
+      Highlighter highlighter = new Highlighter(
+            getFormatter(fieldName, request), 
+            getQueryScorer(query, fieldName, request));
+      highlighter.setTextFragmenter(getFragmenter(fieldName, request));
+      return highlighter;
+   }
+   
+   /**
+    * Return a QueryScorer suitable for this Query and field.
+    * @param query The current query
+    * @param fieldName The name of the field
+    * @param request The SolrQueryRequest
+    */
+   public static QueryScorer getQueryScorer(Query query, String fieldName, 
SolrQueryRequest request)
+   {
+      boolean reqFieldMatch = getParams(request).getFieldBool(fieldName, 
FIELD_MATCH, false);
+      if (reqFieldMatch)
+      {
+         return new QueryScorer(query, request.getSearcher().getReader(), 
fieldName);
+      }
+      else
+      {
+         return new QueryScorer(query);
+      }
+   }
+   
+   /**
+    * Return a String array of the fields to be highlighted.
+    * Falls back to the programatic defaults, or the default search field if 
the list of fields
+    * is not specified in either the handler configuration or the request.
+    * @param query The current Query
+    * @param request The current SolrQueryRequest
+    * @param defaultFields Programmatic default highlight fields, used if 
nothing is specified in the handler config or the request.
+    */
+   public static String[] getHighlightFields(Query query, SolrQueryRequest 
request, String[] defaultFields)
+   {
+      String fields[] = getParams(request).getParams(FIELDS);
+      
+      // if no fields specified in the request, or the handler, fall back to 
programmatic default, or default search field.
+      if(emptyArray(fields)) 
+      {
+         // use default search field if highlight fieldlist not specified.
+         if (emptyArray(defaultFields)) 
+         {
+            fields = new 
String[]{request.getSchema().getDefaultSearchFieldName()};
+         }  
+         else
+         {
+            fields = defaultFields;
+         }
+      }
+      else if (fields.length == 1)
+      {
+         // if there's a single request/handler value, it may be a space/comma 
separated list
+         fields = SolrPluginUtils.split(fields[0]);
+      }
+      
+      return fields;
+   }
+   
+   private static boolean emptyArray(String[] arr)
+   {
+      return (arr == null || arr.length == 0 || arr[0] == null || 
arr[0].trim().length() == 0);
+   }
+   
+   /**
+    * Return the max number of snippets for this field. If this has not
+    * been configured for this field, fall back to the configured default
+    * or the solr default.
+    * @param fieldName The name of the field
+    * @param request The current SolrQueryRequest
+    */
+   public static int getMaxSnippets(String fieldName, SolrQueryRequest request)
+   {
+      return Integer.parseInt(getParams(request).getFieldParam(fieldName, 
SNIPPETS));
+   }
+   
+   /**
+    * Return a formatter appropriate for this field. If a formatter
+    * has not been configured for this field, fall back to the configured
+    * default or the solr default (SimpleHTMLFormatter).
+    * 
+    * @param fieldName The name of the field
+    * @param request The current SolrQueryRequest
+    * @return An appropriate Formatter.
+    */
+   public static Formatter getFormatter(String fieldName, SolrQueryRequest 
request)
+   {
+      SolrParams p = getParams(request);
+      
+      // SimpleHTMLFormatter is the only supported Formatter at the moment
+      return new SimpleHTMLFormatter(p.getFieldParam(fieldName, SIMPLE_PRE), 
p.getFieldParam(fieldName, SIMPLE_POST));
+   }
+   
+   /**
+    * Return a fragmenter appropriate for this field. If a fragmenter
+    * has not been configured for this field, fall back to the configured
+    * default or the solr default (GapFragmenter).
+    * 
+    * @param fieldName The name of the field
+    * @param request The current SolrQueryRequest
+    * @return An appropriate Fragmenter.
+    */
+   public static Fragmenter getFragmenter(String fieldName, SolrQueryRequest 
request)
+   {
+      int fragsize = 
Integer.parseInt(getParams(request).getFieldParam(fieldName, FRAGSIZE)); 
+      return (fragsize <= 0) ? new NullFragmenter() : new 
GapFragmenter(fragsize);
+   }
+   
+   /**
+    * Generates a list of Highlighted query fragments for each item in a list
+    * of documents, or returns null if highlighting is disabled.
+    *
+    * @param docs query results
+    * @param query the query
+    * @param req the current request
+    * @param defaultFields default list of fields to summarize
+    *
+    * @return NamedList containing a NamedList for each document, which in
+    * turns contains sets (field, summary) pairs.
+    */
+   public static NamedList doHighlighting(DocList docs, Query query, 
SolrQueryRequest req, String[] defaultFields) throws IOException
+   {
+      if (!isHighlightingEnabled(req))
+         return null;
+      
+      SolrIndexSearcher searcher = req.getSearcher();
+      NamedList fragments = new NamedList();
+      String[] fieldNames = getHighlightFields(query, req, defaultFields);
+
+      DocIterator iterator = docs.iterator();
+      for (int i = 0; i < docs.size(); i++)
+      {
+         int docId = iterator.nextDoc();
+         // use the Searcher's doc cache
+         Document doc = searcher.doc(docId);
+         NamedList docSummaries = new NamedList();
+         for (String fieldName : fieldNames)
+         {
+            fieldName = fieldName.trim();
+            String[] docTexts = doc.getValues(fieldName);
+            if (docTexts == null) continue;
+
+            // get highlighter, and number of fragments for this field
+            Highlighter highlighter = getHighlighter(query, fieldName, req);
+            int numFragments = getMaxSnippets(fieldName, req);
+
+            String[] summaries;
+            TextFragment[] frag;
+            if (docTexts.length == 1)
+            {
+               // single-valued field
+               TokenStream tstream;
+               try
+               {
+                  // attempt term vectors
+                  tstream = TokenSources.getTokenStream(searcher.getReader(), 
docId, fieldName);
+               }
+               catch (IllegalArgumentException e)
+               {
+                  // fall back to analyzer
+                  tstream = new 
TokenOrderingFilter(searcher.getSchema().getAnalyzer().tokenStream(fieldName, 
new StringReader(docTexts[0])), 10);
+               }
+               frag = highlighter.getBestTextFragments(tstream, docTexts[0], 
false, numFragments);
+            }
+            else
+            {
+               // multi-valued field
+               MultiValueTokenStream tstream;
+               tstream = new MultiValueTokenStream(fieldName, docTexts, 
searcher.getSchema().getAnalyzer(), true);
+               frag = highlighter.getBestTextFragments(tstream, 
tstream.asSingleValue(), false, numFragments);
+            }
+            // convert fragments back into text
+            // TODO: we can include score and position information in output 
as snippet attributes
+            if (frag.length > 0)
+            {
+               ArrayList<String> fragTexts = new ArrayList<String>();
+               for (int j = 0; j < frag.length; j++)
+               {
+                  if ((frag[j] != null) && (frag[j].getScore() > 0))
+                  {
+                     fragTexts.add(frag[j].toString());
+                  }
+               }
+               summaries = fragTexts.toArray(new String[0]);
+               if (summaries.length > 0) docSummaries.add(fieldName, 
summaries);
+            }
+         }
+         String printId = searcher.getSchema().printableUniqueKey(doc);
+         fragments.add(printId == null ? null : printId, docSummaries);
+      }
+      return fragments;
+   }
+}

Propchange: 
incubator/solr/trunk/src/java/org/apache/solr/util/HighlightingUtils.java
------------------------------------------------------------------------------
    svn:eol-style = native

Modified: 
incubator/solr/trunk/src/java/org/apache/solr/util/SolrPluginUtils.java
URL: 
http://svn.apache.org/viewvc/incubator/solr/trunk/src/java/org/apache/solr/util/SolrPluginUtils.java?rev=439428&r1=439427&r2=439428&view=diff
==============================================================================
--- incubator/solr/trunk/src/java/org/apache/solr/util/SolrPluginUtils.java 
(original)
+++ incubator/solr/trunk/src/java/org/apache/solr/util/SolrPluginUtils.java Fri 
Sep  1 12:22:47 2006
@@ -25,9 +25,7 @@
 import org.apache.lucene.queryParser.QueryParser;
 import org.apache.lucene.search.*;
 import org.apache.lucene.search.BooleanClause.Occur;
-import org.apache.lucene.search.highlight.Formatter;
 import org.apache.lucene.search.highlight.*;
-import org.apache.solr.core.Config;
 import org.apache.solr.core.SolrCore;
 import org.apache.solr.core.SolrException;
 import org.apache.solr.request.SolrParams;
@@ -133,6 +131,11 @@
   }
     
   private final static Pattern splitList=Pattern.compile(",| ");
+  
+  /** Split a value that may contain a comma, space of bar separated list. */
+  public static String[] split(String value){
+     return splitList.split(value.trim(), 0);
+  }
 
   /**
    * Assumes the standard query param of "fl" to specify the return fields
@@ -156,7 +159,7 @@
     if (fl != null) {
       // TODO - this could become more efficient if widely used.
       // TODO - should field order be maintained?
-      String[] flst = splitList.split(fl.trim(),0);
+      String[] flst = split(fl);
       if (flst.length > 0 && !(flst.length==1 && flst[0].length()==0)) {
         Set<String> set = new HashSet<String>();
         for (String fname : flst) {
@@ -356,234 +359,6 @@
   }
 
   /**
-   * Retrieve a default Highlighter instance for a given query.
-   *
-   * @param query Query instance
-   */
-  public static Highlighter getDefaultHighlighter(Query query) {
-    Highlighter highlighter = new Highlighter(
-      new SimpleHTMLFormatter("<em>", "</em>"), 
-      new QueryScorer(query));
-    highlighter.setTextFragmenter(new GapFragmenter());
-    return highlighter;
-  }
-
-  /**
-   * Generates a list of Highlighted query fragments for each item in a list
-   * of documents.  Convenience method that constructs a Highlighter from a
-   * Query.
-   *
-   * @param docs query results
-   * @param fieldNames list of fields to summarize
-   * @param query resulting query object
-   * @param searcher the SolrIndexSearcher corresponding to a request
-   * @param numFragments maximum number of summary fragments to return for
-   *        a given field   
-   */
-  public static NamedList getHighlights(DocList docs, 
-                                        String[] fieldNames, 
-                                        Query query,
-                                        SolrIndexSearcher searcher,
-                                        int numFragments
-                                        ) throws IOException {  
-    
-    return getHighlights(docs, fieldNames, searcher, 
-                         getDefaultHighlighter(query), numFragments);
-  }
-
-  /**
-   * Generates a list of Highlighted query fragments for each item in a list
-   * of documents
-   *
-   * @param docs query results
-   * @param fieldNames list of fields to summarize
-   * @param searcher the SolrIndexSearcher corresponding to a request
-   * @param numFragments maximum number of summary fragments to return for
-   *        a given field   
-   * @param highlighter a customized Highlighter instance
-   *
-   * @return NamedList containing a NamedList for each document, which in
-   * turns contains sets (field, summary) pairs.
-   */
-  public static NamedList getHighlights(DocList docs, 
-                                        String[] fieldNames, 
-                                        SolrIndexSearcher searcher,
-                                        Highlighter highlighter,
-                                        int numFragments
-                                        ) throws IOException {
-    NamedList fragments = new NamedList();
-    DocIterator iterator = docs.iterator();
-    for (int i=0; i<docs.size(); i++) {
-      int docId = iterator.nextDoc();
-      // use the Searcher's doc cache
-      Document doc = searcher.doc(docId);
-      NamedList docSummaries = new NamedList();
-      for(String fieldName : fieldNames) {
-        fieldName = fieldName.trim();
-        String[] docTexts = doc.getValues(fieldName);
-        if(docTexts == null) 
-          continue;        
-        String[] summaries;
-        TextFragment[] frag;
-        if(docTexts.length == 1) {
-          // single-valued field
-          TokenStream tstream;
-          try {
-            // attempt term vectors
-            tstream = TokenSources.getTokenStream(
-              searcher.getReader(), docId, fieldName);
-          } catch (IllegalArgumentException e) {
-            // fall back to analyzer
-            tstream = new TokenOrderingFilter(
-                    searcher.getSchema().getAnalyzer().tokenStream(
-                      fieldName, new StringReader(docTexts[0])),
-                    10);
-          }
-          frag = highlighter.getBestTextFragments(
-            tstream, docTexts[0], false, numFragments);
-
-        } else {
-          // multi-valued field
-          MultiValueTokenStream tstream;
-          tstream = new MultiValueTokenStream(fieldName,
-                                              docTexts,
-                                              
searcher.getSchema().getAnalyzer(), true);
-          frag = highlighter.getBestTextFragments(
-            tstream, tstream.asSingleValue(), false, numFragments);
-        }
-        // convert fragments back into text
-        // TODO: we can include score and position information in output as
-        // snippet attributes
-        if(frag.length > 0) {
-          ArrayList fragTexts = new ArrayList();
-          for (int j = 0; j < frag.length; j++) {
-              if ((frag[j] != null) && (frag[j].getScore() > 0)) {
-                  fragTexts.add(frag[j].toString());
-                }
-            }
-          summaries =  (String[]) fragTexts.toArray(new String[0]);
-          if(summaries.length > 0)
-            docSummaries.add(fieldName, summaries);
-        }
-      }      
-      String printId = searcher.getSchema().printableUniqueKey(doc);
-      fragments.add(printId == null ? null : printId, docSummaries);
-    }    
-    return fragments;
-  }
-
-  /**
-   * Perform highlighting of selected fields.
-   *
-   * @param docs query results
-   * @param query the (possibly re-written query)
-   * @param req associated SolrQueryRequest
-   * @param defaultFields default search field list
-   *
-   * @return NamedList containing summary data, or null if highlighting is 
-   * disabled.
-   *
-   */
-  public static NamedList doStandardHighlighting(DocList docs,
-                                                 Query query,
-                                                 SolrQueryRequest req,
-                                                 CommonParams params,
-                                                 String[] defaultFields
-                                                 ) throws IOException {
-    if(!getBooleanParam(req, SolrParams.HIGHLIGHT, params.highlight))
-      return null;
-    String fieldParam = getParam(req, SolrParams.HIGHLIGHT_FIELDS,
-                                 params.highlightFields);
-    String fields[];
-    if(fieldParam == null || fieldParam.trim().equals("")) {
-      // use default search field if highlight fieldlist not specified.
-      if (defaultFields == null || defaultFields.length == 0 ||
-          defaultFields[0] == null) {
-        fields = new String[]{req.getSchema().getDefaultSearchFieldName()};
-      } else
-        fields = defaultFields;
-    } else 
-      fields = splitList.split(fieldParam.trim());
-
-    Highlighter highlighter;
-    String formatterSpec = getParam(req, SolrParams.HIGHLIGHT_FORMATTER_CLASS,
-                                    params.highlightFormatterClass);
-    if(formatterSpec == null || formatterSpec.equals("")) {
-      highlighter = getDefaultHighlighter(query);
-    } else {
-      highlighter = new Highlighter(
-        (Formatter)Config.newInstance(formatterSpec),
-        new QueryScorer(query));
-      highlighter.setTextFragmenter(new GapFragmenter());
-    }
-    
-    int numFragments = getNumberParam(req, SolrParams.MAX_SNIPPETS,
-                                      params.maxSnippets).intValue();
-
-    return getHighlights(
-      docs, 
-      fields, 
-      req.getSearcher(),
-      highlighter,
-      numFragments);
-  }
-
-
-  /** TODO: API IN PROGRESS... SUBJECT TO CHANGE
-   * Perform highlighting of selected fields.
-   *
-   * @param docs query results
-   * @param query the (possibly re-written query)
-   * @param req associated SolrQueryRequest
-   * @param defaultFields default search field list
-   *
-   * @return NamedList containing summary data, or null if highlighting is
-   * disabled.
-   *
-   */
-  public static NamedList doStandardHighlighting(DocList docs,
-                                                 Query query,
-                                                 SolrQueryRequest req,
-                                                 String[] defaultFields
-                                                 ) throws IOException {
-    SolrParams p = req.getParams();
-    if (!p.getBool(SolrParams.HIGHLIGHT, false)) return null;
-    String fieldParam = p.get(SolrParams.HIGHLIGHT_FIELDS);
-    String fields[];
-    if(fieldParam == null || fieldParam.trim().equals("")) {
-      // use default search field if highlight fieldlist not specified.
-      if (defaultFields == null || defaultFields.length == 0 ||
-          defaultFields[0] == null) {
-        fields = new String[]{req.getSchema().getDefaultSearchFieldName()};
-      } else
-        fields = defaultFields;
-    } else
-      fields = splitList.split(fieldParam.trim());
-
-    Highlighter highlighter;
-    String formatterSpec = p.get(SolrParams.HIGHLIGHT_FORMATTER_CLASS);
-    if(formatterSpec == null) {
-      highlighter = getDefaultHighlighter(query);
-    } else {
-      highlighter = new Highlighter(
-        (Formatter)Config.newInstance(formatterSpec),
-        new QueryScorer(query));
-      highlighter.setTextFragmenter(new GapFragmenter());
-    }
-
-    int numFragments = p.getInt(SolrParams.MAX_SNIPPETS, 1);
-
-    return getHighlights(
-      docs,
-      fields,
-      req.getSearcher(),
-      highlighter,
-      numFragments);
-  }
-
-
-
-  /**
    * Executes a basic query in lucene syntax
    */
   public static DocList doSimpleQuery(String sreq,
@@ -1046,6 +821,14 @@
 class GapFragmenter extends SimpleFragmenter {
   public static final int INCREMENT_THRESHOLD = 50;
   protected int fragOffsetAccum = 0;
+  
+  public GapFragmenter() {
+  }
+  
+  public GapFragmenter(int fragsize) {
+     super(fragsize);
+  }
+  
   /* (non-Javadoc)
    * @see 
org.apache.lucene.search.highlight.TextFragmenter#start(java.lang.String)
    */

Modified: incubator/solr/trunk/src/test/org/apache/solr/HighlighterTest.java
URL: 
http://svn.apache.org/viewvc/incubator/solr/trunk/src/test/org/apache/solr/HighlighterTest.java?rev=439428&r1=439427&r2=439428&view=diff
==============================================================================
--- incubator/solr/trunk/src/test/org/apache/solr/HighlighterTest.java 
(original)
+++ incubator/solr/trunk/src/test/org/apache/solr/HighlighterTest.java Fri Sep  
1 12:22:47 2006
@@ -46,10 +46,10 @@
   public void testTermVecHighlight() {
 
     // do summarization using term vectors
-    HashMap args = new HashMap();
-    args.put("highlight", "true");
-    args.put("highlightFields", "tv_text");
-    args.put("maxSnippets", "2");
+    HashMap<String,String> args = new HashMap<String,String>();
+    args.put("hl", "true");
+    args.put("hl.fl", "tv_text");
+    args.put("hl.snippets", "2");
     TestHarness.LocalRequestFactory sumLRF = h.getRequestFactory(
       "standard",0,200,args);
     
@@ -68,9 +68,9 @@
   public void testDisMaxHighlight() {
 
     // same test run through dismax handler
-    HashMap args = new HashMap();
-    args.put("highlight", "true");
-    args.put("highlightFields", "tv_text");
+    HashMap<String,String> args = new HashMap<String,String>();
+    args.put("hl", "true");
+    args.put("hl.fl", "tv_text");
     args.put("qf", "tv_text");
     TestHarness.LocalRequestFactory sumLRF = h.getRequestFactory(
       "dismax",0,200,args);
@@ -90,9 +90,9 @@
   public void testMultiValueAnalysisHighlight() {
 
     // do summarization using re-analysis of the field
-    HashMap args = new HashMap();
-    args.put("highlight", "true");
-    args.put("highlightFields", "textgap");
+    HashMap<String,String> args = new HashMap<String,String>();
+    args.put("hl", "true");
+    args.put("hl.fl", "textgap");
     args.put("df", "textgap");
     TestHarness.LocalRequestFactory sumLRF = h.getRequestFactory(
       "standard", 0, 200, args);
@@ -114,10 +114,10 @@
   public void testDefaultFieldHighlight() {
 
     // do summarization using re-analysis of the field
-    HashMap args = new HashMap();
-    args.put("highlight", "true");
+    HashMap<String,String> args = new HashMap<String,String>();
+    args.put("hl", "true");
     args.put("df", "t_text");
-    args.put("highlightFields", "");
+    args.put("hl.fl", "");
     TestHarness.LocalRequestFactory sumLRF = h.getRequestFactory(
       "standard", 0, 200, args);
     
@@ -137,9 +137,9 @@
   public void testHighlightDisabled() {
 
     // ensure highlighting can be explicitly disabled
-    HashMap args = new HashMap();
-    args.put("highlight", "false");
-    args.put("highlightFields", "t_text");
+    HashMap<String,String> args = new HashMap<String,String>();
+    args.put("hl", "false");
+    args.put("hl.fl", "t_text");
     TestHarness.LocalRequestFactory sumLRF = h.getRequestFactory(
       "standard", 0, 200, args);
     
@@ -155,9 +155,9 @@
   public void testTwoFieldHighlight() {
 
     // do summarization using re-analysis of the field
-    HashMap args = new HashMap();
-    args.put("highlight", "true");
-    args.put("highlightFields", "t_text tv_text");
+    HashMap<String,String> args = new HashMap<String,String>();
+    args.put("hl", "true");
+    args.put("hl.fl", "t_text tv_text");
     TestHarness.LocalRequestFactory sumLRF = h.getRequestFactory(
       "standard", 0, 200, args);
     
@@ -171,17 +171,49 @@
             "//[EMAIL PROTECTED]'1']/[EMAIL PROTECTED]'t_text']/str",
             "//[EMAIL PROTECTED]'1']/[EMAIL PROTECTED]'tv_text']/str"
             );
-
+  }
+  
+  public void testFieldMatch()
+  {
+     assertU(adoc("t_text1", "random words for highlighting tests", "id", "1",
+           "t_text2", "more random words for second field"));
+     assertU(commit());
+     assertU(optimize());
+     
+     HashMap<String,String> args = new HashMap<String,String>();
+     args.put("hl", "true");
+     args.put("hl.fl", "t_text1 t_text2");
+     
+     TestHarness.LocalRequestFactory sumLRF = h.getRequestFactory(
+           "standard", 0, 200, args);
+     // default should highlight both random and words in both fields
+     assertQ("Test Default",
+           sumLRF.makeRequest("t_text1:random OR t_text2:words"),
+           "//[EMAIL PROTECTED]'highlighting']/[EMAIL PROTECTED]'1']",
+           "//[EMAIL PROTECTED]'1']/[EMAIL 
PROTECTED]'t_text1']/str[.='<em>random</em> <em>words</em> for highlighting 
tests']",
+           "//[EMAIL PROTECTED]'1']/[EMAIL PROTECTED]'t_text2']/str[.='more 
<em>random</em> <em>words</em> for second field']"
+           );
+     
+     // requireFieldMatch=true - highlighting should only occur if term 
matched in that field
+     args.put("hl.requireFieldMatch", "true");
+     sumLRF = h.getRequestFactory(
+           "standard", 0, 200, args);
+     assertQ("Test RequireFieldMatch",
+           sumLRF.makeRequest("t_text1:random OR t_text2:words"),
+           "//[EMAIL PROTECTED]'highlighting']/[EMAIL PROTECTED]'1']",
+           "//[EMAIL PROTECTED]'1']/[EMAIL 
PROTECTED]'t_text1']/str[.='<em>random</em> words for highlighting tests']",
+           "//[EMAIL PROTECTED]'1']/[EMAIL PROTECTED]'t_text2']/str[.='more 
random <em>words</em> for second field']"
+           );
   }
 
-  public void testCustomFormatterHighlight() {
+  public void testCustomSimpleFormatterHighlight() {
 
     // do summarization using a custom formatter
-    HashMap args = new HashMap();
-    args.put("highlight", "true");
-    args.put("highlightFields", "t_text");
-    args.put("highlightFormatterClass", 
-             "org.apache.lucene.search.highlight.SimpleHTMLFormatter");
+    HashMap<String,String> args = new HashMap<String,String>();
+    args.put("hl", "true");
+    args.put("hl.fl", "t_text");
+    args.put("hl.simple.pre","<B>");
+    args.put("hl.simple.post","</B>");
     TestHarness.LocalRequestFactory sumLRF = h.getRequestFactory(
       "standard", 0, 200, args);
     
@@ -193,16 +225,25 @@
             "//[EMAIL PROTECTED]'highlighting']/[EMAIL PROTECTED]'1']",
             "//[EMAIL PROTECTED]'1']/[EMAIL PROTECTED]'t_text']/str[.='a 
<B>long</B> days night']"
             );
+    
+    // test a per-field override
+    args.put("f.t_text.hl.simple.pre","<I>");
+    args.put("f.t_text.hl.simple.post","</I>");
+    sumLRF = h.getRequestFactory(
+          "standard", 0, 200, args);
+    assertQ("Basic summarization",
+          sumLRF.makeRequest("t_text:long"),
+          "//[EMAIL PROTECTED]'highlighting']/[EMAIL PROTECTED]'1']",
+          "//[EMAIL PROTECTED]'1']/[EMAIL PROTECTED]'t_text']/str[.='a 
<I>long</I> days night']"
+          );
+    
   }
 
   public void testLongFragment() {
 
-    // do summarization using a custom formatter
-    HashMap args = new HashMap();
-    args.put("highlight", "true");
-    args.put("highlightFields", "tv_text");
-    args.put("highlightFormatterClass", 
-             "org.apache.lucene.search.highlight.SimpleHTMLFormatter");
+    HashMap<String,String> args = new HashMap<String,String>();
+    args.put("hl", "true");
+    args.put("hl.fl", "tv_text");
     TestHarness.LocalRequestFactory sumLRF = h.getRequestFactory(
       "standard", 0, 200, args);
     
@@ -217,5 +258,44 @@
             "//[EMAIL PROTECTED]'highlighting']/[EMAIL PROTECTED]'1']",
             "//[EMAIL PROTECTED]'1']/[EMAIL PROTECTED]'tv_text']/str"
             );
+  }
+  
+  public void testVariableFragsize() {
+     assertU(adoc("tv_text", "a long days night this should be a piece of text 
which is is is is is is is is is is is is is is is is is is is is is is is is 
isis is is is is is is is is is is is is is is is is is is is is is is is is is 
is is is is is is is is is is is is is is is is is is is is is is is is is is 
is is is is is is is is is is is is is is is is is is is is is is is 
sufficiently lengthly to produce multiple fragments which are not concatenated 
at all", 
+           "id", "1"));
+     assertU(commit());
+     assertU(optimize());
+
+     // default length
+     HashMap<String,String> args = new HashMap<String,String>();
+     args.put("hl", "true");
+     args.put("hl.fl", "tv_text");
+     TestHarness.LocalRequestFactory sumLRF = h.getRequestFactory(
+       "standard", 0, 200, args);
+     assertQ("Basic summarization",
+           sumLRF.makeRequest("tv_text:long"),
+           "//[EMAIL PROTECTED]'highlighting']/[EMAIL PROTECTED]'1']",
+           "//[EMAIL PROTECTED]'1']/[EMAIL PROTECTED]'tv_text']/str[.='a 
<em>long</em> days night this should be a piece of text which']"
+           );
+     
+     // 25
+     args.put("hl.fragsize","25");
+     sumLRF = h.getRequestFactory(
+           "standard", 0, 200, args);
+     assertQ("Basic summarization",
+           sumLRF.makeRequest("tv_text:long"),
+           "//[EMAIL PROTECTED]'highlighting']/[EMAIL PROTECTED]'1']",
+           "//[EMAIL PROTECTED]'1']/[EMAIL PROTECTED]'tv_text']/str[.='a 
<em>long</em> days night']"
+           );
+     
+     // 0 - NullFragmenter
+     args.put("hl.fragsize","0");
+     sumLRF = h.getRequestFactory(
+           "standard", 0, 200, args);
+     assertQ("Basic summarization",
+           sumLRF.makeRequest("tv_text:long"),
+           "//[EMAIL PROTECTED]'highlighting']/[EMAIL PROTECTED]'1']",
+           "//[EMAIL PROTECTED]'1']/[EMAIL PROTECTED]'tv_text']/str[.='a 
<em>long</em> days night this should be a piece of text which is is is is is is 
is is is is is is is is is is is is is is is is is is isis is is is is is is is 
is is is is is is is is is is is is is is is is is is is is is is is is is is 
is is is is is is is is is is is is is is is is is is is is is is is is is is 
is is is is is is is is is is is is is is is sufficiently lengthly to produce 
multiple fragments which are not concatenated at all']"
+           );
   }
 }

Modified: incubator/solr/trunk/src/test/test-files/solr/conf/solrconfig.xml
URL: 
http://svn.apache.org/viewvc/incubator/solr/trunk/src/test/test-files/solr/conf/solrconfig.xml?rev=439428&r1=439427&r2=439428&view=diff
==============================================================================
--- incubator/solr/trunk/src/test/test-files/solr/conf/solrconfig.xml (original)
+++ incubator/solr/trunk/src/test/test-files/solr/conf/solrconfig.xml Fri Sep  
1 12:22:47 2006
@@ -201,8 +201,8 @@
   <requestHandler name="defaults" class="solr.StandardRequestHandler">
     <lst name="defaults">
       <int name="rows">4</int>
-      <bool name="highlight">true</bool>
-      <str name="highlightFields">text,name,subject,title,whitetok</str>
+      <bool name="hl">true</bool>
+      <str name="hl.fl">text,name,subject,title,whitetok</str>
     </lst>
   </requestHandler>
 

Modified: incubator/solr/trunk/src/webapp/resources/admin/form.jsp
URL: 
http://svn.apache.org/viewvc/incubator/solr/trunk/src/webapp/resources/admin/form.jsp?rev=439428&r1=439427&r2=439428&view=diff
==============================================================================
--- incubator/solr/trunk/src/webapp/resources/admin/form.jsp (original)
+++ incubator/solr/trunk/src/webapp/resources/admin/form.jsp Fri Sep  1 
12:22:47 2006
@@ -90,6 +90,22 @@
 </tr>
 <tr>
   <td>
+       <strong>Enable Highlighting</strong>
+  </td>
+  <td>
+       <input name="hl" type="checkbox" >
+  </td>
+</tr>
+<tr>
+  <td>
+       <strong>Fields to Highlight</strong>
+  </td>
+  <td>
+       <input name="hl.fl" type="text" >
+  </td>
+</tr>
+<tr>
+  <td>
   </td>
   <td>
        <input class="stdbutton" type="submit" value="search">


Reply via email to