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