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

Last change on this file since 36977 was 36977, checked in by kjdon, 17 months ago

made service names public so we can use them from other classes rather than hard coding the names in those classes. added ValidateDocumentId service - basically shecks whether the supplied id or list of ids is/are valid

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