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

Last change on this file since 30631 was 30631, checked in by kjdon, 8 years ago

getDisplayText has moved classes

  • 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(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.