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