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

Last change on this file since 38964 was 38964, checked in by anupama, 4 weeks ago

Certain user-customised GLI Collage classifier options need to go into the pageResponse to be incorporated into the applet shim. 1. buildConfigxml.pm modified to push these options out into buildConfig.xml. 2. AbstractBrowse.java (classifier Service) has been modified to push out any classifier option subelements out into the pageResponse. 3. classifier.xsl has been modified to construct its applet HTML element's parameter elements taking into account any customised values in the pageResponse or using the old defaults for fallback. 4. The JavaScript code in webswing-collage.xsl doesn't have ready access to the pageResponse elements (this may need revisiting for if the applet element was accidentally removed from the page), but was already taking into account any applet parameters. webswing-collage.xsl has been modified to use any static/dynamic width and height attributes set on the applet parameter to reset the width and height on the div id=webswing-collage element, as webswing uses the dimensions set on the HTML element housing the webswing instance if running the instance as an applet. It does not resize the webswing applet thereafter. So the most transparent way to allow the user customised dimensions to control the dimensions of the webswing application as intended by the user, is to modify the dimensions set on the webswing-collage element's div before launching the webswing application.

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