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