source: trunk/gsdl3/src/java/org/greenstone/gsdl3/service/GS3Retrieve.java@ 6517

Last change on this file since 6517 was 6517, checked in by kjdon, 20 years ago

now classifiers work, and searching works, and hierarchical docs work

  • Property svn:keywords set to Author Date Id Revision
File size: 32.8 KB
Line 
1/*
2 * GS3Retrieve.java
3 * Copyright (C) 2002 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
22// Greenstone classes
23import org.greenstone.gdbm.*;
24import org.greenstone.gsdl3.util.*;
25
26// XML classes
27import org.w3c.dom.Document;
28import org.w3c.dom.Element;
29import org.w3c.dom.NodeList;
30
31// General Java classes
32import java.io.File;
33import java.util.StringTokenizer;
34import java.util.Vector;
35import java.util.Set;
36import java.util.Iterator;
37import java.util.ArrayList;
38
39/** Implements the generic retrieval and classifier services for GS3
40 * collections.
41 *
42 * @author <a href="mailto:[email protected]">Katherine Don</a>
43 * @author <a href="mailto:[email protected]">Michael Dewsnip</a>
44 * @version $Revision: 6517 $
45 */
46
47public abstract class GS3Retrieve
48 extends ServiceRack {
49
50 // the services on offer
51 // these strings must match what is found in the properties file
52 protected static final String DOCUMENT_STRUCTURE_RETRIEVE_SERVICE = "DocumentStructureRetrieve";
53 protected static final String DOCUMENT_METADATA_RETRIEVE_SERVICE = "DocumentMetadataRetrieve";
54 protected static final String DOCUMENT_CONTENT_RETRIEVE_SERVICE = "DocumentContentRetrieve";
55
56
57 // the browsing services - now in here, these will only be advertised if classifiers have been specified in the config file
58 private static final String CLASSIFIER_SERVICE = "ClassifierBrowse";
59 private static final String CLASSIFIER_METADATA_SERVICE = "ClassifierBrowseMetadataRetrieve";
60
61 protected static final String STRUCT_PARAM = "structure";
62 protected static final String INFO_PARAM = "info";
63
64 protected static final String STRUCT_ANCESTORS = "ancestors";
65 protected static final String STRUCT_PARENT = "parent";
66 protected static final String STRUCT_SIBS = "siblings";
67 protected static final String STRUCT_CHILDREN = "children";
68 protected static final String STRUCT_DESCENDS = "descendants";
69 protected static final String STRUCT_ENTIRE = "entire";
70
71 protected static final String INFO_NUM_SIBS = "numSiblings";
72 protected static final String INFO_NUM_CHILDREN = "numChildren";
73 protected static final String INFO_SIB_POS = "siblingPosition";
74
75 protected static final int DOCUMENT=1;
76 protected static final int CLASSIFIER=2;
77
78 //protected GDBMWrapper gdbm_src = null;
79 protected SQLQuery database = null;
80
81 protected Element config_info = null; // the xml from the config file
82
83 /** constructor */
84 protected GS3Retrieve()
85 {
86 //this.gdbm_src = new GDBMWrapper();
87 this.database = new SQLQuery();
88 }
89
90
91 /** configure this service */
92 public boolean configure(Element info, Element extra_info)
93 {
94 System.out.println("Configuring GS3Retrieve...");
95 this.config_info = info;
96
97 // set up short_service_info_ - for now just has name and type
98 Element dsr_service = this.doc.createElement(GSXML.SERVICE_ELEM);
99 dsr_service.setAttribute(GSXML.TYPE_ATT, GSXML.SERVICE_TYPE_RETRIEVE);
100 dsr_service.setAttribute(GSXML.NAME_ATT, DOCUMENT_STRUCTURE_RETRIEVE_SERVICE);
101 this.short_service_info.appendChild(dsr_service);
102
103 Element dmr_service = this.doc.createElement(GSXML.SERVICE_ELEM);
104 dmr_service.setAttribute(GSXML.TYPE_ATT, GSXML.SERVICE_TYPE_RETRIEVE);
105 dmr_service.setAttribute(GSXML.NAME_ATT, DOCUMENT_METADATA_RETRIEVE_SERVICE);
106 this.short_service_info.appendChild(dmr_service);
107
108 Element dcr_service = this.doc.createElement(GSXML.SERVICE_ELEM);
109 dcr_service.setAttribute(GSXML.TYPE_ATT, GSXML.SERVICE_TYPE_RETRIEVE);
110 dcr_service.setAttribute(GSXML.NAME_ATT, DOCUMENT_CONTENT_RETRIEVE_SERVICE);
111 this.short_service_info.appendChild(dcr_service);
112
113 if (!database.setDatabase(this.cluster_name)) {
114 System.err.println("GS3Search Error: Could not open SQL database!");
115 return false;
116 }
117
118 // now do the classifier browse service
119
120 // check that there are classifiers specified
121 Element class_list = (Element)GSXML.getChildByTagName(info, GSXML.CLASSIFIER_ELEM+GSXML.LIST_MODIFIER);
122 if (class_list == null) {
123 // no classifiers specified
124 return true;
125 }
126
127 // get the display and format elements from the coll config file for
128 // the classifiers
129 extractExtraClassifierInfo(info, extra_info);
130
131 this.config_info = info;
132
133 // short_service_info_ - the browse one
134 Element cb_service = this.doc.createElement(GSXML.SERVICE_ELEM);
135 cb_service.setAttribute(GSXML.TYPE_ATT, GSXML.SERVICE_TYPE_BROWSE);
136 cb_service.setAttribute(GSXML.NAME_ATT, CLASSIFIER_SERVICE);
137 this.short_service_info.appendChild(cb_service);
138
139 // metadata retrieval for the browsing
140 Element cbmr_service = this.doc.createElement(GSXML.SERVICE_ELEM);
141 cbmr_service.setAttribute(GSXML.TYPE_ATT, GSXML.SERVICE_TYPE_RETRIEVE);
142 cbmr_service.setAttribute(GSXML.NAME_ATT, CLASSIFIER_METADATA_SERVICE);
143 this.short_service_info.appendChild(cbmr_service);
144
145 // the format info
146 Element cb_format_info = this.doc.createElement(GSXML.FORMAT_ELEM);
147 boolean format_found = false;
148 // add in to the description a simplified list of classifiers
149 NodeList classifiers = class_list.getElementsByTagName(GSXML.CLASSIFIER_ELEM);
150 for(int i=0; i<classifiers.getLength(); i++) {
151 Element cl = (Element)classifiers.item(i);
152 Element new_cl = (Element)this.doc.importNode(cl, false); // just import this node, not the children
153
154 // get the format info out, and put inside a classifier element
155 Element format_cl = (Element)new_cl.cloneNode(false);
156 Element format = (Element)GSXML.getChildByTagName(cl, GSXML.FORMAT_ELEM);
157 if (format != null) {
158
159 //copy all the children
160 NodeList elems = format.getChildNodes();
161 for (int j=0; j<elems.getLength();j++) {
162 format_cl.appendChild(this.doc.importNode(elems.item(j), true));
163 }
164 cb_format_info.appendChild(format_cl);
165 format_found = true;
166 }
167
168
169 }
170
171 if (format_found) {
172 this.format_info_map.put(CLASSIFIER_SERVICE, cb_format_info);
173 }
174
175 // look for document display format
176 String path = GSPath.appendLink(GSXML.DISPLAY_ELEM, GSXML.FORMAT_ELEM);
177 Element display_format = (Element)GSXML.getNodeByPath(extra_info, path);
178 if (display_format != null) {
179 this.format_info_map.put(DOCUMENT_CONTENT_RETRIEVE_SERVICE, this.doc.importNode(display_format, true));
180 // should we make a copy?
181 }
182 return true;
183 }
184
185 protected Element getServiceDescription(String service_id, String lang, String subset) {
186
187 if (service_id.equals(CLASSIFIER_SERVICE)) {
188
189 Element class_list = (Element)GSXML.getChildByTagName(this.config_info, GSXML.CLASSIFIER_ELEM+GSXML.LIST_MODIFIER);
190 if (class_list == null) {
191 // no classifiers specified
192 return null;
193 }
194
195 Element cb_service = this.doc.createElement(GSXML.SERVICE_ELEM);
196 cb_service.setAttribute(GSXML.TYPE_ATT, GSXML.SERVICE_TYPE_BROWSE);
197 cb_service.setAttribute(GSXML.NAME_ATT, CLASSIFIER_SERVICE);
198 cb_service.appendChild(GSXML.createDisplayTextElement(this.doc, GSXML.DISPLAY_TEXT_NAME, getTextString(CLASSIFIER_SERVICE+".name", lang)));
199 cb_service.appendChild(GSXML.createDisplayTextElement(this.doc, GSXML.DISPLAY_TEXT_DESCRIPTION, getTextString(CLASSIFIER_SERVICE+".description", lang)));
200
201 Element cl_list = this.doc.createElement(GSXML.CLASSIFIER_ELEM+GSXML.LIST_MODIFIER);
202 cb_service.appendChild(cl_list);
203 NodeList classifiers = class_list.getElementsByTagName(GSXML.CLASSIFIER_ELEM);
204 for(int i=0; i<classifiers.getLength(); i++) {
205 Element cl = (Element)classifiers.item(i);
206 Element new_cl = (Element)this.doc.importNode(cl, false); // just import this node, not the children
207 String content = cl.getAttribute(GSXML.CLASSIFIER_CONTENT_ATT);
208 cl_list.appendChild(new_cl);
209 String text = GSXML.getDisplayText(cl,
210 GSXML.DISPLAY_TEXT_NAME,
211 lang, "en");
212 if (text == null || text.equals("")) {
213 // no display element was specified, use the metadata name
214 // for now this looks in the class properties file
215 // this needs to use a general metadata thing instead
216 text = getMetadataNameText(content+".buttonname", lang);
217 }
218 if (text == null) {
219 text = content;
220 }
221
222 Element cl_name = GSXML.createDisplayTextElement(this.doc, GSXML.DISPLAY_TEXT_NAME, text);
223 new_cl.appendChild(cl_name);
224
225 // description
226
227 String meta_name = getMetadataNameText(content, lang);
228 if (meta_name==null) {
229 meta_name = content;
230 }
231 String [] array = {meta_name};
232 String description = getTextString("ClassifierBrowse.classifier_help", array, lang);
233 Element cl_desc = GSXML.createDisplayTextElement(this.doc, GSXML.DISPLAY_TEXT_DESCRIPTION, description);
234 new_cl.appendChild(cl_desc);
235
236 }
237 return cb_service;
238 }
239
240 // these ones are probably never called, but put them here just in case
241
242 if (service_id.equals(CLASSIFIER_METADATA_SERVICE)) {
243
244 Element cbmr_service = this.doc.createElement(GSXML.SERVICE_ELEM);
245 cbmr_service.setAttribute(GSXML.TYPE_ATT, GSXML.SERVICE_TYPE_RETRIEVE);
246 cbmr_service.setAttribute(GSXML.NAME_ATT, CLASSIFIER_METADATA_SERVICE);
247 return cbmr_service;
248 }
249
250 if (service_id.equals(DOCUMENT_STRUCTURE_RETRIEVE_SERVICE)) {
251 Element dsr_service = this.doc.createElement(GSXML.SERVICE_ELEM);
252 dsr_service.setAttribute(GSXML.TYPE_ATT, GSXML.SERVICE_TYPE_RETRIEVE);
253 dsr_service.setAttribute(GSXML.NAME_ATT, DOCUMENT_STRUCTURE_RETRIEVE_SERVICE);
254 return dsr_service;
255 }
256 if (service_id.equals(DOCUMENT_METADATA_RETRIEVE_SERVICE)) {
257 Element dmr_service = this.doc.createElement(GSXML.SERVICE_ELEM);
258 dmr_service.setAttribute(GSXML.TYPE_ATT, GSXML.SERVICE_TYPE_RETRIEVE);
259 dmr_service.setAttribute(GSXML.NAME_ATT, DOCUMENT_METADATA_RETRIEVE_SERVICE);
260 return dmr_service;
261 }
262
263 if (service_id.equals(DOCUMENT_CONTENT_RETRIEVE_SERVICE)) {
264 Element dcr_service = this.doc.createElement(GSXML.SERVICE_ELEM);
265 dcr_service.setAttribute(GSXML.TYPE_ATT, GSXML.SERVICE_TYPE_RETRIEVE);
266 dcr_service.setAttribute(GSXML.NAME_ATT, DOCUMENT_CONTENT_RETRIEVE_SERVICE);
267 return dcr_service;
268 }
269
270 return null;
271 }
272
273 /** this looks for any classifier specific display or format info from extra_info and adds it in to the correct place in info */
274 protected boolean extractExtraClassifierInfo(Element info, Element extra_info) {
275
276 if (extra_info == null) {
277 return false;
278 }
279
280 Document owner = info.getOwnerDocument();
281 // so far we have display and format elements that we need for classifiers
282 NodeList classifiers = info.getElementsByTagName(GSXML.CLASSIFIER_ELEM);
283 Element config_browse = (Element)GSXML.getChildByTagName(extra_info, GSXML.BROWSE_ELEM);
284
285 for (int i=0; i<classifiers.getLength();i++) {
286 Element cl = (Element)classifiers.item(i);
287 String name = cl.getAttribute(GSXML.NAME_ATT);
288 Element node_extra = GSXML.getNamedElement(config_browse,
289 GSXML.CLASSIFIER_ELEM,
290 GSXML.NAME_ATT,
291 name);
292 if (node_extra == null) {
293 System.err.println("GS3REtrieve: haven't found extra info for classifier named "+name);
294 continue;
295 }
296
297 // get the display elements if any - displayName
298 NodeList display_names = node_extra.getElementsByTagName(GSXML.DISPLAY_TEXT_ELEM);
299 if (display_names !=null) {
300 Element display = owner.createElement(GSXML.DISPLAY_ELEM);
301 for (int j=0; j<display_names.getLength(); j++) {
302 Element e = (Element)display_names.item(j);
303 cl.appendChild(owner.importNode(e, true));
304
305 }
306 }
307
308 // get the format element if any
309 Element format = (Element)GSXML.getChildByTagName(node_extra, GSXML.FORMAT_ELEM);
310 if (format==null) { // try a generic one that applies to all classifiers
311 format = (Element)GSXML.getChildByTagName(extra_info,
312 GSXML.FORMAT_ELEM);
313 }
314 if (format!=null) { // append to index info
315 cl.appendChild(owner.importNode(format, true));
316 }
317 } // for each classifier
318 return true;
319 }
320
321
322 /** parent is true if this node is definitely the parent of something,
323 * child is true is it definitely is a child of something - just for efficiency purposes */
324 protected Element createDocNode(String node_id, boolean parent, boolean child) {
325// Element node = this.doc.createElement(GSXML.DOC_NODE_ELEM);
326// node.setAttribute(GSXML.DOC_TYPE_ATT, "simple");
327// node.setAttribute(GSXML.NODE_ID_ATT, node_id);
328// return node;
329
330 Element node;
331 if (isClassifier(node_id)) {
332 node = this.doc.createElement(GSXML.CLASS_NODE_ELEM);
333 //String childtype = info.getInfo("childtype");
334 //String orientation="";
335 //if (childtype.equals("HList")) {
336 // orientation = "horizontal";
337 //} else { // assume vertical
338 // orientation = "vertical";
339 //}
340 //node.setAttribute(GSXML.CLASS_NODE_ORIENTATION_ATT, orientation);
341 } else {
342
343 node = this.doc.createElement(GSXML.DOC_NODE_ELEM);
344 node.setAttribute(GSXML.DOC_TYPE_ATT, "hierarchy"); // need to work this out dynamically
345
346 if (GS3OID.isTop(node_id)) {
347 node.setAttribute(GSXML.NODE_TYPE_ATT, GSXML.NODE_TYPE_ROOT);
348 } else if (database.documentHasChildren(node_id)){
349 node.setAttribute(GSXML.NODE_TYPE_ATT, GSXML.NODE_TYPE_INTERIOR);
350 } else {
351 node.setAttribute(GSXML.NODE_TYPE_ATT, GSXML.NODE_TYPE_LEAF);
352 }
353// String top_id = GS3OID.getTop(node_id);
354// boolean is_top = (top_id.equals(node_id) ? true : false);
355
356// String children = info.getInfo("contains");
357// boolean is_leaf = (children.equals("") ? true : false);
358
359// // set teh node type att
360// if (is_top) {
361// node.setAttribute(GSXML.NODE_TYPE_ATT, GSXML.NODE_TYPE_ROOT);
362// } else if (is_leaf) {
363// node.setAttribute(GSXML.NODE_TYPE_ATT, GSXML.NODE_TYPE_LEAF);
364// } else {
365// node.setAttribute(GSXML.NODE_TYPE_ATT, GSXML.NODE_TYPE_INTERIOR);
366// }
367
368// // set teh doc type att
369// if (is_top && is_leaf) { // a single section document
370// node.setAttribute(GSXML.DOC_TYPE_ATT, "simple");
371
372// } else {
373
374// if (!is_top) { // we need to look at the top info
375// info = this.gdbm_src.getInfo(top_id);
376// }
377
378// String childtype = info.getInfo("childtype");
379// if (childtype.equals("Paged")) {
380// node.setAttribute(GSXML.DOC_TYPE_ATT, "paged");
381// } else {
382// node.setAttribute(GSXML.DOC_TYPE_ATT, "hierarchy");
383// }
384// }
385
386 }
387 node.setAttribute(GSXML.NODE_ID_ATT, node_id);
388 return node;
389
390 }
391 /** Returns the parent of a specified documentID, or null if none exists */
392 protected Element getParent(String doc_id)
393 {
394 String parent_id = GS3OID.getParent(doc_id);
395 if (parent_id.equals(doc_id))
396 return null;
397
398 return createDocNode(parent_id, true, false);
399 }
400
401
402 /** adds all the children of doc_id the the doc element,
403 * and if recursive=true, adds all their children as well*/
404 protected void addDescendants(Element doc, String doc_id,
405 int type, boolean recursive)
406 {
407
408 if (type == DOCUMENT) {
409 ArrayList children = database.getDocumentChildren(doc_id);
410 if (children == null) return;
411 for (int i=0; i<children.size(); i++) {
412 String child_id = (String) children.get(i);
413 Element child = createDocNode(child_id, false, true);
414 doc.appendChild(child);
415 // Apply recursively, if desired
416 if (recursive) {
417 addDescendants(child, child_id, type, recursive);
418 }
419 }
420
421 }
422 else if (type == CLASSIFIER) {
423 ArrayList documents = database.getClassifierDocChildren(doc_id);
424 for (int i=0; i<documents.size(); i++) {
425 String child_id = (String) documents.get(i);
426 Element child = createDocNode(child_id, false, true);
427 doc.appendChild(child);
428 }
429 ArrayList children = database.getClassifierChildren(doc_id);
430 for (int i=0; i<children.size(); i++) {
431 String child_id = (String) children.get(i);
432 Element child = createDocNode(child_id, false, true);
433 doc.appendChild(child);
434 // Apply recursively, if desired
435 if (recursive) {
436 addDescendants(child, child_id, type, recursive);
437 }
438 }
439
440 }
441 }
442
443 /** adds all the siblings of current_id to the parent element. */
444 protected Element addSiblings(Element parent, String parent_id, String current_id) {
445 Element current_node = (Element)parent.getFirstChild();
446 if (current_node ==null) {
447 // create a sensible error message
448 System.err.println("GS3Retrieve Error: there should be a first child.");
449 return null;
450 }
451 // remove the current child,- will add it in later in its correct place
452 parent.removeChild(current_node);
453
454 // add in all the siblings,
455 addDescendants(parent, parent_id, DOCUMENT, false);
456
457 // find the node that is now the current node
458 // this assumes that the new node that was created is the same as
459 // the old one that was removed - we may want to replace the new one
460 // with the old one.
461 Element new_current = GSXML.getNamedElement(parent, current_node.getNodeName(), GSXML.NODE_ID_ATT, current_id);
462 return new_current;
463
464 }
465 /** Returns true if the OID specifies a leaf node, false otherwise
466 Note: this makes a request to the GDBM database so it may not be
467 a particularly cheap operation */
468// protected boolean isLeafNode(String oid)
469// {
470// DBInfo info = this.gdbm_src.getInfo(oid);
471// String children = info.getInfo("contains");
472// return (children.equals(""));
473// }
474
475 // for now just use CL for classifiers - should have a type?
476 protected boolean isClassifier(String oid) {
477 if (oid.startsWith("CL")) {
478 return true;
479 }
480 return false;
481 }
482
483 protected Element processDocumentStructureRetrieve(Element request) {
484 return genericStructureRetrieve(request, DOCUMENT);
485 }
486
487 protected Element processClassifierBrowse(Element request) {
488 return genericStructureRetrieve(request, CLASSIFIER);
489 }
490
491 /** Retrieve the structure of a document */
492 protected Element genericStructureRetrieve(Element request, int type)
493 {
494 // Create a new (empty) result message
495 Element result = this.doc.createElement(GSXML.RESPONSE_ELEM);
496
497 String node_name;
498 String service_name;
499 if (type==DOCUMENT) {
500 service_name = DOCUMENT_STRUCTURE_RETRIEVE_SERVICE;
501 node_name = GSXML.DOC_NODE_ELEM;
502 } else {
503 service_name = CLASSIFIER_SERVICE;
504 node_name = GSXML.CLASS_NODE_ELEM;
505 }
506
507 result.setAttribute(GSXML.FROM_ATT, service_name);
508 result.setAttribute(GSXML.TYPE_ATT, GSXML.REQUEST_TYPE_PROCESS);
509
510
511 Element query_doc_list = (Element) GSXML.getChildByTagName(request, node_name+GSXML.LIST_MODIFIER);
512 if (query_doc_list == null) {
513 System.err.println("GS3Retrieve Error: DocumentStructureRetrieve request specified no doc nodes.\n");
514 return result;
515 }
516
517 // Get the parameters of the request
518 Element param_list = (Element) GSXML.getChildByTagName(request, GSXML.PARAM_ELEM+GSXML.LIST_MODIFIER);
519 if (param_list == null) {
520 System.err.println("GS3Retrieve Error: DocumentStructureRetrieve request had no paramList.");
521 return result; // Return the empty result
522 }
523
524 // the type of info required
525 boolean want_structure = false;
526 boolean want_info = false;
527
528 Vector info_types=new Vector();
529 // The document structure information desired
530 boolean want_ancestors = false;
531 boolean want_parent = false;
532 boolean want_siblings = false;
533 boolean want_children = false;
534 boolean want_descendants = false;
535
536 boolean want_entire_structure = false;
537 // Process the request parameters
538 NodeList params = param_list.getElementsByTagName(GSXML.PARAM_ELEM);
539 for (int i=0; i<params.getLength();i++) {
540
541 Element param = (Element)params.item(i);
542 String p_name = param.getAttribute(GSXML.NAME_ATT);
543 String p_value = GSXML.getValue(param);
544 // Identify the structure information desired
545 if (p_name.equals(STRUCT_PARAM)) {
546 want_structure = true;
547
548 // This is NOT locale sensitive
549 if (p_value.equals(STRUCT_ANCESTORS))
550 want_ancestors = true;
551 else if (p_value.equals(STRUCT_PARENT))
552 want_parent = true;
553 else if (p_value.equals(STRUCT_SIBS))
554 want_siblings = true;
555 else if (p_value.equals(STRUCT_CHILDREN))
556 want_children = true;
557 else if (p_value.equals(STRUCT_DESCENDS))
558 want_descendants = true;
559 else if (p_value.equals(STRUCT_ENTIRE))
560 want_entire_structure = true;
561 else
562 System.err.println("GS3Retrieve Warning: Unknown value \"" + p_value + "\".");
563 } else if (p_name.equals(INFO_PARAM)) {
564 want_info = true;
565 info_types.add(p_value);
566 }
567 }
568
569 // Make sure there is no repeated information
570 if (want_ancestors)
571 want_parent = false;
572 if (want_descendants)
573 want_children = false;
574
575
576
577 Element doc_list = this.doc.createElement(node_name+GSXML.LIST_MODIFIER);
578 result.appendChild(doc_list);
579
580 // Get the documents
581 String[] doc_ids = GSXML.getAttributeValuesFromList(query_doc_list,
582 GSXML.NODE_ID_ATT);
583 for (int i = 0; i < doc_ids.length; i++) {
584 String doc_id = doc_ids[i];
585
586 if (GS3OID.needsTranslating(doc_id)) {
587 doc_id = translateOID(doc_id);
588 }
589 if (type==DOCUMENT && GS3OID.isDocTop(doc_id)) {
590 doc_id = GS3OID.createOID(doc_id, "1");
591 }
592 // Add the document to the list
593 Element doc = this.doc.createElement(node_name);
594 doc_list.appendChild(doc);
595 doc.setAttribute(GSXML.NODE_ID_ATT, doc_id);
596
597
598// if (want_info) {
599
600// Element info_elem = this.doc.createElement("nodeStructureInfo");
601// doc.appendChild(info_elem);
602
603// for (int j=0; j<info_types.size(); j++) {
604// String info_type = (String)info_types.get(j);
605// Element inf = getInfo(doc_id, info_type);
606// if (inf != null) {
607// info_elem.appendChild(inf);
608// }
609// }
610// }
611 if (want_structure) {
612 // all structure info goes into a nodeStructure elem
613 Element structure_elem = this.doc.createElement(GSXML.NODE_STRUCTURE_ELEM);
614 doc.appendChild(structure_elem);
615
616 if (want_entire_structure) {
617 String top_id = GS3OID.getTop(doc_id);
618 Element top_node = createDocNode(top_id, true, false);
619 addDescendants(top_node, top_id, type, true);
620 structure_elem.appendChild(top_node);
621 continue; // with the next document, we dont need to do any more here
622 }
623
624 // Add the requested structure information
625 Element current = createDocNode(doc_id, false, false);
626
627 //Ancestors: continually add parent nodes until the root is reached
628 Element top_node = current; // the top node so far
629 if (want_ancestors) {
630 String current_id = doc_id;
631 while (true) {
632 Element parent = getParent(current_id);
633 if (parent == null)
634 break;
635
636 parent.appendChild(top_node);
637 current_id = parent.getAttribute(GSXML.NODE_ID_ATT);
638 top_node = parent;
639 }
640 }
641 // Parent: get the parent of the selected node
642 if (want_parent) {
643 Element parent = getParent(doc_id);
644 if (parent != null) {
645 parent.appendChild(current);
646 top_node = parent;
647 }
648 }
649
650
651 // now the top node is the root of the structure
652 structure_elem.appendChild(top_node);
653
654 //Siblings: get the other descendants of the selected node's parent
655 if (want_siblings) {
656 Element parent = (Element)current.getParentNode(); // this may be the structure element if there has been no request for parents or ancestors
657 String parent_id = GS3OID.getParent(doc_id);
658
659 // add siblings, - returns a pointer to the new current node
660 current = addSiblings(parent, parent_id, doc_id);
661 }
662
663 // Children: get the descendants, but only one level deep
664 if (want_children)
665 addDescendants(current, doc_id, type, false);
666 // Descendants: recursively get every descendant of the selected node
667 if (want_descendants)
668 addDescendants(current, doc_id, type, true);
669 } // if want structure
670 } // for each doc
671 return result;
672 }
673
674
675 protected Element processDocumentMetadataRetrieve(Element request) {
676 return genericMetadataRetrieve(request, DOCUMENT);
677 }
678
679 protected Element processClassifierBrowseMetadataRetrieve(Element request) {
680 return genericMetadataRetrieve(request, CLASSIFIER);
681 }
682
683
684 /** Retrieve metadata associated with a document or classifier node*/
685 protected Element genericMetadataRetrieve(Element request, int type)
686 {
687 // Create a new (empty) result message
688 Element result = this.doc.createElement(GSXML.RESPONSE_ELEM);
689
690 String node_name;
691
692 String service_name;
693 if (type==DOCUMENT) {
694 service_name = DOCUMENT_METADATA_RETRIEVE_SERVICE;
695 node_name = GSXML.DOC_NODE_ELEM;
696 } else {
697 service_name = CLASSIFIER_METADATA_SERVICE;
698 node_name = GSXML.CLASS_NODE_ELEM;
699 }
700 result.setAttribute(GSXML.FROM_ATT, service_name);
701 result.setAttribute(GSXML.TYPE_ATT, GSXML.REQUEST_TYPE_PROCESS);
702
703 // Get the parameters of the request
704 Element param_list = (Element) GSXML.getChildByTagName(request, GSXML.PARAM_ELEM+GSXML.LIST_MODIFIER);
705 if (param_list == null) {
706 System.err.println("GS3Retrieve, DocumentMetadataRetrieve Error: missing paramList.\n");
707 return result; // Return the empty result
708 }
709
710 // The metadata information required
711 Vector metadata_list = new Vector();
712 boolean all_metadata = false;
713 // Process the request parameters
714 Element param = (Element) param_list.getFirstChild();
715 while (param != null) {
716 // Identify the metadata information desired
717 if (param.getAttribute(GSXML.NAME_ATT).equals("metadata")) {
718 String metadata = GSXML.getValue(param);
719 if (metadata.equals("all")) {
720 all_metadata = true;
721 break;
722 }
723 metadata_list.add(metadata);
724 }
725 param = (Element) param.getNextSibling();
726 }
727
728 Element node_list = this.doc.createElement(node_name+GSXML.LIST_MODIFIER);
729 result.appendChild(node_list);
730
731 // Get the documents
732 Element request_node_list = (Element) GSXML.getChildByTagName(request, node_name+GSXML.LIST_MODIFIER);
733 if (request_node_list == null) {
734 System.err.println("Error: DocumentMetadataRetrieve request had no "+node_name+"List.\n");
735 return result;
736 }
737
738 NodeList request_nodes = request_node_list.getChildNodes();
739 for (int i = 0; i < request_nodes.getLength(); i++) {
740 Element request_node = (Element) request_nodes.item(i);
741 String node_id = request_node.getAttribute(GSXML.NODE_ID_ATT);
742
743 if (GS3OID.needsTranslating(node_id)) {
744 //node_id = this.gdbm_src.translateOID(node_id);
745 node_id = translateOID(node_id);
746 }
747
748
749 // Add the document to the list
750 Element new_node = (Element)this.doc.importNode(request_node, false);
751 node_list.appendChild(new_node);
752
753 // Add the requested metadata information
754 Element node_meta_list = this.doc.createElement(GSXML.METADATA_ELEM+GSXML.LIST_MODIFIER);
755 new_node.appendChild(node_meta_list);
756 //DBInfo info = this.gdbm_src.getInfo(node_id);
757 //if (info == null) {// I have had a case where it is null!
758 //continue;
759 //}
760 if (all_metadata) {
761 // return everything out of the database
762 //Set keys = info.getKeys();
763 //Iterator it = keys.iterator();
764 //while(it.hasNext()) {
765 // String key = (String)it.next();
766 // String value = info.getInfo(key);
767 // GSXML.addMetadata(this.doc, node_meta_list, key, value);
768 //}
769 } else { // just get the selected ones
770 System.out.println("getting metadata for node_id "+node_id);
771 for (int m = 0; m < metadata_list.size(); m++) {
772 String metadata = (String) metadata_list.get(m);
773 System.out.println("lookign for metadata "+metadata);
774 String value = null;
775 if (type==DOCUMENT) {
776 value = database.getDocumentMetadata(node_id, metadata);
777 } else {
778 value = database.getClassifierMetadata(node_id, metadata);
779 }
780 if (value != null) {
781 System.out.println("found value "+value);
782 GSXML.addMetadata(this.doc, node_meta_list, metadata, value);
783 }
784 }
785 }
786 }
787
788 return result;
789 }
790
791// protected final char RELATION_SEP_CHAR = '_';
792// protected final String SEPARATOR_SEP_STRING = "'";
793
794// protected String getMetadata(String node_id, DBInfo info,
795// String metadata) {
796// int pos = metadata.indexOf(RELATION_SEP_CHAR);
797// if (pos ==-1) {
798// return info.getInfo(metadata);
799// }
800
801// String relation = metadata.substring(0, pos);
802// if (!relation.equals("parent") && !relation.equals("root") && !relation.startsWith("ancestors") ) {
803// // its not a valid relation
804// return info.getInfo(metadata);
805// }
806
807// String relation_id = "";
808// if (relation.equals("root")) {
809// relation_id = GS3OID.getTop(node_id);
810// } else {
811// relation_id = GS3OID.getParent(node_id);
812// }
813
814// if (relation_id.equals(node_id)){
815// // no parents or ancestors
816// return "";
817// }
818
819// DBInfo relation_info = this.gdbm_src.getInfo(relation_id);
820// if (relation_info == null) {
821// return "";
822// }
823
824// String new_meta = metadata.substring(pos+1);
825// if (relation.equals("parent") || relation.equals("root")) {
826// return relation_info.getInfo(new_meta);
827// }
828
829// // do ancestor stuff
830// // get teh separating string
831// String items [] = relation.split(SEPARATOR_SEP_STRING);
832// String separator = "";
833// if (items.length > 1) {
834// separator = items[1];
835// relation = items[0];
836// }
837
838// StringBuffer value = new StringBuffer();
839// value.append(relation_info.getInfo(new_meta));
840// String current_id = relation_id;
841// relation_id = GS3OID.getParent(current_id);
842// while (!relation_id.equals(current_id)) {
843// relation_info = this.gdbm_src.getInfo(relation_id);
844// if (relation_info == null) return value.toString();
845// value.insert(0, separator);
846// value.insert(0, relation_info.getInfo(new_meta));
847
848// current_id = relation_id;
849// relation_id = GS3OID.getParent(current_id);
850// }
851
852// return value.toString();
853// }
854
855 /** Retrieve the content of a document - implemented by concrete subclasses */
856 protected abstract Element processDocumentContentRetrieve(Element request);
857
858 /** needs to get info from gdbm database - if the calling code gets it already it may pay to pass it in instead */
859// protected String resolveImages(String doc_content, String doc_id)
860// {
861// String top_doc_id = GS3OID.getTop(doc_id);
862// DBInfo info = this.gdbm_src.getInfo(top_doc_id);
863// String archivedir = info.getInfo("archivedir");
864// String image_dir = this.site_http_address + "/collect/"+this.cluster_name+"/index/assoc/"+archivedir;
865
866// // Resolve all "_httpdocimg_"s
867// doc_content = doc_content.replaceAll("_httpdocimg_", image_dir);
868// return doc_content;
869// }
870
871// protected Element getInfo(String doc_id, String info_type) {
872
873// String value="";
874// if (info_type.equals(INFO_NUM_SIBS)) {
875// String parent_id = GS3OID.getParent(doc_id);
876// if (parent_id.equals(doc_id)) {
877// value="0";
878// } else {
879// value = String.valueOf(getNumChildren(parent_id));
880// }
881// } else if (info_type.equals(INFO_NUM_CHILDREN)) {
882// value = String.valueOf(getNumChildren(doc_id));
883// } else if (info_type.equals(INFO_SIB_POS)) {
884// String parent_id = GS3OID.getParent(doc_id);
885// if (parent_id.equals(doc_id)) {
886// value="-1";
887// } else {
888// DBInfo info = this.gdbm_src.getInfo(parent_id);
889// String contains = info.getInfo("contains");
890// contains = contains.replaceAll("\"", parent_id);
891// String [] children = contains.split(";");
892// for (int i=0;i<children.length;i++) {
893// String child_id = children[i];
894// if (child_id.equals(doc_id)) {
895// value = String.valueOf(i+1); // make it from 1 to length
896// break;
897// }
898// }
899// }
900// } else {
901// return null;
902// }
903// Element info_elem = this.doc.createElement("info");
904// info_elem.setAttribute(GSXML.NAME_ATT, info_type);
905// info_elem.setAttribute(GSXML.VALUE_ATT, value);
906// return info_elem;
907// }
908
909// protected int getNumChildren(String doc_id) {
910// DBInfo info = this.gdbm_src.getInfo(doc_id);
911// String contains = info.getInfo("contains");
912// if (contains.equals("")) {
913// return 0;
914// }
915// String [] children = contains.split(";");
916// return children.length;
917// }
918
919 protected String translateOID(String oid) {
920
921 int p = oid.lastIndexOf('.');
922 if (p != oid.length()-3) {
923 System.out.println("translateoid error: '.' is not the third to last char!!");
924 return oid;
925 }
926
927 String top = oid.substring(0, p);
928 String suff = oid.substring(p+1);
929 if (suff.equals("pr")) {
930 return GS3OID.getParent(top);
931 } else if (suff.equals("rt")) {
932 return GS3OID.getTop(top);
933 }
934 return oid;
935
936 }
937
938}
Note: See TracBrowser for help on using the repository browser.