source: trunk/gsdl3/src/java/org/greenstone/gsdl3/service/GS2Retrieve.java@ 4903

Last change on this file since 4903 was 4903, checked in by kjdon, 21 years ago

tidied up a lot of stuff, particularly the display text stuff, including how its formatted, and some of the service rack methods

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