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

Last change on this file since 30631 was 29989, checked in by kjdon, 9 years ago

add in the replaceListRef macros to the macro resolver

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