source: main/trunk/greenstone3/src/java/org/greenstone/gsdl3/service/AbstractBrowse.java@ 22306

Last change on this file since 22306 was 22306, checked in by ak19, 14 years ago
  1. AbstractBrowse's method extractExtraClassifierInfo() is now package access and static (it never used member variables anyway) so that the FedoraServiceProxy class can reuse it in entirety.
  • Property svn:keywords set to Author Date Id Revision
File size: 25.4 KB
Line 
1/*
2 * AbstractBrowse.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
22// Greenstone classes
23import org.greenstone.gsdl3.util.GSXML;
24import org.greenstone.gsdl3.util.GSPath;
25import org.greenstone.gsdl3.util.MacroResolver;
26import org.greenstone.gsdl3.util.OID;
27
28// XML classes
29import org.w3c.dom.Document;
30import org.w3c.dom.Element;
31import org.w3c.dom.NodeList;
32
33// General Java classes
34import java.util.ArrayList;
35
36import org.apache.log4j.*;
37
38/** Partially implements a generic classifier service
39 *
40 * @author <a href="mailto:[email protected]">Katherine Don</a>
41 */
42public abstract class AbstractBrowse
43 extends ServiceRack {
44
45 static Logger logger = Logger.getLogger(org.greenstone.gsdl3.service.AbstractBrowse.class.getName());
46
47 // the browsing services
48 private static final String CLASSIFIER_SERVICE = "ClassifierBrowse";
49 private static final String CLASSIFIER_METADATA_SERVICE = "ClassifierBrowseMetadataRetrieve";
50
51 // do we want to keep info request?
52
53 protected static final String STRUCT_PARAM = "structure";
54 protected static final String INFO_PARAM = "info";
55
56 protected static final String STRUCT_ANCESTORS = "ancestors";
57 protected static final String STRUCT_PARENT = "parent";
58 protected static final String STRUCT_SIBS = "siblings";
59 protected static final String STRUCT_CHILDREN = "children";
60 protected static final String STRUCT_DESCENDS = "descendants";
61 protected static final String STRUCT_ENTIRE = "entire";
62
63 protected static final String INFO_NUM_SIBS = "numSiblings";
64 protected static final String INFO_NUM_CHILDREN = "numChildren";
65 protected static final String INFO_SIB_POS = "siblingPosition";
66
67 protected Element config_info = null; // the xml from the config file
68
69 protected MacroResolver macro_resolver = null;
70
71 protected String default_document_type = null;
72 /** constructor */
73 protected AbstractBrowse()
74 {
75 }
76
77
78 /** configure this service */
79 public boolean configure(Element info, Element extra_info)
80 {
81 if (!super.configure(info, extra_info)){
82 return false;
83 }
84
85 logger.info("Configuring AbstractBrowse...");
86 this.config_info = info;
87 if (macro_resolver != null) {
88 macro_resolver.setSiteDetails(this.site_http_address, this.cluster_name, this.library_name);
89 // set up the macro resolver
90 Element replacement_elem = (Element)GSXML.getChildByTagName(extra_info, "replaceList");
91 if (replacement_elem != null) {
92 macro_resolver.addMacros(replacement_elem);
93 }
94
95 }
96
97 // check that there are classifiers specified
98 Element class_list = (Element)GSXML.getChildByTagName(info, GSXML.CLASSIFIER_ELEM+GSXML.LIST_MODIFIER);
99 if (class_list == null) {
100 // no classifiers specified
101 return false;
102 }
103
104 // get the display and format elements from the coll config file for
105 // the classifiers
106 extractExtraClassifierInfo(info, extra_info);
107
108 // short_service_info_ - the browse one
109 Element cb_service = this.doc.createElement(GSXML.SERVICE_ELEM);
110 cb_service.setAttribute(GSXML.TYPE_ATT, GSXML.SERVICE_TYPE_BROWSE);
111 cb_service.setAttribute(GSXML.NAME_ATT, CLASSIFIER_SERVICE);
112 this.short_service_info.appendChild(cb_service);
113
114 // metadata retrieval for the browsing
115 Element cbmr_service = this.doc.createElement(GSXML.SERVICE_ELEM);
116 cbmr_service.setAttribute(GSXML.TYPE_ATT, GSXML.SERVICE_TYPE_RETRIEVE);
117 cbmr_service.setAttribute(GSXML.NAME_ATT, CLASSIFIER_METADATA_SERVICE);
118 this.short_service_info.appendChild(cbmr_service);
119
120 // the format info
121 Element cb_format_info = this.doc.createElement(GSXML.FORMAT_ELEM);
122 boolean format_found = false;
123
124 // try the default format first
125 Element def_format = (Element) GSXML.getChildByTagName(info, GSXML.FORMAT_ELEM);
126 if (def_format != null) {
127 cb_format_info.appendChild(GSXML.duplicateWithNewName(this.doc, def_format, GSXML.DEFAULT_ELEM, true));
128 format_found = true;
129 }
130
131 // add in to the description a simplified list of classifiers
132 NodeList classifiers = class_list.getElementsByTagName(GSXML.CLASSIFIER_ELEM);
133 for(int i=0; i<classifiers.getLength(); i++) {
134 Element cl = (Element)classifiers.item(i);
135 Element new_cl = (Element)this.doc.importNode(cl, false); // just import this node, not the children
136
137 // get the format info out, and put inside a classifier element
138 Element format_cl = (Element)new_cl.cloneNode(false);
139 Element format = (Element)GSXML.getChildByTagName(cl, GSXML.FORMAT_ELEM);
140 if (format != null) {
141
142 //copy all the children
143 NodeList elems = format.getChildNodes();
144 for (int j=0; j<elems.getLength();j++) {
145 format_cl.appendChild(this.doc.importNode(elems.item(j), true));
146 }
147 cb_format_info.appendChild(format_cl);
148 format_found = true;
149 }
150
151 }
152
153 if (format_found) {
154 this.format_info_map.put(CLASSIFIER_SERVICE, cb_format_info);
155 }
156
157 // look for document display format - is there a default doc type??
158 String path = GSPath.appendLink(GSXML.DISPLAY_ELEM, GSXML.FORMAT_ELEM);
159 Element display_format = (Element)GSXML.getNodeByPath(extra_info, path);
160 if (display_format != null) {
161 // check for docType option.
162 Element doc_type_opt = GSXML.getNamedElement(display_format, "gsf:option", GSXML.NAME_ATT, "documentType");
163 if (doc_type_opt != null) {
164 String value = doc_type_opt.getAttribute(GSXML.VALUE_ATT);
165 if (!value.equals("")) {
166 this.default_document_type = value;
167 }
168 }
169 }
170
171 return true;
172 }
173
174 protected Element getServiceDescription(String service_id, String lang, String subset) {
175
176 if (service_id.equals(CLASSIFIER_SERVICE)) {
177
178 Element class_list = (Element)GSXML.getChildByTagName(this.config_info, GSXML.CLASSIFIER_ELEM+GSXML.LIST_MODIFIER);
179 if (class_list == null) {
180 // no classifiers specified
181 return null;
182 }
183
184 Element cb_service = this.doc.createElement(GSXML.SERVICE_ELEM);
185 cb_service.setAttribute(GSXML.TYPE_ATT, GSXML.SERVICE_TYPE_BROWSE);
186 cb_service.setAttribute(GSXML.NAME_ATT, CLASSIFIER_SERVICE);
187 cb_service.appendChild(GSXML.createDisplayTextElement(this.doc, GSXML.DISPLAY_TEXT_NAME, getTextString(CLASSIFIER_SERVICE+".name", lang)));
188 cb_service.appendChild(GSXML.createDisplayTextElement(this.doc, GSXML.DISPLAY_TEXT_DESCRIPTION, getTextString(CLASSIFIER_SERVICE+".description", lang)));
189
190 Element cl_list = this.doc.createElement(GSXML.CLASSIFIER_ELEM+GSXML.LIST_MODIFIER);
191 cb_service.appendChild(cl_list);
192 NodeList classifiers = class_list.getElementsByTagName(GSXML.CLASSIFIER_ELEM);
193 for(int i=0; i<classifiers.getLength(); i++) {
194 Element cl = (Element)classifiers.item(i);
195 Element new_cl = (Element)this.doc.importNode(cl, false); // just import this node, not the children
196
197 //String content = cl.getAttribute(GSXML.CLASSIFIER_CONTENT_ATT);
198
199 //get the classify title from the database
200 String class_id = cl.getAttribute(GSXML.NAME_ATT);
201 String content = getMetadata(class_id,"Title");
202
203 cl_list.appendChild(new_cl);
204 String text = GSXML.getDisplayText(cl,
205 GSXML.DISPLAY_TEXT_NAME,
206 lang, "en");
207 if (text == null || text.equals("")) {
208 // no display element was specified, use the metadata name
209 // for now this looks in the class properties file
210 // this needs to use a general metadata thing instead
211 text = getMetadataNameText(content+".buttonname", lang);
212 }
213 if (text == null) {
214 text = content;
215 }
216
217
218 Element cl_name = GSXML.createDisplayTextElement(this.doc, GSXML.DISPLAY_TEXT_NAME, text);
219 new_cl.appendChild(cl_name);
220
221 // description
222
223 String meta_name = getMetadataNameText(content, lang);
224 if (meta_name==null) {
225 meta_name = content;
226 }
227 String [] array = {meta_name};
228 String description = getTextString("ClassifierBrowse.classifier_help", lang, array);
229 Element cl_desc = GSXML.createDisplayTextElement(this.doc, GSXML.DISPLAY_TEXT_DESCRIPTION, description);
230 new_cl.appendChild(cl_desc);
231
232 }
233 return cb_service;
234 }
235
236 // these ones are probably never called, but put them here just in case
237
238 if (service_id.equals(CLASSIFIER_METADATA_SERVICE)) {
239
240 Element cbmr_service = this.doc.createElement(GSXML.SERVICE_ELEM);
241 cbmr_service.setAttribute(GSXML.TYPE_ATT, GSXML.SERVICE_TYPE_RETRIEVE);
242 cbmr_service.setAttribute(GSXML.NAME_ATT, CLASSIFIER_METADATA_SERVICE);
243 return cbmr_service;
244 }
245
246 return null;
247 }
248
249 /** this looks for any classifier specific display or format info from extra_info and adds it in to the correct place in info */
250 static boolean extractExtraClassifierInfo(Element info, Element extra_info) {
251
252 if (extra_info == null) {
253 return false;
254 }
255
256 Document owner = info.getOwnerDocument();
257 // so far we have display and format elements that we need for classifiers
258 NodeList classifiers = info.getElementsByTagName(GSXML.CLASSIFIER_ELEM);
259 Element config_browse = (Element)GSXML.getChildByTagName(extra_info, GSXML.BROWSE_ELEM);
260
261 for (int i=0; i<classifiers.getLength();i++) {
262 Element cl = (Element)classifiers.item(i);
263 String name = cl.getAttribute(GSXML.NAME_ATT);
264
265 //Element node_extra = GSXML.getNamedElement(config_browse,
266 // GSXML.CLASSIFIER_ELEM,
267 // GSXML.NAME_ATT,
268 // name);
269 //now use the position to get the node - CL1
270 int position = Integer.parseInt(name.substring(2));
271 Element node_extra = null;
272 NodeList cls = config_browse.getElementsByTagName(GSXML.CLASSIFIER_ELEM);
273 if (position >0 && position <= cls.getLength()) {
274 node_extra = (Element) cls.item((position -1));
275 }
276
277 if (node_extra == null) {
278 logger.error("GS2REtrieve: haven't found extra info for classifier named "+name);
279 continue;
280 }
281
282 // get the display elements if any - displayName
283 NodeList display_names = node_extra.getElementsByTagName(GSXML.DISPLAY_TEXT_ELEM);
284 if (display_names !=null) {
285 Element display = owner.createElement(GSXML.DISPLAY_ELEM);
286 for (int j=0; j<display_names.getLength(); j++) {
287 Element e = (Element)display_names.item(j);
288 cl.appendChild(owner.importNode(e, true));
289
290 }
291 }
292
293 // get the format element if any
294 Element format = (Element)GSXML.getChildByTagName(node_extra, GSXML.FORMAT_ELEM);
295 if (format==null) { // try a generic one that applies to all classifiers
296 format = (Element)GSXML.getChildByTagName(extra_info,
297 GSXML.FORMAT_ELEM);
298 }
299 if (format!=null) { // append to index info
300 cl.appendChild(owner.importNode(format, true));
301 }
302 } // for each classifier
303
304 // now check for default format info
305 Element default_format = (Element)GSXML.getChildByTagName(config_browse, GSXML.FORMAT_ELEM);
306 if (default_format!=null) { // append to info
307 info.appendChild(owner.importNode(default_format, true));
308 }
309
310 return true;
311 }
312
313 protected Element processClassifierBrowse(Element request) {
314
315 // Create a new (empty) result message
316 Element result = this.doc.createElement(GSXML.RESPONSE_ELEM);
317 result.setAttribute(GSXML.FROM_ATT, CLASSIFIER_SERVICE);
318 result.setAttribute(GSXML.TYPE_ATT, GSXML.REQUEST_TYPE_PROCESS);
319
320 String lang = request.getAttribute(GSXML.LANG_ATT);
321 Element query_node_list = (Element) GSXML.getChildByTagName(request, GSXML.CLASS_NODE_ELEM+GSXML.LIST_MODIFIER);
322 if (query_node_list == null) {
323 logger.error(" ClassifierBrowse request specified no doc nodes.\n");
324 return result;
325 }
326
327 // Get the parameters of the request
328 Element param_list = (Element) GSXML.getChildByTagName(request, GSXML.PARAM_ELEM+GSXML.LIST_MODIFIER);
329 if (param_list == null) {
330 logger.error(" ClassifierBrowse request had no paramList.");
331 return result; // Return the empty result
332 }
333
334 // the type of info required
335 boolean want_structure = false;
336 boolean want_info = false;
337
338 ArrayList info_types=new ArrayList();
339 // The document structure information desired
340 boolean want_ancestors = false;
341 boolean want_parent = false;
342 boolean want_siblings = false;
343 boolean want_children = false;
344 boolean want_descendants = false;
345
346 boolean want_entire_structure = false;
347 // Process the request parameters
348 NodeList params = param_list.getElementsByTagName(GSXML.PARAM_ELEM);
349 for (int i=0; i<params.getLength();i++) {
350
351 Element param = (Element)params.item(i);
352 String p_name = param.getAttribute(GSXML.NAME_ATT);
353 String p_value = GSXML.getValue(param);
354 // Identify the structure information desired
355 if (p_name.equals(STRUCT_PARAM)) {
356 want_structure = true;
357
358 // This is NOT locale sensitive
359 if (p_value.equals(STRUCT_ANCESTORS))
360 want_ancestors = true;
361 else if (p_value.equals(STRUCT_PARENT))
362 want_parent = true;
363 else if (p_value.equals(STRUCT_SIBS))
364 want_siblings = true;
365 else if (p_value.equals(STRUCT_CHILDREN))
366 want_children = true;
367 else if (p_value.equals(STRUCT_DESCENDS))
368 want_descendants = true;
369 else if (p_value.equals(STRUCT_ENTIRE))
370 want_entire_structure = true;
371 else
372 logger.error("AbstractDocumentRetrieve Warning: Unknown value \"" + p_value + "\".");
373 } else if (p_name.equals(INFO_PARAM)) {
374 want_info = true;
375 info_types.add(p_value);
376 }
377 }
378
379 // Make sure there is no repeated information
380 if (want_ancestors)
381 want_parent = false;
382 if (want_descendants)
383 want_children = false;
384
385 // the node list to hold the results
386 Element node_list = this.doc.createElement(GSXML.CLASS_NODE_ELEM+GSXML.LIST_MODIFIER);
387 result.appendChild(node_list);
388
389 // Get the nodes
390 String[] node_ids = GSXML.getAttributeValuesFromList(query_node_list,
391 GSXML.NODE_ID_ATT);
392 for (int i = 0; i < node_ids.length; i++) {
393 // Add the document to the list
394 Element node = this.doc.createElement(GSXML.CLASS_NODE_ELEM);
395 node_list.appendChild(node);
396
397 String node_id = node_ids[i];
398 node.setAttribute(GSXML.NODE_ID_ATT, node_id);
399
400 if (idNeedsTranslating(node_id)) {
401 node_id = translateId(node_id);
402 if (node_id == null) {
403 continue;
404 }
405 node.setAttribute(GSXML.NODE_ID_ATT, node_id);
406 }
407
408 if (want_info) {
409
410 Element node_info_elem = this.doc.createElement("nodeStructureInfo");
411 node.appendChild(node_info_elem);
412
413 for (int j=0; j<info_types.size(); j++) {
414 String info_type = (String)info_types.get(j);
415 String info_value = getStructureInfo(node_id, info_type);
416 if (info_value != null) {
417 Element info_elem = this.doc.createElement("info");
418 info_elem.setAttribute(GSXML.NAME_ATT, info_type);
419 info_elem.setAttribute(GSXML.VALUE_ATT, info_value);
420 node_info_elem.appendChild(info_elem);
421 }
422 }
423 }
424
425 if (want_structure) {
426 // all structure info goes into a nodeStructure elem
427 Element structure_elem = this.doc.createElement(GSXML.NODE_STRUCTURE_ELEM);
428 node.appendChild(structure_elem);
429
430 if (want_entire_structure) {
431 String root_id = getRootId(node_id);
432 Element root_node = createClassifierNode(root_id); //, true, false);
433 addDescendants(root_node, root_id, true);
434 structure_elem.appendChild(root_node);
435 continue; // with the next document, we dont need to do any more here
436 }
437
438 // Add the requested structure information
439 Element base_node = createClassifierNode(node_id); //, false, false);
440
441 //Ancestors: continually add parent nodes until the root is reached
442 Element top_node = base_node; // the top node so far
443 if (want_ancestors) {
444 String current_id = node_id;
445 while (true) {
446 String parent_id = getParentId(current_id);
447 //Element parent = getParent(current_id);
448 if (parent_id == null)
449 break; // no parent
450 Element parent_node = createClassifierNode(parent_id);
451 parent_node.appendChild(top_node);
452 current_id = parent_id;//.getAttribute(GSXML.NODE_ID_ATT);
453 top_node = parent_node;
454 }
455 }
456 // Parent: get the parent of the selected node
457 else if (want_parent) {
458 String parent_id = getParentId(node_id);
459 if (parent_id != null) {
460 Element parent_node = createClassifierNode(parent_id);
461 parent_node.appendChild(base_node);
462 top_node = parent_node;
463 }
464 }
465
466 // now the top node is the root of the structure
467 structure_elem.appendChild(top_node);
468
469 //Siblings: get the other descendants of the selected node's parent
470 if (want_siblings) {
471
472 Element parent_node = (Element)base_node.getParentNode(); // this may be the structure element if there has been no request for parents or ancestors
473 String parent_id = getParentId(node_id);
474 // add siblings, - returns a pointer to the new current node
475 base_node = addSiblings(parent_node, parent_id, node_id);
476 }
477
478 // Children: get the descendants, but only one level deep
479 if (want_children) {
480 addDescendants(base_node, node_id, false);
481 }
482 // Descendants: recursively get every descendant
483 else if (want_descendants) {
484 addDescendants(base_node, node_id, true);
485 }
486 } // if want structure
487 } // for each doc
488 return result;
489 }
490
491
492 protected Element processClassifierBrowseMetadataRetrieve(Element request) {
493
494 // Create a new (empty) result message
495 Element result = this.doc.createElement(GSXML.RESPONSE_ELEM);
496
497 String lang = request.getAttribute(GSXML.LANG_ATT);
498 result.setAttribute(GSXML.FROM_ATT, CLASSIFIER_METADATA_SERVICE);
499 result.setAttribute(GSXML.TYPE_ATT, GSXML.REQUEST_TYPE_PROCESS);
500
501 // Get the parameters of the request
502 Element param_list = (Element) GSXML.getChildByTagName(request, GSXML.PARAM_ELEM+GSXML.LIST_MODIFIER);
503 if (param_list == null) {
504 logger.error("AbstractBrowse, ClassifierBrowseMetadataRetrieve Error: missing paramList.\n");
505 return result; // Return the empty result
506 }
507
508 // The metadata information required
509 ArrayList metadata_names_list = new ArrayList();
510 boolean all_metadata = false;
511 // Process the request parameters
512 Element param = GSXML.getFirstElementChild(param_list);//(Element) param_list.getFirstChild();
513 while (param != null) {
514 // Identify the metadata information desired
515 if (param.getAttribute(GSXML.NAME_ATT).equals("metadata")) {
516 String metadata = GSXML.getValue(param);
517 if (metadata.equals("all")) {
518 all_metadata = true;
519 break;
520 }
521 metadata_names_list.add(metadata);
522 }
523 param = (Element) param.getNextSibling();
524 }
525
526 Element node_list = this.doc.createElement(GSXML.CLASS_NODE_ELEM+GSXML.LIST_MODIFIER);
527 result.appendChild(node_list);
528
529 // Get the nodes
530 Element request_node_list = (Element) GSXML.getChildByTagName(request, GSXML.CLASS_NODE_ELEM+GSXML.LIST_MODIFIER);
531 if (request_node_list == null) {
532 logger.error(" ClassifierBrowseMetadataRetrieve request had no "+GSXML.CLASS_NODE_ELEM+GSXML.LIST_MODIFIER);
533 return result;
534 }
535
536 NodeList request_nodes = request_node_list.getChildNodes();
537 for (int i = 0; i < request_nodes.getLength(); i++) {
538 Element request_node = (Element) request_nodes.item(i);
539 String node_id = request_node.getAttribute(GSXML.NODE_ID_ATT);
540
541 // Add the document to the results list
542 Element new_node = (Element)this.doc.importNode(request_node, false);
543 node_list.appendChild(new_node);
544
545 if (idNeedsTranslating(node_id)) {
546 node_id = translateId(node_id);
547 }
548 if (node_id == null) {
549 continue;
550 }
551
552 Element metadata_list = getMetadataList(node_id, all_metadata, metadata_names_list);
553 new_node.appendChild(metadata_list);
554 }
555
556 return result;
557 }
558
559
560 /** Creates a classifier node */
561 protected Element createClassifierNode(String node_id)
562 {
563 Element node = this.doc.createElement(GSXML.CLASS_NODE_ELEM);
564 node.setAttribute(GSXML.NODE_ID_ATT, node_id);
565 return node;
566 }
567
568 /** create an element to go into the structure. A node element
569 * has the form
570 * <docNode nodeId='xxx' nodeType='leaf' docType='hierarchy'/>
571 */
572 protected Element createDocNode(String node_id) {
573 Element node = this.doc.createElement(GSXML.DOC_NODE_ELEM);
574 node.setAttribute(GSXML.NODE_ID_ATT, node_id);
575
576 String doc_type = null;
577 if (default_document_type != null) {
578 doc_type = default_document_type;
579 } else {
580 doc_type = getDocType(node_id);
581 }
582 node.setAttribute(GSXML.DOC_TYPE_ATT, doc_type);
583 String node_type = getNodeType(node_id, doc_type);
584 node.setAttribute(GSXML.NODE_TYPE_ATT, node_type);
585 return node;
586 }
587
588 /** returns the node type of the specified node.
589 should be one of
590 GSXML.NODE_TYPE_LEAF,
591 GSXML.NODE_TYPE_INTERNAL,
592 GSXML.NODE_TYPE_ROOT
593 */
594 protected String getNodeType(String node_id, String doc_type) {
595 if (doc_type.equals(GSXML.DOC_TYPE_SIMPLE)) {
596 return GSXML.NODE_TYPE_LEAF;
597 }
598
599 if (getParentId(node_id)==null) {
600 return GSXML.NODE_TYPE_ROOT;
601 }
602 if (doc_type.equals(GSXML.DOC_TYPE_PAGED)) {
603 return GSXML.NODE_TYPE_LEAF;
604 }
605 if (getChildrenIds(node_id)==null) {
606 return GSXML.NODE_TYPE_LEAF;
607 }
608 return GSXML.NODE_TYPE_INTERNAL;
609
610 }
611
612 /** adds all the children of doc_id the the doc element,
613 * and if recursive=true, adds all their children as well*/
614 protected void addDescendants(Element node, String node_id,
615 boolean recursive)
616 {
617 ArrayList child_ids = getChildrenIds(node_id);
618 if (child_ids==null) return;
619 for (int i=0; i< child_ids.size(); i++) {
620 String child_id = (String)child_ids.get(i);
621 Element child_elem;
622 if (isDocumentId(child_id)) {
623 child_elem = createDocNode(child_id);
624 } else {
625 child_elem = createClassifierNode(child_id);
626 }
627 node.appendChild(child_elem);
628 if (recursive) {
629 addDescendants(child_elem, child_id, recursive);
630 }
631 }
632 }
633
634 /** adds all the siblings of current_id to the parent element.
635 returns the new current element*/
636 protected Element addSiblings(Element parent_node, String parent_id,
637 String current_id) {
638 Element current_node = GSXML.getFirstElementChild(parent_node);//(Element)parent_node.getFirstChild();
639 if (current_node == null) {
640 // create a sensible error message
641 logger.error(" there should be a first child.");
642 return null;
643 }
644 // remove the current child,- will add it in later in its correct place
645 parent_node.removeChild(current_node);
646
647 // add in all the siblings,
648 addDescendants(parent_node, parent_id, false);
649
650 // find the node that is now the current node
651 // this assumes that the new node that was created is the same as
652 // the old one that was removed - we may want to replace the new one
653 // with the old one.
654 Element new_current = GSXML.getNamedElement(parent_node, current_node.getNodeName(), GSXML.NODE_ID_ATT, current_id);
655 return new_current;
656 }
657
658 /** returns true if oid ends in
659 .fc (firstchild),
660 .lc (lastchild),
661 .pr (parent),
662 .ns (next sibling),
663 .ps (prev sibling),
664 .rt (root)
665 .ss (specified sibling),
666 false otherwise
667 */
668 protected boolean idNeedsTranslating(String node_id) {
669 return OID.needsTranslating(node_id);
670 }
671
672 /** returns the list of sibling ids, including the specified node_id */
673 protected ArrayList getSiblingIds(String node_id) {
674 String parent_id = getParentId(node_id);
675 if (parent_id == null) {
676 return null;
677 }
678 return getChildrenIds(parent_id);
679
680 }
681
682 /** if id ends in .fc, .pc etc, then translate it to the correct id */
683 abstract protected String translateId(String node_id);
684
685 /** returns the document type of the doc that the specified node
686 belongs to. should be one of
687 GSXML.DOC_TYPE_SIMPLE,
688 GSXML.DOC_TYPE_PAGED,
689 GSXML.DOC_TYPE_HIERARCHY
690 */
691 abstract protected String getDocType(String node_id);
692
693 /** returns the id of the root node of the document containing node node_id. . may be the same as node_id */
694 abstract protected String getRootId(String node_id);
695 /** returns a list of the child ids in order, null if no children */
696 abstract protected ArrayList getChildrenIds(String node_id);
697 /** returns the node id of the parent node, null if no parent */
698 abstract protected String getParentId(String node_id);
699
700 /** returns true if the id refers to a document (rather than
701 * a classifier node)
702 */
703 abstract protected boolean isDocumentId(String node_id);
704
705 /** get the metadata for the classifier node node_id
706 * returns a metadataList element:
707 * <metadataList><metadata name="xxx">value</metadata></metadataList>
708 * if all_metadata is true, returns all available metadata, otherwise just
709 * returns requested metadata
710 */
711 abstract protected Element getMetadataList(String node_id,
712 boolean all_metadata,
713 ArrayList metadata_names);
714
715 /** get the particular metadata (identified by the metadata name) for the classifier node node_id
716 *
717 */
718 abstract protected String getMetadata(String node_id, String metadata_name);
719
720
721 /** returns the structural information asked for.
722 * info_type may be one of
723 * INFO_NUM_SIBS, INFO_NUM_CHILDREN, INFO_SIB_POS
724 */
725 abstract protected String getStructureInfo(String node_id, String info_type);
726
727}
Note: See TracBrowser for help on using the repository browser.