    001/*
    002 * Licensed to the Apache Software Foundation (ASF) under one or more
    003 * contributor license agreements.  See the NOTICE file distributed with
    004 * this work for additional information regarding copyright ownership.
    005 * The ASF licenses this file to You under the Apache License, Version 2.0
    006 * (the "License"); you may not use this file except in compliance with
    007 * the License.  You may obtain a copy of the License at
    008 *
    009 *     http://www.apache.org/licenses/LICENSE-2.0
    010 *
    011 * Unless required by applicable law or agreed to in writing, software
    012 * distributed under the License is distributed on an "AS IS" BASIS,
    013 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    014 * See the License for the specific language governing permissions and
    015 * limitations under the License.
    016 */
    017package org.apache.lucene.demo.xmlparser;
    018
    019import java.io.BufferedReader;
    020import java.io.IOException;
    021import java.io.InputStream;
    022import java.io.InputStreamReader;
    023import java.nio.charset.StandardCharsets;
    024import java.util.Enumeration;
    025import java.util.Properties;
    026import java.util.StringTokenizer;
    027
    028import javax.servlet.RequestDispatcher;
    029import javax.servlet.ServletConfig;
    030import javax.servlet.ServletException;
    031import javax.servlet.http.HttpServlet;
    032import javax.servlet.http.HttpServletRequest;
    033import javax.servlet.http.HttpServletResponse;
    034
    035import org.apache.lucene.analysis.Analyzer;
    036import org.apache.lucene.analysis.standard.StandardAnalyzer;
    037import org.apache.lucene.document.Document;
    038import org.apache.lucene.document.Field;
    039import org.apache.lucene.document.FieldType;
    040import org.apache.lucene.document.TextField;
    041import org.apache.lucene.index.DirectoryReader;
    042import org.apache.lucene.index.IndexReader;
    043import org.apache.lucene.index.IndexWriter;
    044import org.apache.lucene.index.IndexWriterConfig;
    045import org.apache.lucene.queryparser.xml.CorePlusExtensionsParser;
    046import org.apache.lucene.queryparser.xml.QueryTemplateManager;
    047import org.apache.lucene.search.IndexSearcher;
    048import org.apache.lucene.search.Query;
    049import org.apache.lucene.search.ScoreDoc;
    050import org.apache.lucene.search.TopDocs;
    051import org.apache.lucene.store.RAMDirectory;
    052
    053/**
    054 * Example servlet that uses the XML queryparser.
    055 * <p>
    056 * NOTE: you must provide CSV data in <code>/WEB-INF/data.tsv</code>
    057 * for the demo to work!
    058 */
    059public class FormBasedXmlQueryDemo extends HttpServlet {
    060
    061  private QueryTemplateManager queryTemplateManager;
    062  private CorePlusExtensionsParser xmlParser;
    063  private IndexSearcher searcher;
    064  private Analyzer analyzer = new StandardAnalyzer();
    065
    066  /** for instantiation by the servlet container */
    067  public FormBasedXmlQueryDemo() {}
    068
    069  @Override
    070  public void init(ServletConfig config) throws ServletException {
    071    super.init(config);
    072    try {
    073      openExampleIndex();
    074
    075      //load servlet configuration settings
    076      String xslFile = config.getInitParameter("xslFile");
    077      String defaultStandardQueryParserField = config.getInitParameter("defaultStandardQueryParserField");
    078
    079
    080      //Load and cache choice of XSL query template using QueryTemplateManager
    081      queryTemplateManager = new QueryTemplateManager(
    082          getServletContext().getResourceAsStream("/WEB-INF/" + xslFile));
    083
    084      //initialize an XML Query Parser for use by all threads
    085      xmlParser = new CorePlusExtensionsParser(defaultStandardQueryParserField, analyzer);
    086    } catch (Exception e) {
    087      throw new ServletException("Error loading query template", e);
    088    }
    089  }
    090
    091  @Override
    092  protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
    093    //Take all completed form fields and add to a Properties object
    094    Properties completedFormFields = new Properties();
    095    Enumeration<?> pNames = request.getParameterNames();
    096    while (pNames.hasMoreElements()) {
    097      String propName = (String) pNames.nextElement();
    098      String value = request.getParameter(propName);
    099      if ((value != null) && (value.trim().length() > 0)) {
    100        completedFormFields.setProperty(propName, value);
    101      }
    102    }
    103
    104    try {
    105      //Create an XML query by populating template with given user criteria
    106      org.w3c.dom.Document xmlQuery = queryTemplateManager.getQueryAsDOM(completedFormFields);
    107
    108      //Parse the XML to produce a Lucene query
    109      Query query = xmlParser.getQuery(xmlQuery.getDocumentElement());
    110
    111      //Run the query
    112      TopDocs topDocs = searcher.search(query, 10);
    113
    114      //and package the results and forward to JSP
    115      if (topDocs != null) {
    116        ScoreDoc[] sd = topDocs.scoreDocs;
    117        Document[] results = new Document[sd.length];
    118        for (int i = 0; i < results.length; i++) {
    119          results[i] = searcher.doc(sd[i].doc);
    120          request.setAttribute("results", results);
    121        }
    122      }
    123      RequestDispatcher dispatcher = getServletContext().getRequestDispatcher("/index.jsp");
    124      dispatcher.forward(request, response);
    125    }
    126    catch (Exception e) {
    127      throw new ServletException("Error processing query", e);
    128    }
    129  }
    130
    131  private void openExampleIndex() throws IOException {
    132    //Create a RAM-based index from our test data file
    133    RAMDirectory rd = new RAMDirectory();
    134    IndexWriterConfig iwConfig = new IndexWriterConfig(analyzer);
    135    IndexWriter writer = new IndexWriter(rd, iwConfig);
    136    InputStream dataIn = getServletContext().getResourceAsStream("/WEB-INF/data.tsv");
    137    BufferedReader br = new BufferedReader(new InputStreamReader(dataIn, StandardCharsets.UTF_8));
    138    String line = br.readLine();
    139    final FieldType textNoNorms = new FieldType(TextField.TYPE_STORED);
    140    textNoNorms.setOmitNorms(true);
    141    while (line != null) {
    142      line = line.trim();
    143      if (line.length() > 0) {
    144        //parse row and create a document
    145        StringTokenizer st = new StringTokenizer(line, "\t");
    146        Document doc = new Document();
    147        doc.add(new Field("location", st.nextToken(), textNoNorms));
    148        doc.add(new Field("salary", st.nextToken(), textNoNorms));
    149        doc.add(new Field("type", st.nextToken(), textNoNorms));
    150        doc.add(new Field("description", st.nextToken(), textNoNorms));
    151        writer.addDocument(doc);
    152      }
    153      line = br.readLine();
    154    }
    155    writer.close();
    156
    157    //open searcher
    158    // this example never closes it reader!
    159    IndexReader reader = DirectoryReader.open(rd);
    160    searcher = new IndexSearcher(reader);
    161  }
    162}