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    }