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

Last change on this file since 25635 was 25635, checked in by sjm84, 12 years ago

Fixing Greenstone 3's use (or lack thereof) of generics, this was done automatically so we may want to change it over time. This change will also auto-format any files that have not already been formatted.

  • Property svn:keywords set to Author Date Id Revision
File size: 13.6 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 // Create a new (empty) result message
165 Element result = doc.createElement(GSXML.RESPONSE_ELEM);
166 result.setAttribute(GSXML.FROM_ATT, QUERY_SERVICE);
167 result.setAttribute(GSXML.TYPE_ATT, GSXML.REQUEST_TYPE_PROCESS);
168
169 // Get the parameters of the request
170 Element param_list = (Element) GSXML.getChildByTagName(request, GSXML.PARAM_ELEM+GSXML.LIST_MODIFIER);
171 if (param_list == null) {
172 logger.error("TextQuery request had no paramList.");
173 return result; // Return the empty result
174 }
175
176 // Process the request parameters
177 HashMap<String, Serializable> params = GSXML.extractParams(param_list, false);
178
179 // Make sure a query has been specified
180 String searchTerm = (String) params.get(QUERY_PARAM);
181 if (searchTerm == null || searchTerm.equals("")) {
182 return result; // Return the empty result
183 }
184
185 // If an index hasn't been specified, use the default
186// String index = (String) params.get(INDEX_PARAM);
187// if (index == null) {
188// index = default_index;
189// }
190
191 //convert the query string from the form '&quotTe Awamutu&quot Hamilton' to 'Te Awamutu+Hamilton'
192
193 //replace ' ' with '+'
194 searchTerm = searchTerm.replace(' ','+');
195
196 //replace '&quot' with '"'
197 int place = -1;
198 while(searchTerm.indexOf("&quot;",place+1) != -1){
199 place = searchTerm.indexOf("&quot;",place+1);
200 searchTerm = (searchTerm.substring(0,place) + "\"" + searchTerm.substring(place+6,searchTerm.length()));
201 }
202
203 //replace spaces in string enclosed in quotes
204 place = -1;
205 while(searchTerm.indexOf('"',place+1) != -1){
206 place = searchTerm.indexOf('"',place+1);
207 if(searchTerm.indexOf('"',place+1) != -1)
208 searchTerm = (searchTerm.substring(0,place) + searchTerm.substring(place, searchTerm.indexOf('"',place+1)).replace('+',' ') + searchTerm.substring(searchTerm.indexOf('"',place+1), searchTerm.length()));
209 place = searchTerm.indexOf('"',place);
210 }
211
212 //remove speech marks
213 place = 0;
214 while(place != -1){
215 place = searchTerm.indexOf('"', place);
216 if(place != -1){
217 searchTerm = searchTerm.substring(0, place) + searchTerm.substring(place+1, searchTerm.length());
218 place=0;
219 }
220 }
221
222 //find the number of search terms (number of '+' plus 1)
223 int words = 1;
224 place = 0;
225 while (place != -1){
226 place = searchTerm.indexOf('+', place+1);
227 if(place != -1) words++;
228 }
229 place = 0;
230
231 //store each search term in a string array
232 String terms[] = new String[words];
233 String terms_freq[] = new String[words];
234 for (int i=0; i<(words-1); i++){
235 terms[i]=searchTerm.substring(place, searchTerm.indexOf('+', place));
236 place = searchTerm.indexOf('+', place)+1;
237 }
238 terms[words-1] = searchTerm.substring(place, searchTerm.length());
239
240 Object nameArray[] = new Object[1];
241 int nameArraySize;
242 String nameData;
243 double xco, yco;
244 LinkedList<Object> mapList = new LinkedList<Object>();
245 LinkedList placeList = new LinkedList();
246 String readString = "";
247
248 //capitalise the search terms
249 for(int i=0;i<words;i++)
250 terms[i] = terms[i].toUpperCase();
251
252 for(int k=0; k<words; k++){
253 nameArraySize=0;
254
255
256 if((nameArray = (Object[])hashNames.get(terms[k].toLowerCase())) != null){
257 logger.debug(hashNames.get(terms[k].toLowerCase()));
258
259 nameArraySize = Arrays.asList(nameArray).size();
260 }
261
262
263 int h;
264 for(h=0;h<nameArraySize;h++){
265
266 nameData = (String)nameArray[h];
267
268 // get the co-ordinates of the current place name
269 xco = Double.parseDouble(nameData.substring(nameData.lastIndexOf('`')+1,nameData.length()));
270 yco = Double.parseDouble(nameData.substring(nameData.lastIndexOf('`',nameData.lastIndexOf('`')-1)+2,nameData.lastIndexOf('`')));
271
272 //open the text file containing map metadata (first line is a description of the file)
273 try{
274 BufferedReader inmap = new BufferedReader(new FileReader(this.files_home_dir + "files"+File.separator+"maps"+File.separator+"mapdata.txt"));
275 inmap.readLine();
276
277 // for each map
278 while(inmap.ready()){
279 readString = inmap.readLine();
280 int indexer = 0;
281 indexer = readString.indexOf('`')+2;
282 // get the co-ordinates of the top left and bottom right corners of the map.
283 double ytop = Double.parseDouble(readString.substring(indexer,indexer+5));
284 indexer = readString.indexOf('`',indexer)+1;
285 double xtop = Double.parseDouble(readString.substring(indexer,indexer+6));
286 indexer = readString.indexOf('`',indexer)+2;
287 double ybot = Double.parseDouble(readString.substring(indexer,indexer+5));
288 indexer = readString.indexOf('`',indexer)+1;
289 double xbot = Double.parseDouble(readString.substring(indexer,indexer+6));
290
291 //if the place is within the map, put the map metadata and the placename metadata in linked list
292 if(xco >= xtop && xco < xbot && yco >= ytop && yco < ybot)
293 mapList.add(readString+"```"+nameData);
294 }
295 }catch(Exception e){e.printStackTrace();}
296 }
297 }
298
299 // use an array object to sort the linked list by map number
300 Object[] mapListArray = mapList.toArray();
301 Arrays.sort(mapListArray);
302 mapList.clear();
303 for(int mla=0; mla<Array.getLength(mapListArray); mla++)
304 mapList.addFirst(mapListArray[mla]);
305
306 //for each map, create a list of the query matches on that map
307 LinkedList<Object> tempList = new LinkedList<Object>();
308 String mapNumber = "";
309 String currentMap[] = {"",""};
310 int mapFreq = 0;
311 while(mapList.size()>0){
312 readString = (String)mapList.removeFirst();
313 if(mapNumber.equals(readString.substring(0,readString.indexOf('.')))){
314 currentMap[1] = currentMap[1]+readString.substring(readString.indexOf("```"),readString.length());
315 mapFreq++;
316 }
317 else{
318 if(!currentMap[0].equals(""))
319 tempList.add(currentMap[0]+"`"+mapFreq+currentMap[1]);
320 currentMap[0] = readString.substring(0,readString.indexOf("```"));
321 currentMap[1] = readString.substring(readString.indexOf("```"),readString.length());
322 mapNumber = readString.substring(0,readString.indexOf('.'));
323 mapFreq=1;
324 }
325 }
326 if(!currentMap[0].equals(""))
327 tempList.add(currentMap[0]+"`"+mapFreq+currentMap[1]);
328
329 int totalDocs = tempList.size();
330
331 // use an array object to sort the linked list by number of matches on each map
332 Object[] tempListArray = tempList.toArray();
333 Arrays.sort(tempListArray, new MapResultSorter());
334 tempList.clear();
335 for(int tla=0; tla<Array.getLength(tempListArray); tla++)
336 tempList.add(tempListArray[tla]);
337
338 // Create a metadata list to store information about the query results
339 Element metadata_list = doc.createElement(GSXML.METADATA_ELEM+GSXML.LIST_MODIFIER);
340 result.appendChild(metadata_list);
341
342 // Add a metadata element specifying the number of matching documents
343 GSXML.addMetadata(this.doc, metadata_list, "numDocsMatched", "" + totalDocs);
344 GSXML.addMetadata(this.doc, metadata_list, "numDocsReturned", ""+totalDocs);
345 // Create a document list to store the matching documents, and add them
346 Element document_list = doc.createElement(GSXML.DOC_NODE_ELEM+GSXML.LIST_MODIFIER);
347 result.appendChild(document_list);
348 for (int d = 0; d < totalDocs; d++) {
349 String doc_id = (String)tempList.get(d);
350
351 Element doc_node = doc.createElement(GSXML.DOC_NODE_ELEM);
352 doc_node.setAttribute(GSXML.NODE_ID_ATT, doc_id);
353 doc_node.setAttribute(GSXML.NODE_TYPE_ATT, "thumbnail");
354 doc_node.setAttribute(GSXML.DOC_TYPE_ATT, "map");
355 document_list.appendChild(doc_node);
356 }
357
358 // Create a term list to store the term information, and add it
359 Element term_list = doc.createElement(GSXML.TERM_ELEM+GSXML.LIST_MODIFIER);
360 result.appendChild(term_list);
361
362
363 for (int t=0; t<words; t++){
364 String term = terms[t];
365
366 Element term_elem = doc.createElement(GSXML.TERM_ELEM);
367 term_elem.setAttribute(GSXML.NAME_ATT, term);
368 term_elem.setAttribute(FREQ_ATT, "" + terms_freq[t]);
369
370 term_list.appendChild(term_elem);
371 }
372 return result;
373 }
374
375
376 public class MapResultSorter implements Comparator {
377
378 public int compare(Object o1, Object o2) {
379 String first = (String)o1;
380 String second = (String) o2;
381 int firstInt;
382 int secondInt;
383 first = first.substring(first.lastIndexOf('`',first.indexOf("```")-1)+1,first.indexOf("```"));
384 second = second.substring(second.lastIndexOf('`',second.indexOf("```")-1)+1,second.indexOf("```"));
385 firstInt = Integer.parseInt(first);
386 secondInt = Integer.parseInt(second);
387 if(firstInt > secondInt)
388 return -1;
389 else if(firstInt == secondInt)
390 return 0;
391 else
392 return 1;
393 }
394 }
395}
Note: See TracBrowser for help on using the repository browser.