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

Last change on this file since 13576 was 13270, checked in by shaoqun, 17 years ago

replace Category class which is deprecated with Logger class

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