source: greenstone3/trunk/resources/java/QBRSOAPServer.java.in@ 15298

Last change on this file since 15298 was 15298, checked in by ak19, 16 years ago

New web service class to provide basic query, browsing and retrieval web services (QBR) for GS3

File size: 33.9 KB
Line 
1/**
2 *#########################################################################
3 * QBRSOAPServer.java.in: a template for a SOAPServer providing
4 * basic Query, Browse, Retrieve web services for Greenstone 3.
5 * Part of the Greenstone digital library suite from the New Zealand
6 * Digital Library Project at the University of Waikato, New Zealand.
7 * <BR><BR>
8 * Copyright (C) 2008 New Zealand Digital Library Project
9 * <BR><BR>
10 * This program is free software; you can redistribute it and/or modify
11 * it under the terms of the GNU General Public License as published by
12 * the Free Software Foundation; either version 2 of the License, or
13 * (at your option) any later version.
14 * <BR><BR>
15 * This program is distributed in the hope that it will be useful,
16 * but WITHOUT ANY WARRANTY; without even the implied warranty of
17 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
18 * GNU General Public License for more details.
19 * <BR><BR>
20 * @author ak19
21 * based on Katherine Don's SOAPServer@sitename@ template file.
22 *########################################################################
23 */
24
25package org.greenstone.gsdl3;
26
27import java.io.File;
28import java.io.InputStream;
29
30import java.util.Properties;
31import java.util.Enumeration;
32import java.util.Map;
33import java.util.Map.Entry;
34import java.util.HashMap;
35import java.util.Set;
36import java.util.Iterator;
37
38import org.w3c.dom.Document;
39import org.w3c.dom.Element;
40
41import org.greenstone.gsdl3.core.MessageRouter;
42import org.greenstone.gsdl3.util.GlobalProperties;
43import org.greenstone.gsdl3.util.GSFile;
44import org.greenstone.gsdl3.util.GSXML;
45import org.greenstone.gsdl3.util.XMLConverter;
46
47import org.apache.log4j.Logger; // Import log4j classes
48
49/*
50 * Add to $GSDLHOME/web/WEB-INF/server-config.wsdd:
51 * <service name="GS3WebServices" provider="java:RPC">
52 * <parameter name="allowedMethods" value="*"/>
53 * <parameter name="className" value="org.greenstone.gs3services.GS3WebServices"/>
54 * </service>
55*/
56
57/** Class that provides the basic Query, Browse and Retrieve (QBR) web service
58 * operations for Greenstone 3.
59 * It contains a MessageRouter that carries out all the tasks by calling the
60 * appropriate Greenstone functionality for each request message passed to it,
61 * and returning a response message.
62 *
63 * All response messages are returned from the MessageRouter to clients invoking
64 * the web services. All return values are strings that represent XML messages.
65 *
66 * Method help() reads from the file QBRWebServicesHelp.properties to list the web
67 * service operations available. Method helpWithMethod(String methodName)
68 * reads from the same file to display a description of the requested operation.
69 * (These method descriptions are mostly the same as those in the Javadoc
70 * comments.)
71 *
72 * NOTE: The folder containing this web service class' properties helpFile
73 * should be on the classpath. (QBRWebServicesHelp.properties)
74 * @author ak19
75*/
76public class QBRSOAPServer@sitename@ {
77 /** site_name the MessageRouter works with, here set to "localsite" */
78 protected String site_name = "@sitename@";
79
80 /** Message Router object to pass requests messages to and which
81 * will process them.*/
82 protected MessageRouter mr = null;
83
84 /** Container Document to create XML Nodes */
85 protected Document doc=null;
86 /** A converter class to parse XML and create Docs */
87 protected XMLConverter converter=null;
88
89 /** The Logger for this class */
90 private static Logger LOG = Logger.getLogger(QBRSOAPServer@[email protected]);
91
92 /** Error message loading helpFile. Remains at "" if everything is fine */
93 protected static String helpErrormessage = "";
94 /** Properties map with mappings from methodname to help
95 * description string. */
96 protected static Properties properties;
97 /** The help properties file describing the web service operations */
98 protected static String helpFile = "QBRWebServicesHelp.properties";
99
100 // static code block to initialise the help Properties from the helpFile
101 static {
102 properties = new Properties();
103 // load the properties file from a location with respect to the
104 // the Web Service .class file
105 InputStream input = null;
106 try {
107 // load the properties file from a location with respect to the
108 // the Web Service .class file
109 input
110 = QBRSOAPServer@[email protected]().getResourceAsStream(
111 helpFile);
112 if(input == null) {
113 helpErrormessage = "Cannot find file " + helpFile + " to load.";
114 LOG.warn(helpErrormessage);
115 } else {
116 properties.load(input);
117 input.close();
118 }
119 } catch(Exception e) {
120 helpErrormessage = "Exception loading properties from help file "
121 + helpFile + "\n" + e.getMessage();
122 LOG.warn("Exception loading properties from help file "
123 + helpFile + "\n" + e.getMessage());
124 }
125 }
126
127
128 /* Describe subset options for the various Greenstone3 modules */
129 protected static final String mrSubsetOptions = // messageRouter
130 "collectionList serviceClusterList serviceList siteList";
131 protected static final String csSubsetOptions = // collections and serviceClusters
132 "metadataList serviceList displayItemList";
133 protected static final String serviceSubsetOptions = // services
134 "paramList displayItemList";
135 protected static final String docStructureOptions =
136 "entire ancestors parent siblings children descendants"; // note the spelling
137 protected static final String docStructureInfo =
138 "numSiblings siblingPosition numChildren";
139 protected static final String browseStructureOptions =
140 "ancestors parent siblings children descendants"; // note the spelling
141
142
143 /** Constructor that initializes the web services' MessageRouter object
144 * Reads from GlobalProperties to get gsdl3_home and set the sitename. */
145 public QBRSOAPServer@sitename@() {
146 String gsdl3_home = GlobalProperties.getGSDL3Home();
147 if (gsdl3_home == null || gsdl3_home.equals("")) {
148 LOG.error(
149 "Couldn't access GSDL3Home from GlobalProperties.getGSDL3HOME,"
150 + "can't initialize the SOAP Server.");
151 return;
152 }
153
154 String site_home = GSFile.siteHome(gsdl3_home, this.site_name);
155
156 File site_file = new File(site_home);
157 if (!site_file.isDirectory()) {
158 LOG.error("The site directory "+site_file.getPath()
159 +" doesn't exist. Can't initialize the SOAP Server.");
160 return;
161 }
162 this.converter = new XMLConverter();
163 this.doc = this.converter.newDOM();
164
165 mr = new MessageRouter();
166 mr.setSiteName(this.site_name);
167 mr.configure();
168 }
169
170 /* (1) DESCRIBE MESSAGES, manual pages 35-41 */
171 /** Sends a describe message to the MessageRouter.
172 * @param lang is the language of the display content in the response.
173 * @param subsetOption are the requested list of items to return in the
174 * response. For the Message Router this can be collectionList,
175 * serviceClusterList, serviceList, siteList
176 * @see <a href="http://wiki.greenstone.org/wiki/index.php/Greenstone3">The Greenstone 3 Developer's Manual - pages 35-41</a>
177 */
178 public String describe(String lang, String subsetOption)
179 {
180 return describe("", lang, subsetOption, mrSubsetOptions);
181 }
182
183 /** For sending Describe messages to ServiceClusters.
184 * @param serviceCluster is the name of the Service Cluster that this describe
185 * request is sent to.
186 * @param lang is the language of the display content in the response
187 * @param subsetOption is the requested list of items to return in the response
188 * For Service Clusters this can be metadataList, serviceList, displayItemList.
189 * @see <a href="http://wiki.greenstone.org/wiki/index.php/Greenstone3">The Greenstone 3 Developer's Manual - pages 35-41</a>
190 */
191 public String describeServiceCluster(
192 String serviceCluster, String lang, String subsetOption)
193 {
194 return describe(serviceCluster, lang, subsetOption, csSubsetOptions);
195 }
196
197 /** For sending Describe messages to Collections.
198 * @param collection is the name of the Collection that this describe request
199 * is sent to.
200 * @param lang is the language of the display content in the response
201 * @param subsetOption is the requested list of items to return in the response
202 * For Collections this can be metadataList, serviceList and displayItemList.
203 * @see <a href="http://wiki.greenstone.org/wiki/index.php/Greenstone3">The Greenstone 3 Developer's Manual - pages 35-41</a>
204 */
205 public String describeCollection(
206 String collection, String lang, String subsetOption)
207 {
208 return describe(collection, lang, subsetOption, csSubsetOptions);
209 }
210
211 /**
212 * For sending a describe message to a Collection's Service.
213 * @see <a href="http://wiki.greenstone.org/wiki/index.php/Greenstone3">The Greenstone 3 Developer's Manual - pages 35-41</a>
214 * @param collection is the name of the Collection whose service
215 * this describe request is sent to.
216 * @param service is the name of the Service (of that collection) to
217 * which this describe request is sent.
218 * @param lang is the language of the display content in the response
219 * @param subsetOption is the requested list of items to return in the response
220 * For Services this can be paramList, displayItemList */
221 public String describeCollectionService(String collection, String service,
222 String lang, String subsetOption)
223 {
224 return describe(collection + "/" + service,
225 lang, subsetOption, serviceSubsetOptions);
226 }
227
228 /**
229 * For sending a describe message to a Service hosted by the Message Router
230 * (no collection).
231 * @see <a href="http://wiki.greenstone.org/wiki/index.php/Greenstone3">The Greenstone 3 Developer's Manual - pages 35-41</a>
232 * @param service is the name of the MessageRouter's Service to which this
233 * describe request is sent.
234 * @param lang is the language of the display content in the response
235 * @param subsetOption is the requested list of items to return in the response
236 * For Services this can be paramList, displayItemList
237 */
238 public String describeService(
239 String service, String lang, String subsetOption)
240 {
241 return describe(service, lang, subsetOption, serviceSubsetOptions);
242 }
243
244 /** For sending a describe message.
245 * If public, this method would give full access: a describe message that
246 * lets the user specify all the details of who the receiver is, and what
247 * details are requested.
248 * @param to - the Greenstone module (MessageRouter, Collection,
249 * ServiceCluster or (Collection-)Service to send this describe message to.
250 * (The module asked to describe itself.)
251 * @param lang - the language of the display content in the response.
252 * @param subsetOption - the set of elements of the describe response that
253 * are requested. These vary depending on the GS3 module asked to describe
254 * itself.
255 * @param validSubsetOptions - the list of subsetOptions that are allowed
256 * for the module this describe message is sent to. Parameter subsetOption
257 * has to be among the list of validSubsetOptions.
258 * @see <a href="http://wiki.greenstone.org/wiki/index.php/Greenstone3">The Greenstone 3 Developer's Manual - pages 35-41</a>
259 */
260 protected String describe(String to, String lang,
261 String subsetOption, String validSubsetOptions)
262 {
263 // Create message element: <message></message>
264 Element message = this.doc.createElement(GSXML.MESSAGE_ELEM);
265 // <message><request lang="en" to="" type="describe" uid="" /></message>
266 Element request = GSXML.createBasicRequest(
267 this.doc, GSXML.REQUEST_TYPE_DESCRIBE, to, lang, "");
268
269 // Check if only a subset of this Module Interface's data is asked
270 // to be described
271 if(!subsetOption.equals("")) {
272 // Now deal with the value for subset param:
273 // only deal with valid params for subset of to-ModuleInterface
274 if(validSubsetOptions.indexOf(subsetOption) == -1)
275 return error("Invalid List to be described. Choose one of:\n"
276 + validSubsetOptions);
277
278 // else, append <paramList>
279 // <param name="subset" value="subsetOption" /></paramList>
280 Element paramList = this.doc.createElement(
281 GSXML.PARAM_ELEM+GSXML.LIST_MODIFIER);
282 // append <param name="subset" value=paramValue />
283 // createParam(Document, name, value);
284 // Name needs to be "subset", but this can be either GSXML.SUBSET_PARAM
285 // or GSXML.SYSTEM_SUBSET_ATT. It's the first one probably.
286 paramList.appendChild(GSXML.createParameter(
287 this.doc, GSXML.SUBSET_PARAM, subsetOption));
288 request.appendChild(paramList);
289 }
290 message.appendChild(request);
291
292 // Send it off to the Message Router and return the response
293 return this.processInternal(message);
294 }
295
296 /* (2) Process-type message, QUERY-TYPE SERVICES - p.45 */
297 /** For executing a (process-type message) query-type service.
298 * @see <a href="http://wiki.greenstone.org/wiki/index.php/Greenstone3">The Greenstone 3 Developer's Manual - page 45</a>
299 * @param collection is the name of the Collection whose query service this
300 * query-process request is sent to. If "", then the Message Router is assumed.
301 * @param service is the name of the Query Service (of that collection) to
302 * which this request is sent.
303 * @param lang is the language of the display content in the response
304 * @param nameToValsMap is a Map of the (fieldname, value) pairs for the
305 * parameters of the query. The field names should be those recognised by
306 * Greenstone 3. That is, the names must exist for the (Collection-)Service Query that this
307 * message is sent To (as given in 'to' argument).
308 * For names of Greenstone-accepted arguments,
309 * @see <a href="http://wiki.greenstone.org/wiki/index.php/Actions_and_Arguments">Greenstone wiki - Actions and Arguments</a>
310 */
311 public String query(String collection, String service,
312 String lang, Map nameToValsMap)
313 {
314 // <paramList></paramList>
315 Element paramList = this.doc.createElement(
316 GSXML.PARAM_ELEM+GSXML.LIST_MODIFIER);
317 // <param>s: creating parameters of (name, value) pairs
318 Set entrySet = nameToValsMap.entrySet();
319 Iterator i = entrySet.iterator();
320 while(i.hasNext()) {
321 Entry entry = (Entry)i.next();
322 String name = (String)entry.getKey();
323 String value = (String)entry.getValue();
324 paramList.appendChild(GSXML.createParameter(
325 this.doc, name, value));
326 }
327 return queryProcess(collection+"/"+service, lang, paramList);
328 }
329
330 /** Values for field Names given in the paramList must exist for the
331 * (Collection-)Service Query that this message is sent To (as given in the
332 * 'to' argument).
333 * @see <a href="http://wiki.greenstone.org/wiki/index.php/Greenstone3">The Greenstone 3 Developer's Manual - page 45</a>
334 * @param to - the (Collection-)Service Query that this message is sent To
335 * @param lang - the language of the display items in the response
336 * @param paramList - XML Dom Element representing the list of field names,
337 * and associated values required for executing the query.
338 * For names of Greenstone-accepted arguments,
339 * @see <a href="http://wiki.greenstone.org/wiki/index.php/Actions_and_Arguments">Greenstone wiki - Actions and Arguments<a>
340 */
341 protected String queryProcess(String to, String lang, Element paramList) {
342 // must work with whatever Document was used to create the
343 // <paramList>: other elements must be created using this
344 // document object too
345 Document ownerDoc = paramList.getOwnerDocument();
346 Element message = ownerDoc.createElement(GSXML.MESSAGE_ELEM);
347 Element request = GSXML.createBasicRequest(
348 ownerDoc, GSXML.REQUEST_TYPE_PROCESS, to, lang, "");
349
350 request.appendChild(paramList);
351 message.appendChild(request);
352
353 // Send it off to the Message Router and return the response
354 return this.processInternal(message);
355 }
356
357 /* (3) RETRIEVE PROCESS METHODS - Manual, pp.47-49 */
358 /** DocumentContentRetrieve request sent to a collection's
359 * DocumentContentRetrieve service (see manual, p.48)
360 * @see <a href="http://wiki.greenstone.org/wiki/index.php/Greenstone3">The Greenstone 3 Developer's Manual - page 48</a>
361 * @param collection is the name of the Collection whose
362 * DocumentContentRetrieve is requested
363 * @param lang is the language of the display content in the response
364 * @param docNodeIDs is the list of documentNodeIDs for which the
365 * content ought to be retrieved. */
366 public String retrieveDocumentContent(
367 String collection, String lang, String[] docNodeIDs)
368 {
369 // creating <documentNodeList></documentNodeList>
370 Element docNodeList = this.doc.createElement(
371 GSXML.DOC_NODE_ELEM+GSXML.LIST_MODIFIER);
372
373 // creating subelements: <documentNode nodeID="..." />
374 for(int i = 0; i < docNodeIDs.length; i++) {
375 Element docNode = this.doc.createElement(GSXML.DOC_NODE_ELEM);
376 docNode.setAttribute(GSXML.NODE_ID_ATT, docNodeIDs[i]);
377 docNodeList.appendChild(docNode);
378 }
379
380 Element message = doc.createElement(GSXML.MESSAGE_ELEM);
381 Element request = GSXML.createBasicRequest(
382 doc, GSXML.REQUEST_TYPE_PROCESS,
383 collection+"/DocumentContentRetrieve", lang, "");
384
385 // create an empty <paramlist /> element (as example in manual)
386 Element paramlist = doc.createElement(
387 GSXML.PARAM_ELEM+GSXML.LIST_MODIFIER);
388
389 request.appendChild(paramlist);
390 request.appendChild(docNodeList);
391 message.appendChild(request);
392
393 // Send it off to the Message Router and return the response
394 return this.processInternal(message);
395 }
396
397 /** DocumentStructureRetrieve request sent to a collection's
398 * DocumentStructureRetrieve service (manual pp.48, 49) to retrieve
399 * the entire document structure.
400 * @see <a href="http://wiki.greenstone.org/wiki/index.php/Greenstone3">The Greenstone 3 Developer's Manual - pages 48, 49</a>
401 * @param collection is the name of the Collection whose
402 * DocumentStructureRetrieve is requested
403 * @param lang is the language of the display content in the response
404 * @param docNodeIDs is the list of documentNodeIDs for which the
405 * entire structure ought to be retrieved. */
406 public String retrieveEntireDocumentStructure(String collection,
407 String lang, String[] docNodeIDs)
408 {
409 return retrieveDocumentStructure(collection, lang, docNodeIDs,
410 new String[] { "entire" }, null);
411 }
412
413 /** DocumentStructureRetrieve request sent to a collection's
414 * DocumentStructureRetrieve service (manual pp.48, 49) to retrieve
415 * the specified part of the document's structure.
416 * @see <a href="http://wiki.greenstone.org/wiki/index.php/Greenstone3">The Greenstone 3 Developer's Manual - pages 48, 49</a>
417 * @param collection is the name of the Collection whose
418 * DocumentStructureRetrieve is requested
419 * @param lang is the language of the display content in the response
420 * @param docNodeIDs is the list of documentNodeIDs for which the
421 * structure ought to be retrieved.
422 * @param structure specifies what structure information needs to
423 * be retrieved. The values can be one or more of ancestors, parent,
424 * siblings, children, descendants (<b>note spelling</b>), entire.
425 * @param info - for specifying extra information to be retrieved.
426 * Possible values for info parameters are numSiblings, siblingPosition,
427 * numChildren */
428 public String retrieveDocumentStructure(String collection, String lang,
429 String[] docNodeIDs, String[] structure, String[] info)
430 {
431 // creating subelements: <documentNode nodeID="..." />
432 Element docNodeList = this.doc.createElement(
433 GSXML.DOC_NODE_ELEM+GSXML.LIST_MODIFIER);
434 for(int i = 0; i < docNodeIDs.length; i++) {
435 Element docNode = this.doc.createElement(GSXML.DOC_NODE_ELEM);
436 docNode.setAttribute(GSXML.NODE_ID_ATT, docNodeIDs[i]);
437 docNodeList.appendChild(docNode);
438 }
439
440 Element message = doc.createElement(GSXML.MESSAGE_ELEM);
441 Element request = GSXML.createBasicRequest(
442 doc, GSXML.REQUEST_TYPE_PROCESS,
443 collection+"/DocumentStructureRetrieve", lang, "");
444
445 // Create the <paramlist></paramlist> element of param elements,
446 // if any; and only if values are legal (that is, if they occur in
447 // static Strings docStructureOptions and docStructureInfo):
448 // <param name="structure" value = "structure[i]">
449 // <param name="info" value = "info[i]">
450 Element paramList = doc.createElement(
451 GSXML.PARAM_ELEM+GSXML.LIST_MODIFIER);
452
453 if(structure != null) {
454 for(int i = 0; i < structure.length; i++) {
455 if(docStructureOptions.indexOf(structure[i]) != -1) {
456 paramList.appendChild(GSXML.createParameter(
457 this.doc, "structure", structure[i]));
458 }
459 }
460 }
461 if(info != null) {
462 for(int i = 0; i < info.length; i++) {
463 if(docStructureInfo.indexOf(info[i]) != -1) {
464 paramList.appendChild(GSXML.createParameter(
465 this.doc, "info", info[i]));
466 }
467 }
468 }
469
470 // paramList is allowed to be empty and may indeed be empty:
471 request.appendChild(paramList);
472 request.appendChild(docNodeList);
473 message.appendChild(request);
474
475 // Send it off to the Message Router and return the response
476 return this.processInternal(message);
477 }
478
479 /* Retrieve for Doc Metadata: explained in the manual on page 47 */
480 /** DocumentMetadataRetrieve request sent to a collection's
481 * DocumentMetadataRetrieve service to retrieve all of a document's metadata.
482 * @see <a href="http://wiki.greenstone.org/wiki/index.php/Greenstone3">The Greenstone 3 Developer's Manual - page 47</a>
483 * @param collection is the name of the Collection whose
484 * DocumentMetadataRetrieve is requested
485 * @param lang is the language of the display content in the response
486 * @param docNodeIDs is the list of documentNodeIDs for which the
487 * structure ought to be retrieved.
488 */
489 public String retrieveAllDocumentMetadata(String collection, String lang,
490 String[] docNodeIDs)
491 {
492 // See bottom of manual p.44 for the fact that "all" is used
493 // as the metaName value when retrieving all metadata for a doc
494 return retrieveDocumentMetadata(collection, lang, docNodeIDs,
495 new String[]{ "all" });
496 }
497
498 /** DocumentMetadataRetrieve service to retrieve some specific
499 * metadata values of a document. (Manual on page 47.)
500 * @see <a href="http://wiki.greenstone.org/wiki/index.php/Greenstone3">The Greenstone 3 Developer's Manual - page 47</a>
501 * @param collection is the name of the Collection whose
502 * DocumentContentRetrieve is requested
503 * @param lang is the language of the display content in the response
504 * @param docNodeIDs is the list of documentNodeIDs for which the
505 * structure ought to be retrieved.
506 * @param metaNames is a list of metadata names which are requested
507 * to be fetched for the specified documents */
508 public String retrieveDocumentMetadata(String collection, String lang,
509 String[] docNodeIDs, String[] metaNames)
510 {
511 return metadataRetrieve(collection+"/DocumentMetadataRetrieve",
512 lang, docNodeIDs, metaNames, GSXML.DOC_NODE_ELEM);
513 }
514
515 /** Retrieve all classification Metadata for browsing (sent to the
516 * ClassifierBrowseMetadataRetrieve service).
517 * @see <a href="http://wiki.greenstone.org/wiki/index.php/Greenstone3">The Greenstone 3 Developer's Manual - pages 47, 48</a>
518 * @param collection is the name of the Collection whose
519 * ClassifierBrowseMetadataRetrieve service is called
520 * @param categoryName - name of the browsing category, usually
521 * ClassifierBrowse. (If left as "", then it defaults to ClassifierBrowse)
522 * @param lang is the language of the display content in the response
523 * @param nodeIDs is the list of document or classifier NodeIDs
524 * for which the metadata ought to be retrieved.*/
525 public String retrieveAllBrowseMetadata(String collection,
526 String categoryName, String lang, String[] nodeIDs)
527 {
528 if(categoryName.equals(""))
529 categoryName = "ClassifierBrowse";
530 // See bottom of manual p.47 for the fact that "all" is used as
531 // the metaName value when retrieving all metadata for a classifier
532 return metadataRetrieve(collection+"/"+categoryName+"MetadataRetrieve",
533 lang, nodeIDs, new String[]{ "all" }, GSXML.CLASS_NODE_ELEM);
534 }
535
536 /** ClassifierBrowseMetadataRetrieve service to retrieve some specific
537 * metadata values of a document.
538 * @see <a href="http://wiki.greenstone.org/wiki/index.php/Greenstone3">The Greenstone 3 Developer's Manual - pages 47, 48</a>
539 * @param collection is the name of the Collection whose
540 * ClassifierBrowseMetadataRetrieve service is called
541 * @param categoryName - name of the browsing category, usually
542 * ClassifierBrowse. (If left as "", then it defaults to ClassifierBrowse)
543 * @param lang is the language of the display content in the response
544 * @param nodeIDs is the list of document or classifier NodeIDs
545 * for which the metadata ought to be retrieved.
546 * @param metaNames is a list of metadata names which are requested
547 * to be fetched for the specified documents or classifiers */
548 public String retrieveBrowseMetadata(String collection, String categoryName,
549 String lang, String[] nodeIDs, String[] metaNames)
550 {
551 if(categoryName.equals(""))
552 categoryName = "ClassifierBrowse";
553 return metadataRetrieve(collection+"/"+categoryName+"MetadataRetrieve",
554 lang, nodeIDs, metaNames, GSXML.CLASS_NODE_ELEM);
555 }
556
557 /** Performs a metadata retrieve for documents and (browse) classification
558 * hierarchies. Sends a Document- or ClassifierBrowse- MetadataRetrieve message
559 * to the Document- or ClassifierBrowse- MetadataRetrieve service.
560 * @param to - the Document- or ClassifierBrowse- MetadataRetrieve service to
561 * send this metadata retrieve message to.
562 * @param lang - the language of the display content in the response
563 * @param nodeIDs - the list of (document or classifier) nodeIDs for which
564 * to retrieve the metadata for
565 * @param metaNames - a list specifiying the names of the metadata items
566 * to be retrieved for each nodeID. E.g. "Title", but a list is allowed.
567 * @param NODE_ELEM - either of GSXML's names for the &lt;documentNode&gt; or
568 * &lt;classifierNode&gt; elements.
569 */
570 protected String metadataRetrieve(String to, String lang,
571 String[] nodeIDs, String[] metaNames, final String NODE_ELEM)
572 {
573 // create the <paramlist></paramlist> element of param elements:
574 // <param name="metadata" value = "metaName[i]">
575 Element metadataParamList = this.doc.createElement(
576 GSXML.PARAM_ELEM+GSXML.LIST_MODIFIER);
577 for(int i = 0; i < metaNames.length; i++) {
578 metadataParamList.appendChild(GSXML.createParameter(
579 this.doc, GSXML.METADATA_ELEM, metaNames[i]));
580 }
581
582 // creating subelements: <documentNode nodeID="..." />
583 // or <classifierNode nodeID="..." />
584 Element nodeList = this.doc.createElement(
585 NODE_ELEM+GSXML.LIST_MODIFIER);
586 for(int i = 0; i < nodeIDs.length; i++) {
587 Element docNode = this.doc.createElement(NODE_ELEM);
588 docNode.setAttribute(GSXML.NODE_ID_ATT, nodeIDs[i]);
589 nodeList.appendChild(docNode);
590 }
591
592 Element message = doc.createElement(GSXML.MESSAGE_ELEM);
593 Element request = GSXML.createBasicRequest(doc,
594 GSXML.REQUEST_TYPE_PROCESS, to, lang, "");
595
596 request.appendChild(metadataParamList);
597 request.appendChild(nodeList);
598 message.appendChild(request);
599
600 // Send it off to the Message Router and return the response
601 return this.processInternal(message);
602 }
603
604 /* (4) Classifier BROWSE PROCESS METHODS - p.46 */
605 /** To send a browse request for all the descendants of a classifier node.
606 * Useful for getting the entire structure of a top-level &lt;classificationNode&gt;
607 * @see <a href="http://wiki.greenstone.org/wiki/index.php/Greenstone3">The Greenstone 3 Developer's Manual - page 46</a>
608 * @param collection is the name of the Collection whose browse Classifier
609 * Browse Service is called
610 * @param browseService is the name of the (Classifier) Browse Service (of
611 * the given collection) to which this request message is sent.
612 * @param lang is the language of the display content in the response
613 * @param classifierNodeIDs is an array of classifierNodeIDs for which the
614 * structures ought to be retrieved.
615 */
616 public String browseDescendants(String collection, String browseService,
617 String lang, String[] classifierNodeIDs)
618 {
619 // We are at the top level, we want all the descendants:
620 // <param name="structure" value = "descendants">
621 // <classifierNodeList><classifier nodeID="CLx" /></classifierNodeList>
622 return browse(collection, browseService, lang,
623 classifierNodeIDs,
624 new String[] {"descendants"}); // note the spelling
625 }
626
627 /** To send a browse request for specific parts of a classifier node
628 * (children, ancestors, descendants). Useful for getting specific parts
629 * of the structure of a top-level &lt;classificationNode&gt;.
630 * @see <a href="http://wiki.greenstone.org/wiki/index.php/Greenstone3">The Greenstone 3 Developer's Manual - page 46</a>
631 * @param collection is the name of the Collection whose browse Classifier
632 * Browse Service is called
633 * @param browseService is the name of the (Classifier) Browse Service (of
634 * the given collection) to which this request message is sent.
635 * @param lang is the language of the display content in the response
636 * @param classifierNodeIDs is the list of classifierNodeIDs for which the
637 * structure ought to be retrieved.
638 * @param structureParams the list of parameters indicating what structure
639 * information is requested. Accepted values are ancestors, parent, siblings,
640 * children, descendants.
641 */
642 public String browse(String collection, String browseService, String lang,
643 String[] classifierNodeIDs, String[] structureParams)
644 {
645 if(browseService.equals(""))
646 browseService = "ClassifierBrowse";
647
648 // Create message element: <message></message>
649 Element message = this.doc.createElement(GSXML.MESSAGE_ELEM);
650 // <message><request lang="en" to="" type="process" uid="" /></message>
651 Element request = GSXML.createBasicRequest(this.doc,
652 GSXML.REQUEST_TYPE_PROCESS, collection+"/"+browseService, lang, "");
653
654 // <param name="structure" value = "structureParams[i]">
655 Element paramList = this.doc.createElement(
656 GSXML.PARAM_ELEM+GSXML.LIST_MODIFIER);
657 for(int i = 0; i < structureParams.length; i++) {
658 // check it is a valid structure parameter
659 if(browseStructureOptions.indexOf(structureParams[i]) != -1) {
660 paramList.appendChild(GSXML.createParameter(
661 this.doc, "structure", structureParams[i]));
662 }
663 }
664
665 // <classifierNodeList><classifier nodeID="CLx" />
666 // <classifier nodeID="CLy" /></classifierNodeList>
667 // where CLx and CLy are given in the parameter classifierNodeIDs
668 Element classifierNodeList = this.doc.createElement(
669 GSXML.CLASS_NODE_ELEM+GSXML.LIST_MODIFIER);
670 for(int i = 0; i < classifierNodeIDs.length; i++) {
671 Element classifier = this.doc.createElement(GSXML.CLASS_NODE_ELEM);
672 classifier.setAttribute(GSXML.NODE_ID_ATT, classifierNodeIDs[i]);
673 classifierNodeList.appendChild(classifier);
674 }
675
676 // now finish constructing the request message:
677 request.appendChild(paramList);
678 request.appendChild(classifierNodeList);
679 message.appendChild(request);
680
681 // Send it off to the Message Router and return the response
682 return this.processInternal(message);
683 }
684
685 /** Called by most other methods in order to send the constructed message
686 * to the Greenstone's MessageRouter, intercept the response and return it.
687 * @param message is the XML message Element to send to GS3's MessageRouter.
688 * @return the XML response in String format. */
689 protected String processInternal(Element message) {
690 // Let the messagerouter process the request message and get the response
691 LOG.debug(this.converter.getPrettyString(message));
692
693 // Let the messagerouter process the request message and get the response
694 Element response = mr.process(message);
695 // won't be null, MR always returns some response
696
697 // Return it as a String formatted for display
698 return this.converter.getPrettyString(response);
699 }
700
701 /** Creates a String response message to represent an XML error response
702 * message using the error specified in the message parameter. A String is
703 * created because this method ensures that a response message is reliably
704 * constructed (no exceptions are thrown) that can be sent to clients.
705 * @param errorMessage - the errormessage to be conveyed
706 * @return an XML response message containing an GS3 error element. */
707 protected String error(String errorMessage) {
708 StringBuffer buf = new StringBuffer("<" + GSXML.MESSAGE_ELEM + ">");
709 buf.append("<" + GSXML.RESPONSE_ELEM + " "
710 + GSXML.FROM_ATT + "=\"" + "Greenstone 3 Web Services\"" + ">");
711 buf.append("<" + GSXML.ERROR_ELEM + " "
712 + GSXML.ERROR_TYPE_ATT + "=\""+ GSXML.ERROR_TYPE_OTHER + "\"" + ">");
713 buf.append(errorMessage+"\n");
714 buf.append("</" + GSXML.ERROR_ELEM + ">");
715 buf.append("</" + GSXML.RESPONSE_ELEM + ">");
716 buf.append("</" + GSXML.MESSAGE_ELEM + ">");
717 return buf.toString();
718 }
719
720 /*
721 Look in file QBRWebServicesHelp.properties
722 - Have a properties file that maps methodname to help string specific
723 to the method.
724 - Read it all in statically at the start of the class, into a Properties Map.
725 - When this method is called, display the usage: "help methodname"
726 and list all the available methods by going over the keys in the Map.
727 - When the helpWithMethod(String methodname) method is called, return the
728 value of the Map for the methodname key. This value would be the help
729 description for that method.
730 */
731 /** @return a help string for listing all the web service methods. */
732 public static String help() {
733 if(!helpErrormessage.equals("")) {
734 return helpErrormessage;
735 }
736
737 StringBuffer helpString = new StringBuffer(
738 "USAGE: helpWithMethod(String <method name>)\n");
739 helpString.append(
740 "\nNearly all the web service operations return a String\n");
741 helpString.append(
742 "representing a Greenstone 3 XML response message.\n");
743 helpString.append("\nA list of all the method names: \n");
744
745 Enumeration props = properties.keys();
746 while(props.hasMoreElements()){
747 String methodName = (String)props.nextElement();
748 helpString.append("\t");
749 helpString.append(methodName);
750 helpString.append("\n");
751 }
752
753 return helpString.toString();
754 }
755
756 /** @param methodname is the name of the method to be described.
757 * @return a help string for the given method, explaining what the method
758 * does, what parameters it expects and their types and what it returns.
759 */
760 public static String helpWithMethod(String methodname) {
761 if(!helpErrormessage.equals("")) {
762 return helpErrormessage;
763 }
764 // else we can get the method's description from the properties
765 // map loaded from the QBRWebServicesHelp.properties file:
766 String helpString = properties.getProperty(methodname,
767 "No description for " + methodname); // if the method does not exist
768
769 return helpString;
770 }
771} // end web service class
Note: See TracBrowser for help on using the repository browser.