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

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

Classifier nodes will now have childType and classifierStyle attributes so that we can tell if it is a VList or an HList

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