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

Last change on this file since 25688 was 25688, checked in by sjm84, 12 years ago

Reformatting this file

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