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_CURRENT, 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 }