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

Last change on this file since 23050 was 23050, checked in by kjdon, 14 years ago

code was assuming CLx and removing CL then parsing the integer to get the position. But now just use the position in the list to be the position and assume that the coll config and build config lists are the same. then we can get classifier info for eg oai classifier

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