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

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

Removed an unnecessary debug statement

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