source: trunk/gsdl3/src/java/org/greenstone/gsdl3/service/MapSearch.java@ 9286

Last change on this file since 9286 was 9286, checked in by kjdon, 19 years ago

renamed MapQuery to MapSearch, and it now inherits from AbstractSearch instead of ServiceRack

  • Property svn:keywords set to Author Date Id Revision
File size: 13.4 KB
Line 
1/*
2 * MapSearch.java
3 * Copyright (C) 2005 New Zealand Digital Library, http://www.nzdl.org
4 *
5 * This program is free software; you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License as published by
7 * the Free Software Foundation; either version 2 of the License, or
8 * (at your option) any later version.
9 *
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU General Public License for more details.
14 *
15 * You should have received a copy of the GNU General Public License
16 * along with this program; if not, write to the Free Software
17 * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
18 */
19package org.greenstone.gsdl3.service;
20
21// Greenstone classes
22import org.greenstone.gdbm.*;
23import org.greenstone.gsdl3.util.*;
24
25// XML classes
26import org.w3c.dom.Element;
27import org.w3c.dom.Document;
28import org.w3c.dom.NodeList;
29
30// General java classes
31import java.util.Hashtable;
32import java.util.HashMap;
33import java.util.Arrays;
34import java.util.ArrayList;
35import java.util.LinkedList;
36import java.lang.reflect.Array;
37import java.util.Comparator;
38import java.io.BufferedReader;
39import java.io.FileReader;
40import java.io.File;
41import java.io.IOException;
42import java.io.ObjectInputStream;
43import java.io.FileInputStream;
44import java.lang.ClassNotFoundException;
45
46/**
47 *
48 *
49 */
50public class MapSearch
51 extends AbstractSearch {
52
53 protected String files_home_dir = null;
54
55 protected static final String FREQ_ATT = "freq";
56
57 // use the following if we add back in index searching
58 //protected String default_index = null;
59 //protected static final String DEFAULT_INDEX_ELEM = "defaultIndex";
60 //protected static final String INDEX_ELEM = "index";
61
62 /** Hashtable containing the place names database, indexed on the place name in lower case. */
63 public static Hashtable hashNames;
64
65 /** Constructor */
66 public MapSearch() {}
67
68 /** */
69 public boolean configure(Element info, Element extra_info)
70 {
71 if (!super.configure(info, extra_info)) {
72 return false;
73 }
74 System.out.println("Configuring MapSearch...");
75
76 // set the files_home_dir variable for this collection
77 this.files_home_dir = GSFile.collectionIndexDir(site_home, cluster_name)+File.separator+"assoc"+File.separator;
78
79 //load the hashtable
80 hashNames = new Hashtable();
81 try{
82 ObjectInputStream in = new ObjectInputStream(new FileInputStream(this.files_home_dir+"hashnames.dat"));
83 hashNames = (Hashtable)in.readObject();
84 in.close();
85 }catch(IOException ioe){
86 ioe.printStackTrace();
87 return false;
88 }catch(ClassNotFoundException cnf){
89 cnf.printStackTrace();
90 return false;
91 }
92
93 // just in case we get the index stuff going, here is the code
94
95 // get the display stuff for the indexes
96
97// NodeList indexes = info.getElementsByTagName(GSXML.INDEX_ELEM);
98// if (extra_info != null) {
99// Document owner = info.getOwnerDocument();
100// Element config_search = (Element)GSXML.getChildByTagName(extra_info, GSXML.SEARCH_ELEM);
101// if (config_search != null) {
102// for (int i=0; i<indexes.getLength();i++) {
103// Element ind = (Element)indexes.item(i);
104// String name = ind.getAttribute(GSXML.NAME_ATT);
105// Element node_extra = GSXML.getNamedElement(config_search,
106// GSXML.INDEX_ELEM,
107// GSXML.NAME_ATT,
108// name);
109// if (node_extra == null) {
110// // no index specification for this index
111// continue;
112// }
113
114// // get the display elements if any - displayName
115// NodeList display_names = node_extra.getElementsByTagName(GSXML.DISPLAY_TEXT_ELEM);
116// if (display_names !=null) {
117// for (int j=0; j<display_names.getLength(); j++) {
118// Element e = (Element)display_names.item(j);
119// ind.appendChild(owner.importNode(e, true));
120// }
121// }
122// } // for each index
123// }
124// }
125// // Get the default index out of <defaultIndex> (buildConfig.xml)
126// Element def = (Element) GSXML.getChildByTagName(info, DEFAULT_INDEX_ELEM);
127// if (def != null) {
128// default_index = def.getAttribute(GSXML.NAME_ATT);
129// }
130// if (default_index == null || default_index.equals("")) {
131// // use the first one from the index list
132// default_index = ((Element)indexes.item(0)).getAttribute(GSXML.NAME_ATT);
133// }
134
135 return true;
136 }
137
138 protected void getIndexData(ArrayList index_ids, ArrayList index_names, String lang)
139 {
140 // for now, we just have one dummy index
141 index_ids.add("idx");
142 index_names.add("maps"); // get from properties
143
144 // use the following if we ever get the index search working
145// Element index_list = (Element)GSXML.getChildByTagName(this.config_info, INDEX_ELEM+GSXML.LIST_MODIFIER);
146// NodeList indexes = index_list.getElementsByTagName(INDEX_ELEM);
147// for (int i=0; i<indexes.getLength(); i++) {
148// Element index = (Element)indexes.item(i);
149// index_ids.add( index.getAttribute(GSXML.NAME_ATT));
150// index_names.add(GSXML.getDisplayText(index, GSXML.DISPLAY_TEXT_NAME, lang, "en"));
151
152// }
153 }
154
155
156 /** Process a map query */
157 protected Element processTextQuery(Element request)
158 {
159 // Create a new (empty) result message
160 Element result = doc.createElement(GSXML.RESPONSE_ELEM);
161 result.setAttribute(GSXML.FROM_ATT, TEXT_QUERY_SERVICE);
162 result.setAttribute(GSXML.TYPE_ATT, GSXML.REQUEST_TYPE_PROCESS);
163
164 // Get the parameters of the request
165 Element param_list = (Element) GSXML.getChildByTagName(request, GSXML.PARAM_ELEM+GSXML.LIST_MODIFIER);
166 if (param_list == null) {
167 System.err.println("Error: TextQuery request had no paramList.");
168 return result; // Return the empty result
169 }
170
171 // Process the request parameters
172 HashMap params = GSXML.extractParams(param_list, false);
173
174 // Make sure a query has been specified
175 String searchTerm = (String) params.get(QUERY_PARAM);
176 if (searchTerm == null || searchTerm.equals("")) {
177 return result; // Return the empty result
178 }
179
180 // If an index hasn't been specified, use the default
181// String index = (String) params.get(INDEX_PARAM);
182// if (index == null) {
183// index = default_index;
184// }
185
186 //convert the query string from the form '&quotTe Awamutu&quot Hamilton' to 'Te Awamutu+Hamilton'
187
188 //replace ' ' with '+'
189 searchTerm = searchTerm.replace(' ','+');
190
191 //replace '&quot' with '"'
192 int place = -1;
193 while(searchTerm.indexOf("&quot;",place+1) != -1){
194 place = searchTerm.indexOf("&quot;",place+1);
195 searchTerm = (searchTerm.substring(0,place) + "\"" + searchTerm.substring(place+6,searchTerm.length()));
196 }
197
198 //replace spaces in string enclosed in quotes
199 place = -1;
200 while(searchTerm.indexOf('"',place+1) != -1){
201 place = searchTerm.indexOf('"',place+1);
202 if(searchTerm.indexOf('"',place+1) != -1)
203 searchTerm = (searchTerm.substring(0,place) + searchTerm.substring(place, searchTerm.indexOf('"',place+1)).replace('+',' ') + searchTerm.substring(searchTerm.indexOf('"',place+1), searchTerm.length()));
204 place = searchTerm.indexOf('"',place);
205 }
206
207 //remove speech marks
208 place = 0;
209 while(place != -1){
210 place = searchTerm.indexOf('"', place);
211 if(place != -1){
212 searchTerm = searchTerm.substring(0, place) + searchTerm.substring(place+1, searchTerm.length());
213 place=0;
214 }
215 }
216
217 //find the number of search terms (number of '+' plus 1)
218 int words = 1;
219 place = 0;
220 while (place != -1){
221 place = searchTerm.indexOf('+', place+1);
222 if(place != -1) words++;
223 }
224 place = 0;
225
226 //store each search term in a string array
227 String terms[] = new String[words];
228 String terms_freq[] = new String[words];
229 for (int i=0; i<(words-1); i++){
230 terms[i]=searchTerm.substring(place, searchTerm.indexOf('+', place));
231 place = searchTerm.indexOf('+', place)+1;
232 }
233 terms[words-1] = searchTerm.substring(place, searchTerm.length());
234
235 Object nameArray[] = new Object[1];
236 int nameArraySize;
237 String nameData;
238 double xco, yco;
239 LinkedList mapList = new LinkedList();
240 LinkedList placeList = new LinkedList();
241 String readString = "";
242
243 //capitalise the search terms
244 for(int i=0;i<words;i++)
245 terms[i] = terms[i].toUpperCase();
246
247 for(int k=0; k<words; k++){
248 nameArraySize=0;
249
250
251 if((nameArray = (Object[])hashNames.get(terms[k].toLowerCase())) != null){
252 //System.out.println(hashNames.get(terms[k].toLowerCase()));
253
254 nameArraySize = Arrays.asList(nameArray).size();
255 }
256
257
258 int h;
259 for(h=0;h<nameArraySize;h++){
260
261 nameData = (String)nameArray[h];
262
263 // get the co-ordinates of the current place name
264 xco = Double.parseDouble(nameData.substring(nameData.lastIndexOf('`')+1,nameData.length()));
265 yco = Double.parseDouble(nameData.substring(nameData.lastIndexOf('`',nameData.lastIndexOf('`')-1)+2,nameData.lastIndexOf('`')));
266
267 //open the text file containing map metadata (first line is a description of the file)
268 try{
269 BufferedReader inmap = new BufferedReader(new FileReader(this.files_home_dir + "files"+File.separator+"maps"+File.separator+"mapdata.txt"));
270 inmap.readLine();
271
272 // for each map
273 while(inmap.ready()){
274 readString = inmap.readLine();
275 int indexer = 0;
276 indexer = readString.indexOf('`')+2;
277 // get the co-ordinates of the top left and bottom right corners of the map.
278 double ytop = Double.parseDouble(readString.substring(indexer,indexer+5));
279 indexer = readString.indexOf('`',indexer)+1;
280 double xtop = Double.parseDouble(readString.substring(indexer,indexer+6));
281 indexer = readString.indexOf('`',indexer)+2;
282 double ybot = Double.parseDouble(readString.substring(indexer,indexer+5));
283 indexer = readString.indexOf('`',indexer)+1;
284 double xbot = Double.parseDouble(readString.substring(indexer,indexer+6));
285
286 //if the place is within the map, put the map metadata and the placename metadata in linked list
287 if(xco >= xtop && xco < xbot && yco >= ytop && yco < ybot)
288 mapList.add(readString+"```"+nameData);
289 }
290 }catch(Exception e){e.printStackTrace();}
291 }
292 }
293
294 // use an array object to sort the linked list by map number
295 Object[] mapListArray = mapList.toArray();
296 Arrays.sort(mapListArray);
297 mapList.clear();
298 for(int mla=0; mla<Array.getLength(mapListArray); mla++)
299 mapList.addFirst(mapListArray[mla]);
300
301 //for each map, create a list of the query matches on that map
302 LinkedList tempList = new LinkedList();
303 String mapNumber = "";
304 String currentMap[] = {"",""};
305 int mapFreq = 0;
306 while(mapList.size()>0){
307 readString = (String)mapList.removeFirst();
308 if(mapNumber.equals(readString.substring(0,readString.indexOf('.')))){
309 currentMap[1] = currentMap[1]+readString.substring(readString.indexOf("```"),readString.length());
310 mapFreq++;
311 }
312 else{
313 if(!currentMap[0].equals(""))
314 tempList.add(currentMap[0]+"`"+mapFreq+currentMap[1]);
315 currentMap[0] = readString.substring(0,readString.indexOf("```"));
316 currentMap[1] = readString.substring(readString.indexOf("```"),readString.length());
317 mapNumber = readString.substring(0,readString.indexOf('.'));
318 mapFreq=1;
319 }
320 }
321 if(!currentMap[0].equals(""))
322 tempList.add(currentMap[0]+"`"+mapFreq+currentMap[1]);
323
324 int totalDocs = tempList.size();
325
326 // use an array object to sort the linked list by number of matches on each map
327 Object[] tempListArray = tempList.toArray();
328 Arrays.sort(tempListArray, new MapResultSorter());
329 tempList.clear();
330 for(int tla=0; tla<Array.getLength(tempListArray); tla++)
331 tempList.add(tempListArray[tla]);
332
333 // Create a metadata list to store information about the query results
334 Element metadata_list = doc.createElement(GSXML.METADATA_ELEM+GSXML.LIST_MODIFIER);
335 result.appendChild(metadata_list);
336
337 // Add a metadata element specifying the number of matching documents
338 GSXML.addMetadata(this.doc, metadata_list, "numDocsMatched", "" + totalDocs);
339 GSXML.addMetadata(this.doc, metadata_list, "numDocsReturned", ""+totalDocs);
340 // Create a document list to store the matching documents, and add them
341 Element document_list = doc.createElement(GSXML.DOC_NODE_ELEM+GSXML.LIST_MODIFIER);
342 result.appendChild(document_list);
343 for (int d = 0; d < totalDocs; d++) {
344 String doc_id = (String)tempList.get(d);
345
346 Element doc_node = doc.createElement(GSXML.DOC_NODE_ELEM);
347 doc_node.setAttribute(GSXML.NODE_ID_ATT, doc_id);
348 doc_node.setAttribute(GSXML.NODE_TYPE_ATT, "thumbnail");
349 doc_node.setAttribute(GSXML.DOC_TYPE_ATT, "map");
350 document_list.appendChild(doc_node);
351 }
352
353 // Create a term list to store the term information, and add it
354 Element term_list = doc.createElement(GSXML.TERM_ELEM+GSXML.LIST_MODIFIER);
355 result.appendChild(term_list);
356
357
358 for (int t=0; t<words; t++){
359 String term = terms[t];
360
361 Element term_elem = doc.createElement(GSXML.TERM_ELEM);
362 term_elem.setAttribute(GSXML.NAME_ATT, term);
363 term_elem.setAttribute(FREQ_ATT, "" + terms_freq[t]);
364
365 term_list.appendChild(term_elem);
366 }
367 return result;
368 }
369
370
371 public class MapResultSorter implements Comparator {
372
373 public int compare(Object o1, Object o2) {
374 String first = (String)o1;
375 String second = (String) o2;
376 int firstInt;
377 int secondInt;
378 first = first.substring(first.lastIndexOf('`',first.indexOf("```")-1)+1,first.indexOf("```"));
379 second = second.substring(second.lastIndexOf('`',second.indexOf("```")-1)+1,second.indexOf("```"));
380 firstInt = Integer.parseInt(first);
381 secondInt = Integer.parseInt(second);
382 if(firstInt > secondInt)
383 return -1;
384 else if(firstInt == secondInt)
385 return 0;
386 else
387 return 1;
388 }
389 }
390}
Note: See TracBrowser for help on using the repository browser.