1 /* 2 * @(#)QueryEngine.java 1.25 06/10/30 3 * 4 * Copyright (c) 2006 Sun Microsystems, Inc. All Rights Reserved. 5 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 6 * 7 * This code is free software; you can redistribute it and/or modify it 8 * under the terms of the GNU General Public License version 2 only, as 9 * published by the Free Software Foundation. Sun designates this 10 * particular file as subject to the "Classpath" exception as provided 11 * by Sun in the LICENSE file that accompanied this code. 12 * 13 * This code is distributed in the hope that it will be useful, but WITHOUT 14 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 15 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 16 * version 2 for more details (a copy is included in the LICENSE file that 17 * accompanied this code). 18 * 19 * You should have received a copy of the GNU General Public License version 20 * 2 along with this work; if not, write to the Free Software Foundation, 21 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. 22 * 23 * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, 24 * CA 95054 USA or visit www.sun.com if you need additional information or 25 * have any questions. 26 */ 27 28 /* 29 * @version 1.25 10/30/06 30 */ 31 32 package com.sun.java.help.search; 33 34 import java.text.BreakIterator; 35 import java.util.Vector; 36 import java.util.Locale; 37 import java.util.Enumeration; 38 import java.lang.reflect.Method; 39 import java.io.BufferedReader; 40 import java.io.InputStreamReader; 41 import java.io.File; 42 import java.net.URL; 43 import javax.help.search.SearchQuery; 44 import javax.help.HelpUtilities; 45 46 /** 47 * This class is the initial interface into the search engine. It can be 48 * run as a standalone search engine or instantiated as a class. 49 * 50 * @author Jacek R. Ambroziak 51 * @author Roger D. Brinkley 52 * @author Eduardo Pelegri-Llopart 53 * @version 1.25 10/30/06 54 */ 55 56 public class QueryEngine 57 { 58 private SearchEnvironment _env; 59 QueryEngine(String indexDir, URL hsBase)60 public QueryEngine(String indexDir, URL hsBase) throws Exception { 61 _env = new SearchEnvironment(indexDir, hsBase); 62 } 63 processQuery(String query, Locale l, SearchQuery searchQuery)64 public void processQuery(String query, Locale l, SearchQuery searchQuery) throws Exception 65 { 66 BreakIterator boundary; 67 int start; 68 String term; 69 Vector ids = new Vector();; 70 LiteMorph morph = getMorphForLocale(l); 71 int col=-1; 72 73 try { 74 boundary = BreakIterator.getWordInstance(l); 75 boundary.setText(query); 76 start = boundary.first(); 77 for (int end = boundary.next(); 78 end != BreakIterator.DONE; 79 start = end, end = boundary.next()) { 80 term = new String(query.substring(start,end)); 81 term = term.trim(); 82 term = term.toLowerCase(l); 83 if (term.length() > 1) { 84 col += 1; 85 int id = _env.fetch(term); 86 if (id > 0) { 87 ids.addElement(new SearchIds(col, id, 0.0)); 88 } 89 if (morph != null) { 90 String [] morphs = morph.variantsOf(term); 91 for (int i=0; i < morphs.length ; i++) { 92 int id2 = _env.fetch(morphs[i]); 93 if (id2 > 0) { 94 ids.addElement(new SearchIds(col, id2, 0.1)); 95 } 96 } 97 } 98 } else if (term.length() == 1) { 99 int charType = Character.getType(term.charAt(0)); 100 if ((charType == Character.DECIMAL_DIGIT_NUMBER) || 101 (charType == Character.LETTER_NUMBER) || 102 (charType == Character.LOWERCASE_LETTER) || 103 (charType == Character.OTHER_LETTER) || 104 (charType == Character.OTHER_NUMBER) || 105 (charType == Character.TITLECASE_LETTER) || 106 (charType == Character.UNASSIGNED) || 107 (charType == Character.UPPERCASE_LETTER)) { 108 col += 1; 109 int id = _env.fetch(term); 110 if (id > 0) { 111 ids.addElement(new SearchIds(col, id, 0.0)); 112 } 113 if (morph != null) { 114 String [] morphs = morph.variantsOf(term); 115 for (int i=0; i < morphs.length ; i++) { 116 int id2 = _env.fetch(morphs[i]); 117 if (id2 > 0) { 118 ids.addElement(new SearchIds(col, id2, 0.1)); 119 } 120 } 121 } 122 } 123 } 124 } 125 } 126 catch (Exception e) { 127 e.printStackTrace(); 128 } 129 int size = ids.size(); 130 Search search = new Search(_env, col + 1); 131 IntegerArray children = new IntegerArray(); 132 133 // add the terms and any children of a given term to the list of 134 // searched items. Penalize the children slightly 135 for (int i = 0; i < size; i++) 136 { 137 SearchIds id = (SearchIds) ids.elementAt(i); 138 search.addTerm(id.col, id.concept, id.score, 0); 139 children.clear(); 140 _env.getChildren(id.concept, children); 141 if (children.cardinality() > 0) 142 for (int j = 0; j < children.cardinality(); j++) 143 { 144 search.addTerm(id.col, children.at(j), 145 id.score + 0.1, 0); 146 // appending (grand)+children 147 //!!! as it is too many duplicates are added 148 _env.getChildren(children.at(j), children); 149 } 150 } 151 152 search.startSearch(searchQuery); 153 } 154 getMorphForLocale(Locale l)155 private LiteMorph getMorphForLocale(Locale l) { 156 // In the event that nolocale has been defined try English 157 if (l == null) { 158 l = Locale.ENGLISH; 159 } 160 //Try to find a locale version of LiteMorph 161 Enumeration enum1 = HelpUtilities.getCandidates(l); 162 String front = "com.sun.java.help.search.LiteMorph"; 163 ClassLoader cl = QueryEngine.class.getClassLoader(); 164 while (enum1.hasMoreElements()) { 165 String tail = (String) enum1.nextElement(); 166 String name = new String(front + tail); 167 try { 168 Class klass; 169 if (cl == null) { 170 klass = Class.forName(name); 171 } else { 172 klass = cl.loadClass(name); 173 } 174 Method method = klass.getMethod ("getMorph", 175 (java.lang.Class[]) null); 176 return (LiteMorph) method.invoke(null, 177 (java.lang.Object[]) null); 178 } catch (Exception e) { 179 continue; 180 } 181 } 182 // couldn't find a match 183 return null; 184 } 185 186 main(String[] args)187 public static void main(String[] args) 188 { 189 try { 190 // BufferedReader is needed for readLine() method 191 BufferedReader in = 192 // but we'll make it a degenerate buffer of 1 193 // to workaround a problem with some PC implementation 194 // which wouldn't start to read before a lot of chars 195 // were typed 196 new BufferedReader(new InputStreamReader(System.in), 1); 197 String file = new String (args[0]); 198 QueryEngine qe = new QueryEngine(file, null); 199 System.out.println("initialized; enter query"); 200 while(true) 201 { 202 String line = in.readLine(); 203 if (line.equals(".")) 204 break; 205 else 206 { 207 long start = System.currentTimeMillis(); 208 qe.processQuery(line, Locale.getDefault(), null); 209 System.out.println((System.currentTimeMillis()-start) 210 +" msec search"); 211 } 212 System.out.println("enter next query or . to quit"); 213 } 214 } 215 catch (Exception e) { 216 e.printStackTrace(); 217 } 218 } 219 220 private class SearchIds { 221 public int col; 222 public int concept; 223 public double score; 224 SearchIds(int col, int concept, double score)225 public SearchIds (int col, int concept, double score) { 226 this.col = col; 227 this.concept = concept; 228 this.score = score; 229 } 230 toString()231 public String toString() { 232 return "col=" + col + " concept=" + concept + " score=" + score; 233 } 234 } 235 } 236