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

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

Setting the nodeid so that relative links work

  • Property svn:keywords set to Author Date Id Revision
File size: 25.9 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<String> metadata_names_list = new ArrayList<String>();
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 {
264 node_id = getGreenstoneIdFromHref(request_node);
265 if (node_id == null)
266 {
267 // **** TODO, is this good enough???
268 request_node.setAttribute("external_link", "true");
269 continue;
270 }
271
272 }
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 } // for each doc node
303
304 return result;
305 }
306
307 protected Element processDocumentStructureRetrieve(Element request)
308 {
309
310 // Create a new (empty) result message
311 Element result = this.doc.createElement(GSXML.RESPONSE_ELEM);
312 result.setAttribute(GSXML.FROM_ATT, DOCUMENT_STRUCTURE_RETRIEVE_SERVICE);
313 result.setAttribute(GSXML.TYPE_ATT, GSXML.REQUEST_TYPE_PROCESS);
314
315 if (!does_structure)
316 {
317 // shouldn't get here
318 return result;
319 }
320
321 String lang = request.getAttribute(GSXML.LANG_ATT);
322
323 // Get the parameters of the request
324 Element param_list = (Element) GSXML.getChildByTagName(request, GSXML.PARAM_ELEM + GSXML.LIST_MODIFIER);
325 if (param_list == null)
326 {
327 GSXML.addError(this.doc, result, "DocumentStructureRetrieve: missing " + GSXML.PARAM_ELEM + GSXML.LIST_MODIFIER, GSXML.ERROR_TYPE_SYNTAX);
328 return result;
329 }
330
331 // get the documents of the request
332 Element query_doc_list = (Element) GSXML.getChildByTagName(request, GSXML.DOC_NODE_ELEM + GSXML.LIST_MODIFIER);
333 if (query_doc_list == null)
334 {
335 GSXML.addError(this.doc, result, "DocumentStructureRetrieve: missing " + GSXML.DOC_NODE_ELEM + GSXML.LIST_MODIFIER, GSXML.ERROR_TYPE_SYNTAX);
336 return result;
337 }
338
339 // copy the doc_list to the response
340 Element response_node_list = (Element) this.doc.importNode(query_doc_list, true);
341 result.appendChild(response_node_list);
342
343 // check that we have some doc nodes specified
344 NodeList node_list = GSXML.getChildrenByTagName(response_node_list, GSXML.DOC_NODE_ELEM);
345 if (node_list.getLength() == 0)
346 {
347 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);
348 return result;
349 }
350
351 // the type of info required
352 boolean want_structure = false;
353 boolean want_info = false;
354
355 ArrayList<String> info_types = new ArrayList<String>();
356 // The document structure information desired
357 boolean want_ancestors = false;
358 boolean want_parent = false;
359 boolean want_siblings = false;
360 boolean want_children = false;
361 boolean want_descendants = false;
362
363 boolean want_entire_structure = false;
364 // Process the request parameters
365 NodeList params = param_list.getElementsByTagName(GSXML.PARAM_ELEM);
366 for (int i = 0; i < params.getLength(); i++)
367 {
368
369 Element param = (Element) params.item(i);
370 String p_name = param.getAttribute(GSXML.NAME_ATT);
371 String p_value = GSXML.getValue(param);
372 // Identify the structure information desired
373 if (p_name.equals(STRUCT_PARAM))
374 {
375 want_structure = true;
376
377 // This is NOT locale sensitive
378 if (p_value.equals(STRUCT_ANCESTORS))
379 want_ancestors = true;
380 else if (p_value.equals(STRUCT_PARENT))
381 want_parent = true;
382 else if (p_value.equals(STRUCT_SIBS))
383 want_siblings = true;
384 else if (p_value.equals(STRUCT_CHILDREN))
385 want_children = true;
386 else if (p_value.equals(STRUCT_DESCENDS))
387 want_descendants = true;
388 else if (p_value.equals(STRUCT_ENTIRE))
389 want_entire_structure = true;
390 else
391 logger.error("AbstractDocumentRetrieve Warning: Unknown value \"" + p_value + "\".");
392 }
393 else if (p_name.equals(INFO_PARAM))
394 {
395 want_info = true;
396 info_types.add(p_value);
397 }
398 }
399
400 // Make sure there is no repeated information
401 if (want_ancestors)
402 want_parent = false;
403 if (want_descendants)
404 want_children = false;
405
406 for (int i = 0; i < node_list.getLength(); i++)
407 {
408 Element doc = (Element) node_list.item(i);
409
410 String doc_id = doc.getAttribute(GSXML.NODE_ID_ATT);
411 boolean is_href_id = false;
412 if (doc_id.equals(""))
413 {
414 doc_id = getGreenstoneIdFromHref(doc);
415 if (doc_id == null)
416 {
417 // **** TODO, is this good enough???
418 doc.setAttribute("external_link", "true");
419 continue;
420 }
421 doc.setAttribute(GSXML.NODE_ID_ATT, doc_id);
422 }
423
424 if (idNeedsTranslating(doc_id))
425 {
426 doc_id = translateId(doc_id);
427 doc.setAttribute(GSXML.NODE_ID_ATT, doc_id);
428 }
429
430 if (doc_id == null)
431 {
432 continue;
433 }
434
435 if (want_info)
436 {
437 Element node_info_elem = this.doc.createElement("nodeStructureInfo");
438 doc.appendChild(node_info_elem);
439
440 for (int j = 0; j < info_types.size(); j++)
441 {
442 String info_type = info_types.get(j);
443 String info_value = getStructureInfo(doc_id, info_type);
444 if (info_value != null)
445 {
446 Element info_elem = this.doc.createElement("info");
447 info_elem.setAttribute(GSXML.NAME_ATT, info_type);
448 info_elem.setAttribute(GSXML.VALUE_ATT, info_value);
449 node_info_elem.appendChild(info_elem);
450 }
451 }
452 }
453
454 if (want_structure)
455 {
456 // all structure info goes into a nodeStructure elem
457 Element structure_elem = this.doc.createElement(GSXML.NODE_STRUCTURE_ELEM);
458 doc.appendChild(structure_elem);
459
460 if (want_entire_structure)
461 {
462 String root_id = getRootId(doc_id);
463 Element root_node = createDocNode(root_id); //, true, false);
464 addDescendants(root_node, root_id, true);
465 structure_elem.appendChild(root_node);
466 continue; // with the next document, we dont need to do any more here
467 }
468
469 // Add the requested structure information
470 Element base_node = createDocNode(doc_id); //, false, false);
471
472 //Ancestors: continually add parent nodes until the root is reached
473 Element top_node = base_node; // the top node so far
474 if (want_ancestors)
475 {
476 String current_id = doc_id;
477 while (true)
478 {
479 String parent_id = getParentId(current_id);
480 //Element parent = getParent(current_id);
481 if (parent_id == null)
482 break; // no parent
483 Element parent_node = createDocNode(parent_id);
484 parent_node.appendChild(top_node);
485 current_id = parent_id;//.getAttribute(GSXML.NODE_ID_ATT);
486 top_node = parent_node;
487 }
488 }
489 // Parent: get the parent of the selected node
490 else if (want_parent)
491 {
492 String parent_id = getParentId(doc_id);
493 if (parent_id != null)
494 {
495 Element parent_node = createDocNode(parent_id);
496 parent_node.appendChild(base_node);
497 top_node = parent_node;
498 }
499 }
500
501 // now the top node is the root of the structure
502 structure_elem.appendChild(top_node);
503
504 //Siblings: get the other descendants of the selected node's parent
505 if (want_siblings)
506 {
507 String parent_id = getParentId(doc_id);
508 if (parent_id != null)
509 {
510 // if parent == current id, then we are at the top
511 // and can't get siblings
512 Element parent_node = (Element) base_node.getParentNode(); // this may be the structure element if there has been no request for parents or ancestors
513
514 // add siblings, - returns a pointer to the new current node
515 base_node = addSiblings(parent_node, parent_id, doc_id);
516 }
517
518 }
519
520 // Children: get the descendants, but only one level deep
521 if (want_children)
522 {
523 addDescendants(base_node, doc_id, false);
524 }
525 // Descendants: recursively get every descendant
526 else if (want_descendants)
527 {
528 addDescendants(base_node, doc_id, true);
529 }
530 } // if want structure
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
587 if (node_id.equals(""))
588 {
589 node_id = getGreenstoneIdFromHref(request_node);
590 if (node_id == null)
591 {
592 // **** TODO, is this good enough???
593 request_node.setAttribute("external_link", "true");
594 continue;
595 }
596 request_node.setAttribute(GSXML.NODE_ID_ATT, node_id);
597 }
598
599 // may have modifiers .rt, .1.ss etc
600 if (idNeedsTranslating(node_id))
601 {
602 node_id = translateId(node_id);
603 }
604
605 if (node_id == null)
606 {
607 continue;
608 }
609 try
610 {
611 Element node_content = getNodeContent(node_id, lang);
612 if (node_content != null)
613 {
614 request_node.appendChild(node_content);
615 }
616 }
617 catch (GSException e)
618 {
619 GSXML.addError(this.doc, result, e.getMessage());
620 return result;
621 }
622 } // for each node
623 return result;
624 } // processDocumentContentRetrieve
625
626 /**
627 * create an element to go into the structure. A node element has the form
628 * <docNode nodeId='xxx' nodeType='leaf' docType='hierarchy'/>
629 */
630 protected Element createDocNode(String node_id)
631 {
632 Element node = this.doc.createElement(GSXML.DOC_NODE_ELEM);
633 node.setAttribute(GSXML.NODE_ID_ATT, node_id);
634
635 String doc_type = null;
636 if (default_document_type != null)
637 {
638 doc_type = default_document_type;
639 }
640 else
641 {
642 doc_type = getDocType(node_id);
643 }
644 node.setAttribute(GSXML.DOC_TYPE_ATT, doc_type);
645 String node_type = getNodeType(node_id, doc_type);
646 node.setAttribute(GSXML.NODE_TYPE_ATT, node_type);
647 return node;
648 }
649
650 /**
651 * adds all the children of doc_id the the doc element, and if
652 * recursive=true, adds all their children as well
653 */
654 protected void addDescendants(Element doc, String doc_id, boolean recursive)
655 {
656 ArrayList<String> child_ids = getChildrenIds(doc_id);
657 if (child_ids == null)
658 return;
659 for (int i = 0; i < child_ids.size(); i++)
660 {
661 String child_id = child_ids.get(i);
662 Element child_elem = createDocNode(child_id);
663 doc.appendChild(child_elem);
664 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)))
665 {
666 addDescendants(child_elem, child_id, recursive);
667 }
668 }
669 }
670
671 /**
672 * adds all the siblings of current_id to the parent element. returns the
673 * new current element
674 */
675 protected Element addSiblings(Element parent_node, String parent_id, String current_id)
676 {
677 Element current_node = GSXML.getFirstElementChild(parent_node);//(Element)parent_node.getFirstChild();
678 if (current_node == null)
679 {
680 // create a sensible error message
681 logger.error(" there should be a first child.");
682 return null;
683 }
684 // remove the current child,- will add it in later in its correct place
685 parent_node.removeChild(current_node);
686
687 // add in all the siblings,
688 addDescendants(parent_node, parent_id, false);
689
690 // find the node that is now the current node
691 // this assumes that the new node that was created is the same as
692 // the old one that was removed - we may want to replace the new one
693 // with the old one.
694 Element new_current = GSXML.getNamedElement(parent_node, current_node.getNodeName(), GSXML.NODE_ID_ATT, current_id);
695 return new_current;
696 }
697
698 /**
699 * returns true if oid ends in .fc (firstchild), .lc (lastchild), .pr
700 * (parent), .ns (next sibling), .ps (prev sibling), .rt (root) .ss
701 * (specified sibling), false otherwise
702 */
703 protected boolean idNeedsTranslating(String id)
704 {
705 return OID.needsTranslating(id);
706 }
707
708 /** returns the list of sibling ids, including the specified node_id */
709 protected ArrayList<String> getSiblingIds(String node_id)
710 {
711 String parent_id = getParentId(node_id);
712 if (parent_id == null)
713 {
714 return null;
715 }
716 return getChildrenIds(parent_id);
717
718 }
719
720 /**
721 * returns the node type of the specified node. should be one of
722 * GSXML.NODE_TYPE_LEAF, GSXML.NODE_TYPE_INTERNAL, GSXML.NODE_TYPE_ROOT
723 */
724 protected String getNodeType(String node_id, String doc_type)
725 {
726 if (doc_type.equals(GSXML.DOC_TYPE_SIMPLE))
727 {
728 return GSXML.NODE_TYPE_LEAF;
729 }
730
731 if (getParentId(node_id) == null)
732 {
733 return GSXML.NODE_TYPE_ROOT;
734 }
735 if (doc_type.equals(GSXML.DOC_TYPE_PAGED))
736 {
737 return GSXML.NODE_TYPE_LEAF;
738 }
739 if (getChildrenIds(node_id) == null)
740 {
741 return GSXML.NODE_TYPE_LEAF;
742 }
743 return GSXML.NODE_TYPE_INTERNAL;
744
745 }
746
747 /**
748 * if id ends in .fc, .pc etc, then translate it to the correct id default
749 * implementation: just remove the suffix
750 */
751 protected String translateId(String id)
752 {
753 return id.substring(0, id.length());
754 }
755
756 /**
757 * if an id is not a greenstone id (an external id) then translate it to a
758 * greenstone one default implementation: return the id
759 */
760 protected String translateExternalId(String id)
761 {
762 return id;
763 }
764
765 protected String getGreenstoneIdFromHref(Element doc_node)
766 {
767 String node_id = doc_node.getAttribute(GSXML.HREF_ID_ATT);
768 node_id = translateExternalId(node_id);
769 if (node_id == null)
770 {
771 return node_id;
772 }
773 // check for id modifiers
774 String id_mods = doc_node.getAttribute(GSXML.ID_MOD_ATT);
775 if (!id_mods.equals(""))
776 {
777 node_id = node_id + id_mods;
778 }
779 return node_id;
780 }
781
782 /**
783 * returns the document type of the doc that the specified node belongs to.
784 * should be one of GSXML.DOC_TYPE_SIMPLE, GSXML.DOC_TYPE_PAGED,
785 * GSXML.DOC_TYPE_HIERARCHY default implementation: return DOC_TYPE_SIMPLE
786 */
787 protected String getDocType(String node_id)
788 {
789 return GSXML.DOC_TYPE_HIERARCHY;
790 }
791
792 /**
793 * returns the id of the root node of the document containing node node_id.
794 * may be the same as node_id default implemntation: return node_id
795 */
796 protected String getRootId(String node_id)
797 {
798 return node_id;
799 }
800
801 /**
802 * returns a list of the child ids in order, null if no children default
803 * implementation: return null
804 */
805 protected ArrayList<String> getChildrenIds(String node_id)
806 {
807 return null;
808 }
809
810 /**
811 * returns the node id of the parent node, null if no parent default
812 * implementation: return null
813 */
814 protected String getParentId(String node_id)
815 {
816 return null;
817 }
818
819 /**
820 * get the metadata for the doc node doc_id returns a metadataList element:
821 * <metadataList><metadata name="xxx">value</metadata></metadataList>
822 */
823 abstract protected Element getMetadataList(String doc_id, boolean all_metadata, ArrayList<String> metadata_names) throws GSException;
824
825 /**
826 * returns the content of a node should return a nodeContent element:
827 * <nodeContent>text content or other elements</nodeContent> can return
828 */
829 abstract protected Element getNodeContent(String doc_id, String lang) throws GSException;
830
831 /**
832 * returns the structural information asked for. info_type may be one of
833 * INFO_NUM_SIBS, INFO_NUM_CHILDREN, INFO_SIB_POS
834 */
835 abstract protected String getStructureInfo(String doc_id, String info_type);
836
837 protected String getHrefOID(String href_url)
838 {
839 return null;
840 }
841
842}
Note: See TracBrowser for help on using the repository browser.