<HTML><!-- -*-java-*- -->
<!-- Lucene Search Demo via CompiledPageServlet -->
<!-- Copyright (c) 1998,2000 Douglass R. Cutting. -->

<java type=import>
  javax.servlet.*
  javax.servlet.http.*
  java.io.*
  org.apache.lucene.analysis.*
  org.apache.lucene.document.*
  org.apache.lucene.index.*
  org.apache.lucene.search.*
  org.apache.lucene.queryParser.*
  org.apache.lucene.demo.*
  org.apache.lucene.demo.html.Entities
</java>

<java>
  // get index from request
  String indexName = request.getParameter("index");
  if (indexName == null)			  // default to "index"
    indexName = "index";
  Searcher searcher =				  // make searcher
    new IndexSearcher(getReader(indexName));

  // get query from request
  String queryString = request.getParameter("query");
  if (queryString == null)			  
    throw new ServletException("no query specified");
    
  int start = 0;				  // first hit to display
  String startString = request.getParameter("start");
  if (startString != null)
    start = Integer.parseInt(startString);

  int hitsPerPage = 10;				  // number of hits to display
  String hitsString = request.getParameter("hitsPerPage");
  if (hitsString != null)
    hitsPerPage = Integer.parseInt(hitsString);

  boolean showSummaries = true;			  // show summaries?
  if ("false".equals(request.getParameter("showSummaries")))
    showSummaries = false;

  Query query = null;
  try {						  // parse query
    query = QueryParser.parse(queryString, "contents", analyzer);
  } catch (ParseException e) {			  // error parsing query
    </java>
    <HEAD><TITLE>Error Parsing Query</TITLE></HEAD><BODY>
    <p>While parsing `queryString`: `e.getMessage()`
    <java>
    return;
  }

  String servletPath = request.getRequestURI();	  // getServletPath should work
  int j = servletPath.indexOf('?');		  // here but doesn't, so we
  if (j != -1)					  // remove query by hand...
    servletPath = servletPath.substring(0, j);

</java>

<head><title>Lucene Search Results</title></head><body>

<center>
 <form name=search action=`servletPath` method=get>
 <input name=query size=44 value='`queryString`'>
 <input type=hidden name=index value="`indexName`">
 <input type=hidden name=hitsPerPage value=`hitsPerPage`>
 <input type=hidden name=showSummaries value=`showSummaries`>
 <input type=submit value=Search>
 </form>
</center>
<java>
  Hits hits = searcher.search(query);		  // perform query
  int end = Math.min(hits.length(), start + hitsPerPage);
</java>

<p>Hits <b><java type=print>start+1</java>-<java type=print>end</java></b>
(out of <java type=print>hits.length()</java> total matching documents):

<ul>
<java>
  for (int i = start; i < end; i++) {		  // display the hits
    Document doc = hits.doc(i);
    String title = doc.get("title");
    if (title.equals(""))			  // use url for docs w/o title
      title = doc.get("url");
    </java>
    <p><b><java type=print>(int)(hits.score(i) * 100.0f)</java>%
    <a href="`doc.get("url")`">
    <java type=print>Entities.encode(title)</java>
    </b></a>
    <java>
    if (showSummaries) {			  // maybe show summary
    </java>
    <ul><i>Summary</i>:
      <java type=print>Entities.encode(doc.get("summary"))</java>
    </ul>
    <java>
    }
  }
</java>
</ul>

<java>
  if (end < hits.length()) {			  // insert next page button
</java>
    <center>
    <form name=search action=`servletPath` method=get>
    <input type=hidden name=query value='`queryString`'>
    <input type=hidden name=start value=`end`>
    <input type=hidden name=index value="`indexName`">
    <input type=hidden name=hitsPerPage value=`hitsPerPage`>
    <input type=hidden name=showSummaries value=`showSummaries`>
    <input type=submit value=Next>
    </form>
    </center>
<java>
    }
</java>

</body>

<java type=class>

  Analyzer analyzer = new StopAnalyzer();	  // used to tokenize queries

  /** Keep a cache of open IndexReader's, so that an index does not have to
      opened for each query.  The cache re-opens an index when it has changed
      so that additions and deletions are visible ASAP. */

  static Hashtable indexCache = new Hashtable();  // name->CachedIndex

  class CachedIndex {				  // an entry in the cache
    IndexReader reader;				  // an open reader
    long modified;				  // reader's modified date
    
    CachedIndex(String name) throws IOException {
      modified = IndexReader.lastModified(name);  // get modified date
      reader = IndexReader.open(name);		  // open reader
    }
  }

  IndexReader getReader(String name) throws ServletException {
    CachedIndex index =				  // look in cache
      (CachedIndex)indexCache.get(name);
    
    try {
      if (index != null &&			  // check up-to-date
	  (index.modified == IndexReader.lastModified(name)))
	return index.reader;			  // cache hit
      else {
	index = new CachedIndex(name);		  // cache miss
      }
    } catch (IOException e) {
      StringWriter writer = new StringWriter();
      PrintWriter pw = new PrintWriter(writer);
      throw new ServletException("Could not open index " + name + ": " +
				 e.getClass().getName() + "--" +
				 e.getMessage());
    }

    indexCache.put(name, index);		  // add to cache
    return index.reader;
  }
</java>
