source: main/trunk/greenstone3/src/java/org/greenstone/gsdl3/service/AbstractDocumentRetrieve.java@ 25305

Last change on this file since 25305 was 25305, checked in by kjdon, 12 years ago

tidying up handling of external links and hrefs that are relative greenstone links

  • Property svn:keywords set to Author Date Id Revision
File size: 26.0 KB
Line 
1/*
2 * AbstractDocumentRetrieve.java
3 * a base class for retrieval services
4
5 * Copyright (C) 2005 New Zealand Digital Library, http://www.nzdl.org
6 *
7 * This program is free software; you can redistribute it and/or modify
8 * it under the terms of the GNU General Public License as published by
9 * the Free Software Foundation; either version 2 of the License, or
10 * (at your option) any later version.
11 *
12 * This program is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 * GNU General Public License for more details.
16 *
17 * You should have received a copy of the GNU General Public License
18 * along with this program; if not, write to the Free Software
19 * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
20 */
21package org.greenstone.gsdl3.service;
22
23// Greenstone classes
24import org.greenstone.util.GlobalProperties;
25import org.greenstone.gsdl3.core.GSException;
26import org.greenstone.gsdl3.util.GSXML;
27import org.greenstone.gsdl3.util.GSPath;
28import org.greenstone.gsdl3.util.MacroResolver;
29import org.greenstone.gsdl3.util.OID;
30import org.greenstone.gsdl3.util.GSConstants;
31
32// XML classes
33import org.w3c.dom.Document;
34import org.w3c.dom.Element;
35import org.w3c.dom.NodeList;
36
37// General Java classes
38import java.io.File;
39import java.util.StringTokenizer;
40import java.util.Set;
41import java.util.Iterator;
42import java.util.ArrayList;
43
44import org.apache.log4j.*;
45
46/**
47 * Abstract class for Document Retrieval Services
48 */
49
50public abstract class AbstractDocumentRetrieve extends ServiceRack
51{
52 static Logger logger = Logger.getLogger(org.greenstone.gsdl3.service.AbstractDocumentRetrieve.class.getName());
53
54 // the services on offer
55 protected static final String DOCUMENT_STRUCTURE_RETRIEVE_SERVICE = "DocumentStructureRetrieve";
56 protected static final String DOCUMENT_METADATA_RETRIEVE_SERVICE = "DocumentMetadataRetrieve";
57 protected static final String DOCUMENT_CONTENT_RETRIEVE_SERVICE = "DocumentContentRetrieve";
58
59 protected static final String STRUCT_PARAM = "structure";
60 protected static final String INFO_PARAM = "info";
61
62 protected static final String STRUCT_ANCESTORS = "ancestors";
63 protected static final String STRUCT_PARENT = "parent";
64 protected static final String STRUCT_SIBS = "siblings";
65 protected static final String STRUCT_CHILDREN = "children";
66 protected static final String STRUCT_DESCENDS = "descendants";
67 protected static final String STRUCT_ENTIRE = "entire";
68
69 protected static final String INFO_NUM_SIBS = "numSiblings";
70 protected static final String INFO_NUM_CHILDREN = "numChildren";
71 protected static final String INFO_SIB_POS = "siblingPosition";
72
73 // means the id is not a greenstone id and needs translating
74 // protected static final String EXTID_PARAM = "ext";
75
76 protected Element config_info = null; // the xml from the config file
77
78 protected String default_document_type = null;
79 protected MacroResolver macro_resolver = null;
80
81 /** does this class provide the service?? */
82 protected boolean does_metadata = true;
83 protected boolean does_content = true;
84 protected boolean does_structure = true;
85
86 /** constructor */
87 public AbstractDocumentRetrieve()
88 {
89 }
90
91 /** configure this service */
92 public boolean configure(Element info, Element extra_info)
93 {
94 if (!super.configure(info, extra_info))
95 {
96 return false;
97 }
98
99 logger.info("Configuring AbstractDocumentRetrieve...");
100 this.config_info = info;
101
102 // set up short_service_info_ - for now just has name and type
103 if (does_structure)
104 {
105 Element dsr_service = this.doc.createElement(GSXML.SERVICE_ELEM);
106 dsr_service.setAttribute(GSXML.TYPE_ATT, GSXML.SERVICE_TYPE_RETRIEVE);
107 dsr_service.setAttribute(GSXML.NAME_ATT, DOCUMENT_STRUCTURE_RETRIEVE_SERVICE);
108 this.short_service_info.appendChild(dsr_service);
109 }
110
111 if (does_metadata)
112 {
113 Element dmr_service = this.doc.createElement(GSXML.SERVICE_ELEM);
114 dmr_service.setAttribute(GSXML.TYPE_ATT, GSXML.SERVICE_TYPE_RETRIEVE);
115 dmr_service.setAttribute(GSXML.NAME_ATT, DOCUMENT_METADATA_RETRIEVE_SERVICE);
116 this.short_service_info.appendChild(dmr_service);
117 }
118
119 if (does_content)
120 {
121 Element dcr_service = this.doc.createElement(GSXML.SERVICE_ELEM);
122 dcr_service.setAttribute(GSXML.TYPE_ATT, GSXML.SERVICE_TYPE_RETRIEVE);
123 dcr_service.setAttribute(GSXML.NAME_ATT, DOCUMENT_CONTENT_RETRIEVE_SERVICE);
124 this.short_service_info.appendChild(dcr_service);
125 }
126
127 // look for document display format
128 String path = GSPath.appendLink(GSXML.DISPLAY_ELEM, GSXML.FORMAT_ELEM);
129 Element display_format = (Element) GSXML.getNodeByPath(extra_info, path);
130 if (display_format != null)
131 {
132 this.format_info_map.put(DOCUMENT_CONTENT_RETRIEVE_SERVICE, this.doc.importNode(display_format, true));
133 // should we keep a copy?
134 // check for docType option.
135 Element doc_type_opt = GSXML.getNamedElement(display_format, "gsf:option", GSXML.NAME_ATT, "documentType");
136 if (doc_type_opt != null)
137 {
138 String value = doc_type_opt.getAttribute(GSXML.VALUE_ATT);
139 if (!value.equals(""))
140 {
141 this.default_document_type = value;
142 }
143 }
144 }
145
146 if (macro_resolver != null)
147 {
148 macro_resolver.setSiteDetails(this.site_http_address, this.cluster_name, this.getLibraryName());
149 // set up the macro resolver
150 Element replacement_elem = (Element) GSXML.getChildByTagName(extra_info, GSXML.REPLACE_ELEM+GSXML.LIST_MODIFIER);
151 if (replacement_elem != null)
152 {
153 macro_resolver.addMacros(replacement_elem);
154 }
155 // look for any refs to global replace lists
156 NodeList replace_refs_elems = extra_info.getElementsByTagName(GSXML.REPLACE_ELEM+GSXML.LIST_MODIFIER+GSXML.REF_MODIFIER);
157 for (int i = 0; i < replace_refs_elems.getLength(); i++)
158 {
159 String id = ((Element) replace_refs_elems.item(i)).getAttribute("id");
160 if (!id.equals(""))
161 {
162 Element replace_list = GSXML.getNamedElement(this.router.config_info, GSXML.REPLACE_ELEM+GSXML.LIST_MODIFIER, "id", id);
163 if (replace_list != null)
164 {
165 macro_resolver.addMacros(replace_list);
166 }
167 }
168 }
169 }
170
171 return true;
172 }
173
174 protected Element getServiceDescription(String service_id, String lang, String subset)
175 {
176
177 // these ones are probably never called, but put them here just in case
178 Element service_elem = this.doc.createElement(GSXML.SERVICE_ELEM);
179 service_elem.setAttribute(GSXML.TYPE_ATT, GSXML.SERVICE_TYPE_RETRIEVE);
180 service_elem.setAttribute(GSXML.NAME_ATT, service_id);
181 return service_elem;
182 }
183
184 protected Element processDocumentMetadataRetrieve(Element request)
185 {
186
187 // Create a new (empty) result message
188 Element result = this.doc.createElement(GSXML.RESPONSE_ELEM);
189 String lang = request.getAttribute(GSXML.LANG_ATT);
190 result.setAttribute(GSXML.FROM_ATT, DOCUMENT_METADATA_RETRIEVE_SERVICE);
191 result.setAttribute(GSXML.TYPE_ATT, GSXML.REQUEST_TYPE_PROCESS);
192
193 if (!does_metadata)
194 {
195 // shouldn't get here
196 return result;
197 }
198 // Get the parameters of the request
199 Element param_list = (Element) GSXML.getChildByTagName(request, GSXML.PARAM_ELEM + GSXML.LIST_MODIFIER);
200 if (param_list == null)
201 {
202 GSXML.addError(this.doc, result, "DocumentMetadataRetrieve: missing " + GSXML.PARAM_ELEM + GSXML.LIST_MODIFIER, GSXML.ERROR_TYPE_SYNTAX);
203 return result;
204 }
205
206 // The metadata information required
207 ArrayList metadata_names_list = new ArrayList();
208 boolean all_metadata = false;
209 // Process the request parameters
210 Element param = GSXML.getFirstElementChild(param_list);//(Element) param_list.getFirstChild();
211 while (param != null)
212 {
213 // Identify the metadata information desired
214 if (param.getAttribute(GSXML.NAME_ATT).equals("metadata"))
215 {
216 String metadata = GSXML.getValue(param);
217 if (metadata.equals("all"))
218 {
219 all_metadata = true;
220 break;
221 }
222 metadata_names_list.add(metadata);
223 }
224
225 param = (Element) param.getNextSibling();
226 }
227
228 // check that there has been some metadata specified
229 if (!all_metadata && metadata_names_list.size() == 0)
230 {
231 GSXML.addError(this.doc, result, "DocumentMetadataRetrieve: no metadata names found in the " + GSXML.PARAM_ELEM + GSXML.LIST_MODIFIER, GSXML.ERROR_TYPE_SYNTAX);
232 return result;
233 }
234
235 // Get the documents
236 Element request_node_list = (Element) GSXML.getChildByTagName(request, GSXML.DOC_NODE_ELEM + GSXML.LIST_MODIFIER);
237 if (request_node_list == null)
238 {
239 GSXML.addError(this.doc, result, "DocumentMetadataRetrieve: missing " + GSXML.DOC_NODE_ELEM + GSXML.LIST_MODIFIER, GSXML.ERROR_TYPE_SYNTAX);
240 return result;
241 }
242
243 // copy the request doc node list to the response
244 Element response_node_list = (Element) this.doc.importNode(request_node_list, true);
245 result.appendChild(response_node_list);
246
247 // use the copied list so that we add the metadata into the copy
248 // are we just adding metadata for the top level nodes? or can we accept a hierarchy here???
249 NodeList request_nodes = GSXML.getChildrenByTagName(response_node_list, GSXML.DOC_NODE_ELEM);
250 if (request_nodes.getLength() == 0)
251 {
252 GSXML.addError(this.doc, result, "DocumentMetadataRetrieve: no " + GSXML.DOC_NODE_ELEM + " found in the " + GSXML.DOC_NODE_ELEM + GSXML.LIST_MODIFIER, GSXML.ERROR_TYPE_SYNTAX);
253 return result;
254 }
255
256 // Whew, now we have checked (almost) all the syntax of the request, now we can process it.
257 for (int i = 0; i < request_nodes.getLength(); i++)
258 {
259 Element request_node = (Element) request_nodes.item(i);
260 String node_id = request_node.getAttribute(GSXML.NODE_ID_ATT);
261 boolean is_href_id = false;
262 if (node_id.equals("")) {
263 node_id = getGreenstoneIdFromHref(request_node);
264 if(node_id == null) {
265 // **** TODO, is this good enough???
266 request_node.setAttribute("external_link", "true");
267 continue;
268 }
269
270 }
271
272 System.err.println("getting meta for node"+node_id);
273
274 // may have modifiers .rt, .1.ss etc
275 if (idNeedsTranslating(node_id))
276 {
277 node_id = translateId(node_id);
278 }
279
280 if (node_id == null)
281 {
282 continue;
283 }
284 try
285 {
286 Element metadata_list = getMetadataList(node_id, all_metadata, metadata_names_list);
287 if(metadata_list != null)
288 {
289 request_node.appendChild(metadata_list);
290 }
291 }
292 catch (GSException e)
293 {
294 GSXML.addError(this.doc, result, e.getMessage(), e.getType());
295 if (e.getType().equals(GSXML.ERROR_TYPE_SYSTEM))
296 {
297 // there is no point trying any others
298 return result;
299 }
300 }
301
302
303 } // for each doc node
304
305 return result;
306 }
307
308 protected Element processDocumentStructureRetrieve(Element request)
309 {
310
311 // Create a new (empty) result message
312 Element result = this.doc.createElement(GSXML.RESPONSE_ELEM);
313 result.setAttribute(GSXML.FROM_ATT, DOCUMENT_STRUCTURE_RETRIEVE_SERVICE);
314 result.setAttribute(GSXML.TYPE_ATT, GSXML.REQUEST_TYPE_PROCESS);
315
316 if (!does_structure)
317 {
318 // shouldn't get here
319 return result;
320 }
321
322 String lang = request.getAttribute(GSXML.LANG_ATT);
323
324 // Get the parameters of the request
325 Element param_list = (Element) GSXML.getChildByTagName(request, GSXML.PARAM_ELEM + GSXML.LIST_MODIFIER);
326 if (param_list == null)
327 {
328 GSXML.addError(this.doc, result, "DocumentStructureRetrieve: missing " + GSXML.PARAM_ELEM + GSXML.LIST_MODIFIER, GSXML.ERROR_TYPE_SYNTAX);
329 return result;
330 }
331
332 // get the documents of the request
333 Element query_doc_list = (Element) GSXML.getChildByTagName(request, GSXML.DOC_NODE_ELEM + GSXML.LIST_MODIFIER);
334 if (query_doc_list == null)
335 {
336 GSXML.addError(this.doc, result, "DocumentStructureRetrieve: missing " + GSXML.DOC_NODE_ELEM + GSXML.LIST_MODIFIER, GSXML.ERROR_TYPE_SYNTAX);
337 return result;
338 }
339
340 // copy the doc_list to the response
341 Element response_node_list = (Element) this.doc.importNode(query_doc_list, true);
342 result.appendChild(response_node_list);
343
344 // check that we have some doc nodes specified
345 NodeList node_list = GSXML.getChildrenByTagName(response_node_list, GSXML.DOC_NODE_ELEM);
346 if (node_list.getLength() == 0)
347 {
348 GSXML.addError(this.doc, result, "DocumentStructureRetrieve: no " + GSXML.DOC_NODE_ELEM + " found in the " + GSXML.DOC_NODE_ELEM + GSXML.LIST_MODIFIER, GSXML.ERROR_TYPE_SYNTAX);
349 return result;
350 }
351
352 // the type of info required
353 boolean want_structure = false;
354 boolean want_info = false;
355
356 ArrayList info_types = new ArrayList();
357 // The document structure information desired
358 boolean want_ancestors = false;
359 boolean want_parent = false;
360 boolean want_siblings = false;
361 boolean want_children = false;
362 boolean want_descendants = false;
363
364 boolean want_entire_structure = false;
365 // Process the request parameters
366 NodeList params = param_list.getElementsByTagName(GSXML.PARAM_ELEM);
367 for (int i = 0; i < params.getLength(); i++)
368 {
369
370 Element param = (Element) params.item(i);
371 String p_name = param.getAttribute(GSXML.NAME_ATT);
372 String p_value = GSXML.getValue(param);
373 // Identify the structure information desired
374 if (p_name.equals(STRUCT_PARAM))
375 {
376 want_structure = true;
377
378 // This is NOT locale sensitive
379 if (p_value.equals(STRUCT_ANCESTORS))
380 want_ancestors = true;
381 else if (p_value.equals(STRUCT_PARENT))
382 want_parent = true;
383 else if (p_value.equals(STRUCT_SIBS))
384 want_siblings = true;
385 else if (p_value.equals(STRUCT_CHILDREN))
386 want_children = true;
387 else if (p_value.equals(STRUCT_DESCENDS))
388 want_descendants = true;
389 else if (p_value.equals(STRUCT_ENTIRE))
390 want_entire_structure = true;
391 else
392 logger.error("AbstractDocumentRetrieve Warning: Unknown value \"" + p_value + "\".");
393 }
394 else if (p_name.equals(INFO_PARAM))
395 {
396 want_info = true;
397 info_types.add(p_value);
398 }
399 }
400
401 // Make sure there is no repeated information
402 if (want_ancestors)
403 want_parent = false;
404 if (want_descendants)
405 want_children = false;
406
407 for (int i = 0; i < node_list.getLength(); i++)
408 {
409 Element doc = (Element) node_list.item(i);
410
411 String doc_id = doc.getAttribute(GSXML.NODE_ID_ATT);
412 boolean is_href_id = false;
413 if (doc_id.equals("")) {
414 doc_id = getGreenstoneIdFromHref(doc);
415 if(doc_id == null) {
416 // **** TODO, is this good enough???
417 doc.setAttribute("external_link", "true");
418 continue;
419 }
420 doc.setAttribute(GSXML.NODE_ID_ATT, doc_id);
421 }
422
423 if (idNeedsTranslating(doc_id))
424 {
425 doc_id = translateId(doc_id);
426 doc.setAttribute(GSXML.NODE_ID_ATT, doc_id);
427 }
428
429 if (doc_id == null)
430 {
431 continue;
432 }
433
434 if (want_info)
435 {
436 Element node_info_elem = this.doc.createElement("nodeStructureInfo");
437 doc.appendChild(node_info_elem);
438
439 for (int j = 0; j < info_types.size(); j++)
440 {
441 String info_type = (String) info_types.get(j);
442 String info_value = getStructureInfo(doc_id, info_type);
443 if (info_value != null)
444 {
445 Element info_elem = this.doc.createElement("info");
446 info_elem.setAttribute(GSXML.NAME_ATT, info_type);
447 info_elem.setAttribute(GSXML.VALUE_ATT, info_value);
448 node_info_elem.appendChild(info_elem);
449 }
450 }
451 }
452
453 if (want_structure)
454 {
455 // all structure info goes into a nodeStructure elem
456 Element structure_elem = this.doc.createElement(GSXML.NODE_STRUCTURE_ELEM);
457 doc.appendChild(structure_elem);
458
459 if (want_entire_structure)
460 {
461 String root_id = getRootId(doc_id);
462 Element root_node = createDocNode(root_id); //, true, false);
463 addDescendants(root_node, root_id, true);
464 structure_elem.appendChild(root_node);
465 continue; // with the next document, we dont need to do any more here
466 }
467
468 // Add the requested structure information
469 Element base_node = createDocNode(doc_id); //, false, false);
470
471 //Ancestors: continually add parent nodes until the root is reached
472 Element top_node = base_node; // the top node so far
473 if (want_ancestors)
474 {
475 String current_id = doc_id;
476 while (true)
477 {
478 String parent_id = getParentId(current_id);
479 //Element parent = getParent(current_id);
480 if (parent_id == null)
481 break; // no parent
482 Element parent_node = createDocNode(parent_id);
483 parent_node.appendChild(top_node);
484 current_id = parent_id;//.getAttribute(GSXML.NODE_ID_ATT);
485 top_node = parent_node;
486 }
487 }
488 // Parent: get the parent of the selected node
489 else if (want_parent)
490 {
491 String parent_id = getParentId(doc_id);
492 if (parent_id != null)
493 {
494 Element parent_node = createDocNode(parent_id);
495 parent_node.appendChild(base_node);
496 top_node = parent_node;
497 }
498 }
499
500 // now the top node is the root of the structure
501 structure_elem.appendChild(top_node);
502
503 //Siblings: get the other descendants of the selected node's parent
504 if (want_siblings)
505 {
506 String parent_id = getParentId(doc_id);
507 if (parent_id != null)
508 {
509 // if parent == current id, then we are at the top
510 // and can't get siblings
511 Element parent_node = (Element) base_node.getParentNode(); // this may be the structure element if there has been no request for parents or ancestors
512
513 // add siblings, - returns a pointer to the new current node
514 base_node = addSiblings(parent_node, parent_id, doc_id);
515 }
516
517 }
518
519 // Children: get the descendants, but only one level deep
520 if (want_children)
521 {
522 addDescendants(base_node, doc_id, false);
523 }
524 // Descendants: recursively get every descendant
525 else if (want_descendants)
526 {
527 addDescendants(base_node, doc_id, true);
528 }
529 } // if want structure
530
531
532 } // for each doc
533 return result;
534 }
535
536 /** Retrieve the content of a document */
537 protected Element processDocumentContentRetrieve(Element request)
538 {
539 // Create a new (empty) result message
540 Element result = this.doc.createElement(GSXML.RESPONSE_ELEM);
541 result.setAttribute(GSXML.FROM_ATT, DOCUMENT_CONTENT_RETRIEVE_SERVICE);
542 result.setAttribute(GSXML.TYPE_ATT, GSXML.REQUEST_TYPE_PROCESS);
543
544 if (!does_content)
545 {
546 // shouldn't get here
547 return result;
548 }
549
550 // Get the parameters of the request
551 Element param_list = (Element) GSXML.getChildByTagName(request, GSXML.PARAM_ELEM + GSXML.LIST_MODIFIER);
552 // Get the request content
553 Element query_doc_list = (Element) GSXML.getChildByTagName(request, GSXML.DOC_NODE_ELEM + GSXML.LIST_MODIFIER);
554 if (query_doc_list == null)
555 {
556 logger.error("Error: DocumentContentRetrieve request specified no doc nodes.\n");
557 return result;
558 }
559
560 String lang = request.getAttribute(GSXML.LANG_ATT);
561
562 // copy the request doc node list to the response
563 Element response_node_list = (Element) this.doc.importNode(query_doc_list, true);
564 result.appendChild(response_node_list);
565
566 NodeList request_nodes = GSXML.getChildrenByTagName(response_node_list, GSXML.DOC_NODE_ELEM);
567 if (request_nodes.getLength() == 0)
568 {
569 GSXML.addError(this.doc, result, "DocumentContentRetrieve: no " + GSXML.DOC_NODE_ELEM + " found in the " + GSXML.DOC_NODE_ELEM + GSXML.LIST_MODIFIER, GSXML.ERROR_TYPE_SYNTAX);
570 return result;
571 }
572
573 //Element doc_list = this.doc.createElement(GSXML.DOC_NODE_ELEM + GSXML.LIST_MODIFIER);
574 //result.appendChild(doc_list);
575
576 // set up the retrieval??
577
578 // Get the documents
579 //String[] doc_ids = GSXML.getAttributeValuesFromList(query_doc_list, GSXML.NODE_ID_ATT);
580 //String[] is_externals = GSXML.getAttributeValuesFromList(query_doc_list, "externalURL");
581
582 for (int i = 0; i < request_nodes.getLength(); i++)
583 {
584 Element request_node = (Element) request_nodes.item(i);
585 String node_id = request_node.getAttribute(GSXML.NODE_ID_ATT);
586 boolean is_href_id = false;
587 if (node_id.equals("")) {
588 node_id = getGreenstoneIdFromHref(request_node);
589 if(node_id == null) {
590 // **** TODO, is this good enough???
591 request_node.setAttribute("external_link", "true");
592 continue;
593 }
594
595 }
596
597 // may have modifiers .rt, .1.ss etc
598 if (idNeedsTranslating(node_id))
599 {
600 node_id = translateId(node_id);
601 }
602
603 if (node_id == null)
604 {
605 continue;
606 }
607 try
608 {
609 Element node_content = getNodeContent(node_id, lang);
610 request_node.appendChild(node_content);
611 }
612 catch (GSException e)
613 {
614 GSXML.addError(this.doc, result, e.getMessage());
615 return result;
616
617 }
618 } // for each node
619 return result;
620 } // processDocumentContentRetrieve
621
622 /**
623 * create an element to go into the structure. A node element has the form
624 * <docNode nodeId='xxx' nodeType='leaf' docType='hierarchy'/>
625 */
626 protected Element createDocNode(String node_id)
627 {
628 Element node = this.doc.createElement(GSXML.DOC_NODE_ELEM);
629 node.setAttribute(GSXML.NODE_ID_ATT, node_id);
630
631 String doc_type = null;
632 if (default_document_type != null)
633 {
634 doc_type = default_document_type;
635 }
636 else
637 {
638 doc_type = getDocType(node_id);
639 }
640 node.setAttribute(GSXML.DOC_TYPE_ATT, doc_type);
641 String node_type = getNodeType(node_id, doc_type);
642 node.setAttribute(GSXML.NODE_TYPE_ATT, node_type);
643 return node;
644 }
645
646 /**
647 * adds all the children of doc_id the the doc element, and if
648 * recursive=true, adds all their children as well
649 */
650 protected void addDescendants(Element doc, String doc_id, boolean recursive)
651 {
652 ArrayList child_ids = getChildrenIds(doc_id);
653 if (child_ids == null)
654 return;
655 for (int i = 0; i < child_ids.size(); i++)
656 {
657 String child_id = (String) child_ids.get(i);
658 Element child_elem = createDocNode(child_id);
659 doc.appendChild(child_elem);
660 if (recursive && (!child_elem.getAttribute(GSXML.NODE_TYPE_ATT).equals(GSXML.NODE_TYPE_LEAF) || child_elem.getAttribute(GSXML.DOC_TYPE_ATT).equals(GSXML.DOC_TYPE_PAGED)))
661 {
662 addDescendants(child_elem, child_id, recursive);
663 }
664 }
665 }
666
667 /**
668 * adds all the siblings of current_id to the parent element. returns the
669 * new current element
670 */
671 protected Element addSiblings(Element parent_node, String parent_id, String current_id)
672 {
673 Element current_node = GSXML.getFirstElementChild(parent_node);//(Element)parent_node.getFirstChild();
674 if (current_node == null)
675 {
676 // create a sensible error message
677 logger.error(" there should be a first child.");
678 return null;
679 }
680 // remove the current child,- will add it in later in its correct place
681 parent_node.removeChild(current_node);
682
683 // add in all the siblings,
684 addDescendants(parent_node, parent_id, false);
685
686 // find the node that is now the current node
687 // this assumes that the new node that was created is the same as
688 // the old one that was removed - we may want to replace the new one
689 // with the old one.
690 Element new_current = GSXML.getNamedElement(parent_node, current_node.getNodeName(), GSXML.NODE_ID_ATT, current_id);
691 return new_current;
692 }
693
694 /**
695 * returns true if oid ends in .fc (firstchild), .lc (lastchild), .pr
696 * (parent), .ns (next sibling), .ps (prev sibling), .rt (root) .ss
697 * (specified sibling), false otherwise
698 */
699 protected boolean idNeedsTranslating(String id)
700 {
701 return OID.needsTranslating(id);
702 }
703
704 /** returns the list of sibling ids, including the specified node_id */
705 protected ArrayList getSiblingIds(String node_id)
706 {
707 String parent_id = getParentId(node_id);
708 if (parent_id == null)
709 {
710 return null;
711 }
712 return getChildrenIds(parent_id);
713
714 }
715
716 /**
717 * returns the node type of the specified node. should be one of
718 * GSXML.NODE_TYPE_LEAF, GSXML.NODE_TYPE_INTERNAL, GSXML.NODE_TYPE_ROOT
719 */
720 protected String getNodeType(String node_id, String doc_type)
721 {
722 if (doc_type.equals(GSXML.DOC_TYPE_SIMPLE))
723 {
724 return GSXML.NODE_TYPE_LEAF;
725 }
726
727 if (getParentId(node_id) == null)
728 {
729 return GSXML.NODE_TYPE_ROOT;
730 }
731 if (doc_type.equals(GSXML.DOC_TYPE_PAGED))
732 {
733 return GSXML.NODE_TYPE_LEAF;
734 }
735 if (getChildrenIds(node_id) == null)
736 {
737 return GSXML.NODE_TYPE_LEAF;
738 }
739 return GSXML.NODE_TYPE_INTERNAL;
740
741 }
742
743 /**
744 * if id ends in .fc, .pc etc, then translate it to the correct id default
745 * implementation: just remove the suffix
746 */
747 protected String translateId(String id)
748 {
749 return id.substring(0, id.length());
750 }
751
752 /**
753 * if an id is not a greenstone id (an external id) then translate it to a
754 * greenstone one default implementation: return the id
755 */
756 protected String translateExternalId(String id)
757 {
758 return id;
759 }
760
761 protected String getGreenstoneIdFromHref(Element doc_node)
762 {
763 String node_id = doc_node.getAttribute(GSXML.HREF_ID_ATT);
764 node_id = translateExternalId(node_id);
765 if (node_id == null) {
766 return node_id;
767 }
768 // check for id modifiers
769 String id_mods = doc_node.getAttribute(GSXML.ID_MOD_ATT);
770 if (!id_mods.equals("")) {
771 node_id = node_id+id_mods;
772 }
773 return node_id;
774 }
775 /**
776 * returns the document type of the doc that the specified node belongs to.
777 * should be one of GSXML.DOC_TYPE_SIMPLE, GSXML.DOC_TYPE_PAGED,
778 * GSXML.DOC_TYPE_HIERARCHY default implementation: return DOC_TYPE_SIMPLE
779 */
780 protected String getDocType(String node_id)
781 {
782 return GSXML.DOC_TYPE_SIMPLE;
783 }
784
785 /**
786 * returns the id of the root node of the document containing node node_id.
787 * may be the same as node_id default implemntation: return node_id
788 */
789 protected String getRootId(String node_id)
790 {
791 return node_id;
792 }
793
794 /**
795 * returns a list of the child ids in order, null if no children default
796 * implementation: return null
797 */
798 protected ArrayList getChildrenIds(String node_id)
799 {
800 return null;
801 }
802
803 /**
804 * returns the node id of the parent node, null if no parent default
805 * implementation: return null
806 */
807 protected String getParentId(String node_id)
808 {
809 return null;
810 }
811
812 /**
813 * get the metadata for the doc node doc_id returns a metadataList element:
814 * <metadataList><metadata name="xxx">value</metadata></metadataList>
815 */
816 abstract protected Element getMetadataList(String doc_id, boolean all_metadata, ArrayList metadata_names) throws GSException;
817
818 /**
819 * returns the content of a node should return a nodeContent element:
820 * <nodeContent>text content or other elements</nodeContent> can return
821 */
822 abstract protected Element getNodeContent(String doc_id, String lang) throws GSException;
823
824 /**
825 * returns the structural information asked for. info_type may be one of
826 * INFO_NUM_SIBS, INFO_NUM_CHILDREN, INFO_SIB_POS
827 */
828 abstract protected String getStructureInfo(String doc_id, String info_type);
829
830 protected String getHrefOID(String href_url)
831 {
832 return null;
833 }
834
835}
Note: See TracBrowser for help on using the repository browser.