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

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

Remove the assumption that top level format statements apply to the classifier

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