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

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

Fixing Greenstone 3's use (or lack thereof) of generics, this was done automatically so we may want to change it over time. This change will also auto-format any files that have not already been formatted.

  • Property svn:keywords set to Author Date Id Revision
File size: 25.8 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 boolean is_href_id = false;
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
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.