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

Last change on this file since 26198 was 26046, checked in by kjdon, 12 years ago

moved a heap of duplicated code out of service racks and into BasicDocument classes

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