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}