source: main/trunk/greenstone3/src/java/org/greenstone/gsdl3/service/MapSearch.java@ 28966

Last change on this file since 28966 was 28966, checked in by kjdon, 10 years ago

Lots of changes. Mainly to do with removing this.doc from everywhere. Document is not thread safe. Now we tend to create a new Document everytime we are starting a new page/message etc. in service this.desc_doc is available as teh document to create service info stuff. But it should only be used for this and not for other messages. newDOM is now static for XMLConverter. method param changes for some GSXML methods.

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