source: other-projects/trunk/gs3-webservices-democlient/src/GS3Fedora/org/greenstone/fedora/services/FedoraGS3Connection.java@ 15331

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

Corrected method initSearchFunctionality() and changed property name from gSearch.WsdlURL to gsearch.wsdlURL

File size: 89.6 KB
Line 
1/**
2 *#########################################################################
3 * FedoraGS3Connection.java - works with the demo-client for Greenstone 3,
4 * of the Greenstone digital library suite from the New Zealand Digital
5 * Library Project at the * University of Waikato, New Zealand.
6 * <BR><BR>
7 * Copyright (C) 2008 New Zealand Digital Library Project
8 * <BR><BR>
9 * This program is free software; you can redistribute it and/or modify
10 * it under the terms of the GNU General Public License as published by
11 * the Free Software Foundation; either version 2 of the License, or
12 * (at your option) any later version.
13 * <BR><BR>
14 * This program is distributed in the hope that it will be useful,
15 * but WITHOUT ANY WARRANTY; without even the implied warranty of
16 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17 * GNU General Public License for more details.
18 *########################################################################
19 */
20
21package org.greenstone.fedora.services;
22
23
24import java.io.StringReader;
25
26import org.apache.log4j.Logger;
27import org.greenstone.fedora.services.FedoraGS3Exception.AuthenticationFailedException;
28import org.greenstone.fedora.services.FedoraGS3Exception.CancelledException;
29import org.greenstone.fedora.services.FedoraGS3Exception.FedoraGS3RunException;
30import org.greenstone.fedora.services.FedoraGS3Exception.NotAFedoraServerException;
31import org.greenstone.fedora.services.FedoraToGS3Interface.Constants;
32import org.greenstone.gsdl3.util.GSXML;
33import org.w3c.dom.Document;
34import org.w3c.dom.Element;
35import org.w3c.dom.Attr;
36import org.w3c.dom.Text;
37import org.w3c.dom.NodeList;
38import org.w3c.dom.Node;
39import org.xml.sax.InputSource;
40
41import java.io.File;
42import java.util.HashMap;
43import java.util.Properties;
44import java.util.Map;
45
46import javax.swing.JOptionPane;
47
48import org.xml.sax.SAXException;
49import java.io.UnsupportedEncodingException;
50import java.io.IOException;
51import javax.net.ssl.SSLHandshakeException;
52import java.net.ConnectException;
53import java.net.MalformedURLException;
54import java.rmi.RemoteException;
55import javax.xml.parsers.ParserConfigurationException;
56import javax.xml.transform.TransformerException;
57
58/**
59 * Class that extends FedoraConnection in order to be able to use
60 * Fedora's web services to retrieve the specific datastreams of
61 * Greenstone documents stored in Fedora's repository. This class
62 * provides methods that convert those datastreams into Greenstone3
63 * XML response messages which are returned.
64 * @author ak19
65*/
66public class FedoraGS3Connection
67 extends FedoraConnection implements FedoraToGS3Interface,
68 FedoraToGS3Interface.Constants
69{
70 /** The logging instance for this class */
71 private static final Logger LOG = Logger.getLogger(
72 FedoraGS3Connection.class.getName());
73
74 /** The last part of the gSearchWSDL URL. The first part is
75 * the same as the fedora server's base url. */
76 protected static final String gSearchWSDLSuffix
77 = "gsearch/services/FgsOperations?wsdl";
78
79 /** Complete list of services that are supported our FedoraGS3 would
80 * support if everything goes well. If a connection to FedoraGSearch
81 * cannot be established, the query services will no longer be
82 * available. The actual services supported are given by member
83 * variable serviceNames. */
84 protected static final String[] SERVICES = {
85 "DocumentContentRetrieve", "DocumentMetadataRetrieve",
86 "DocumentStructureRetrieve",
87 "TextQuery", "FieldQuery",
88 "ClassifierBrowse", "ClassifierBrowseMetadataRetrieve"
89 };
90
91 /** List of services actually supported by our FedoraGS3 repository
92 * after construction. If FedoraGenericSearch can't be connected to,
93 * then query services will not be offered */
94 protected String[] serviceNames;
95
96 /** constant CHILDREN indicates that a DocumentStructureRetrieve is to
97 * return only the child nodes of a section, not any further descendants */
98 protected static final int CHILDREN = 0;
99
100 /** constant DESCENDANTS indicates that a DocumentStructureRetrieve is to
101 * return all descendants of a section */
102 protected static final int DESCENDANTS = 1;
103
104 /** The object used to connect to FedoraGenericSearch, which is used
105 * for doing full-text searching */
106 protected GSearchConnection fedoraGSearch;
107
108 /** The url for the wsdl file of FedoraGSearch's web services
109 * by default this will be the Fedora server's base URL
110 * concatenated to "gsearch/services/FgsOperations?wsdl" */
111 protected String gSearchWSDLURL;
112
113 /** 5 argument constructor is the same as that of superclass FedoraConnection:
114 * @param protocol can be either http or https
115 * @param host is the host where the fedora server is listening
116 * @param port is the port where the fedora server is listening
117 * @param fedoraServerUsername is the username for administrative
118 * authentication required to access the fedora server.
119 * @param fedoraServerPassword is the password for administrative
120 * authentication required to access the fedora server. If no password was set
121 * when installing Fedora, leave the field "".
122 * Instantiates a FedoraGS3Connection object which connects to Fedora's
123 * web services through stub classes and tries to connect to FedoraGSearch's
124 * web services through the default WSDL location for it
125 * ("gsearch/services/FgsOperations?wsdl"). If another url is to be used,
126 * call setGSearchWSDLURL(url) after the constructor instead.
127 */
128 public FedoraGS3Connection(String protocol, String host, int port,
129 String fedoraServerUsername, String fedoraServerPassword)
130 throws ParserConfigurationException, MalformedURLException,
131 SSLHandshakeException, RemoteException, AuthenticationFailedException,
132 NotAFedoraServerException, ConnectException, Exception
133 {
134 super(protocol, host, port, fedoraServerUsername, fedoraServerPassword);
135 // super() will call setInitialisationProperties(properties)
136 // And that will try to instantiate the GSearchConnection.
137 }
138
139 /** No-argument constructor which is the same as that of superclass
140 * FedoraConnection: it displays a small dialog requesting input for the
141 * host, port, administrative password and username of the fedora server.
142 * If no password was set on the fedora repository when installing it,
143 * the user can leave the password field blank. */
144 public FedoraGS3Connection()
145 throws ParserConfigurationException, MalformedURLException,
146 CancelledException, ConnectException, RemoteException,
147 SSLHandshakeException, Exception
148 {
149 super();
150 // super() will call setInitialisationProperties(properties)
151 // And that will try to instantiate the GSearchConnection.
152 }
153
154 /** Single-argument constructor which is the same as that of superclass
155 * FedoraConnection: it takes the name of the properties file where
156 * connection initialisation values may already be provided and then
157 * displays a small dialog requesting input for the host, port,
158 * administrative password and username of the fedora server showing
159 * the values in the properties file as default. If the necessary
160 * initialisation are not present in the file, they corresponding fields
161 * in the dialog will be blank.
162 * If no password was set on the fedora repository when installing it,
163 * the user can leave the password field blank. */
164 public FedoraGS3Connection(File propertiesFilename)
165 throws ParserConfigurationException, MalformedURLException,
166 CancelledException, ConnectException, RemoteException,
167 SSLHandshakeException, Exception
168 {
169 super(propertiesFilename);
170 // super() will call setInitialisationProperties(properties)
171 // And that will try to instantiate the GSearchConnection.
172 }
173
174 /** The superclass constructor calls this method passing any preset
175 * properties loaded from a propertiesFile. This method is overridden
176 * here in order to instantiate the gSearchConnection based on the
177 * gSearchWSDLURL. (If one was not provided in the properties file,
178 * gSearchWSDLURL defaults to something of the form
179 * "http://localhost:8080/fedoragsearch/services/FgsOperations?wsdl"
180 * where http://localhost:8080/fedora is the baseURL of fedora and
181 * "gsearch/services/FgsOperations?wsdl" is the default gSearchWSDLSuffix.)
182 * @param properties is the Properties Map loaded from a properties file
183 * (if there was any) which specifies such things as host and port of the
184 * FedoraServer, but can also specify the property "gsearch.wsdlURL".
185 * At the end of this method, properties' "gsearch.wsdlURL" will be set
186 * to whatever the final value of this.gSearchWSDLURL is.
187 */
188 protected void setInitialisationProperties(Properties properties)
189 throws ParserConfigurationException, MalformedURLException,
190 CancelledException, ConnectException, RemoteException,
191 SSLHandshakeException, Exception
192 {
193 super.setInitialisationProperties(properties);
194 // gsearchWSDL URL, if not specified, defaults to something of the form:
195 // "http://localhost:8080/fedoragsearch/services/FgsOperations?wsdl"
196 // where http://localhost:8080/fedora is the baseURL of fedora
197 this.gSearchWSDLURL = properties.getProperty(
198 "gsearch.wsdlURL", this.baseURL+gSearchWSDLSuffix);
199 // Set the property to whatever this.gSearchWSDLURL is now,
200 // so that it will be written out to the properties file again
201 properties.setProperty("gsearch.wsdlURL", this.gSearchWSDLURL);
202 // Create a connection to FedoraGSearch's web services:
203 initSearchFunctionality();
204 }
205
206 /** Init method that instantiates a GSearchConnection object used
207 * to work with the separate FedoraGSearch web services.
208 * The url of the WSDL for FedoraGSearch's web services is worked out
209 * from the baseURL of the Fedora server.
210 */
211 protected void initSearchFunctionality()
212 {
213 try {
214 this.fedoraGSearch = new GSearchConnection(gSearchWSDLURL);
215 this.serviceNames = SERVICES;
216 } catch(Exception e){
217 LOG.error("Cannot connect to FedoraGSearch's web services at "
218 + gSearchWSDLURL + "\nQuery services will not be available.");
219 // If an exception occurs, something has gone wrong when
220 // trying to connect to FedoraGSearch's web services. This
221 // means, we can't offer query services, as that's provided
222 // by FedoraGSearch
223 serviceNames = null;
224 int countOfNonQueryServices = 0;
225 for(int i = 0; i < SERVICES.length; i++) {
226 // do not count query services
227 if(!SERVICES[i].toLowerCase().contains("query")) {
228 countOfNonQueryServices++;
229 }
230 }
231 // Services now supported are everything except Query services
232 serviceNames = new String[countOfNonQueryServices];
233 int j = 0;
234 for(int i = 0; i < SERVICES.length; i++) {
235 if(!SERVICES[i].toLowerCase().contains("query")) {
236 serviceNames[j] = SERVICES[i];
237 j++; // valid serviceName, so increment serviceName counter
238 }
239
240 }
241 }
242 }
243
244 /** @return the gSearchWSDLURL, the url of the WSDL for the
245 * FedoraGSearch web services */
246 public String getGSearchWSDLURL() { return gSearchWSDLURL; }
247
248 /** Sets the member variable gSearchWSDLURL that specify the location of
249 * the WSDL file of FedoraGSearch's web services. Then it attempts
250 * to instantiate a connection to those web services.
251 * @param url is the new url of the GSearch web services WSDL file */
252 public void setGSearchWSDLURL(String url) {
253 gSearchWSDLURL = url;
254 initSearchFunctionality();
255 }
256
257 /** @return the array of the services actually supported by FedoraGS3 */
258 protected String[] getServiceNames() { return this.serviceNames;}
259
260 /**
261 * For finding out if the sectionNumber is given as part of the docID.
262 * @param docID is the String that contains the docPID and may also
263 * contain the section number.
264 * @return true if the document identifier docID contains a section-
265 * number, and false if it consists solely of the docPID.
266 * That is, true is returned if
267 * <pre>docID = "greenstone:colName-&lt;docPID&gt;-&lt;sectionNum&gt;"</pre>
268 * and false is returned if
269 * <pre>docID = "greenstone:colName-&lt;docPID&gt;"</pre>
270 * */
271 protected boolean containsSectionNumber(String docID) {
272 // if there are two hyphens in the docID, then there are sections
273 // (and the section number is appended at end of docID)
274 // docID = "greenstone:colName-<docPID>-<sectionNum>"
275 return (docID.lastIndexOf(HYPHEN) != docID.indexOf(HYPHEN));
276 }
277
278 /** This method will extract the docPID from docID and return it.
279 * (If a sectionNumber is suffixed to the docID, the docPID which is
280 * the prefix is returned; otherwise the docID is the docPID and is
281 * returned)
282 * @param docID is the String that contains the docPID and may also
283 * contain the section number.
284 * @return only the docPID portion of the docID.
285 */
286 protected String getDocPIDFromDocID(String docID) {
287 if(containsSectionNumber(docID))
288 return docID.substring(0, docID.lastIndexOf(HYPHEN));
289 // else (if there's no sectionNumber), docID is the docPID
290 return docID;
291 }
292
293 /** This method will return the section Number, if there's any
294 * suffixed to the docID. Otherwise it will return the empty string
295 * @param docID is the String that contains the docPID and may also
296 * contain the section number.
297 * @return only the sectionID portion of the docID - if any, else "".
298 */
299 protected String getSectionIDFromDocID(String docID) {
300 if(containsSectionNumber(docID))
301 return docID.substring(
302 docID.lastIndexOf(HYPHEN)+1, docID.length());
303 return "";
304 }
305
306 /** Given a list of collectionIDs, returns a GS3 DocumentMetadataRetrieve
307 * response message that gives the metadata for each collection identified
308 * @param collIDs is an array of fedora pids identifying collections in the
309 * fedora repository
310 * @return a GS3 DocumentMetadataRetrieve response message containing the
311 * EX metadata for all the requested collections */
312 public String getCollectionMetadata(String[] collIDs) {
313 return getMetadata(collIDs);
314 }
315
316 /** Given a list of document identifiers, a GS3 DocumentMetadataRetrieve
317 * response message is returned containing the metadata for each document.
318 * @param docIDs is an array of document identifiers (docID can either be
319 * &lt;pid&gt;s items (documents) in the fedora repository, or
320 * "&lt;pid&gt;-sectionNumber".
321 * @return a GS3 DocumentMetadataRetrieve response message containing the
322 * EX, DC, DLS metadata for all the requested documents */
323 public String getDocumentMetadata(String[] docIDs) {
324 return getMetadata(docIDs);
325 }
326
327 /** Given a collectionID, returns a GS3 DocumentMetadataRetrieve
328 * response message that gives the metadata for the collection identified
329 * @param collID is a fedora pid identifying a collection in its repository
330 * @return a GS3 DocumentMetadataRetrieve response message containing the
331 * EX metadata for the requested collection */
332 public String getCollectionMetadata(String collID) {
333 return getMetadata(new String[] {collID});
334 }
335
336 /** Given a document identifier, returns a GS3 DocumentMetadataRetrieve
337 * response message containing the metadata for the document.
338 * @param docID is a document identifier (docID can either be a &lt;pid&gt;
339 * of an item (document) in the fedora repository, or it can be
340 * "&lt;pid&gt;-sectionNumber".
341 * @return a GS3 DocumentMetadataRetrieve response message containing the
342 * EX, DC, DLS metadata for the requested document */
343 public String getDocumentMetadata(String docID) {
344 return getMetadata(new String[] {docID});
345 }
346
347 /** @return a greenstone DocumentMetadataRetrieve response for the
348 * documents or collections indicated by the docIDsOrCollIDs.
349 * @param docIDsOrCollIDs is an array of identifiers which may be either the
350 * fedora pids for collections, or otherwise may be a document identifier.
351 * In the last case, the document ID may consist of either
352 * "documentPID-sectionNumber" or may just be just fedora documentPID */
353 public String getMetadata(String[] docIDsOrCollIDs)
354 {
355 Document doc = builder.newDocument();
356 FedoraGS3RunException ex = null;
357
358 Element docNodeList = doc.createElement(
359 GSXML.DOC_NODE_ELEM+GSXML.LIST_MODIFIER);
360
361 try{
362 for(int i = 0; i < docIDsOrCollIDs.length; i++) {
363 // create the <documentNode> containing the metadata
364 // for each document docID
365 Element docNode = getMetadata(doc, docIDsOrCollIDs[i]);
366 docNodeList.appendChild(docNode);
367 }
368 } catch(Exception e) {
369 ex = new FedoraGS3RunException(e);
370 ex.setSpecifics("EX (and/or DC, DLS) metadata datastream");
371 }
372
373 Element responseMsg = createResponseMessage(doc, docNodeList, ex,
374 GSXML.REQUEST_TYPE_PROCESS, "DocumentMetadataRetrieve");
375 try{
376 return FedoraCommons.elementToFormattedString(responseMsg);
377 } catch(TransformerException e) {
378 return FedoraGS3RunException.xmlToStringConversionFailureResponseMsg
379 + " " + e;
380 }
381 }
382
383 /** Method that takes a new DOM document, as well as an identifier of either
384 * a collection or document (which may be a fedora pid for the collection
385 * or document, or may be the documentPid-sectionNumber for a document) and
386 * returns a documentNode element for it:
387 * &lt;documentNode&gt;&lt;metadataList&gt;
388 * &lt;metadata name=""&gt;value&lt;/metadata&gt;
389 * ...
390 * &lt;/metadataList&gt;&lt;/documentNode&gt;
391 * @return documentNode containing the metadata for the collection or
392 * document given by parameter ID
393 * @param id denotes a collection pid, a document pid or a docID of the
394 * form "documentpid-sectionNumber" */
395 protected Element getMetadata(Document doc, String id)
396 throws RemoteException, UnsupportedEncodingException,
397 SAXException, IOException
398 {
399 // We're going to create the documentNode nested inside the following
400 // documentNodeList:
401 // <documentNodeList>
402 // <documentNode nodeID=""><metadataList>
403 // <metadata name="">value</metadata>
404 // </metadataList></documentNode>
405 // <documentNode>...</documentNode>
406 // </documentNodeList>
407 // <documentNodeList>
408
409 // <documentNode nodeID="docID"> - the docNode on which a structure
410 // retrieve is being performed
411 Element docNode = doc.createElement(GSXML.DOC_NODE_ELEM);
412 Attr attribute = doc.createAttribute(GSXML.NODE_ID_ATT);
413 attribute.setValue(id);
414 docNode.setAttributeNode(attribute);
415
416 // <metadataList>
417 Element metadataList = doc.createElement(
418 GSXML.METADATA_ELEM+GSXML.LIST_MODIFIER);
419
420 String ex = "";
421 String dc = "";
422 String dls = "";
423 if(id.endsWith(_COLLECTION)) { // docID refers to a collection
424 // Obtain the "EX" datastream (extracted metadata) for the collection
425 ex = this.getEX(id);
426 }
427 else { // docID refers to a document
428 // work out the document's fedora PID and section ID, and then
429 // obtain the EX (extracted metadata) and DC datastreams for the doc
430
431 // Note that EX/DC for pid="greenstone:<colname>-docPID-1"
432 // is the same as for pid="greenstone:<colname>-docPID"
433 // That is, <Section id="1"> refers to the toplevel document docPID
434 // If requested for top-level document, there may also be DLS meta
435 String sectionID = getSectionIDFromDocID(id);
436 String docPID = getDocPIDFromDocID(id);
437 if(sectionID.equals("") || sectionID.equals("1")) {
438 //metadata of toplevel document is requested
439 ex = this.getEX(docPID); // slightly faster than doing
440 //getSectionEXMetadata(docID, "1")
441 dc = this.getDC(docPID);
442 dls = this.getDLS(docPID);
443 }
444 else {
445 ex = getSectionEXMetadata(docPID, sectionID);
446 dc = getSectionDCMetadata(docPID, sectionID);
447 }
448 }
449
450 // Adding in metadata sets in alphabetical order
451 // DC metadata for a top-level document is different from EX, DLS:
452 // only the element's namespace prefix is "dc", the rest of a tagname
453 // is unknown.
454 if(!dc.equals("")) {
455 addMetadataWithNamespacedTagNames(doc, metadataList,
456 dc, DC);
457 }
458
459 // Check if we were supposed to process dls and dc metadata
460 // as well. We only ever do this for top-level documents,
461 // in which case, dls and dc will be non-empty strings
462 if(!dls.equals("")) {
463 addMetadataWithFixedTagName(doc, metadataList, dls, DLS);
464 }
465
466 // we definitely have an EX metadatastream for each
467 // collection object, top-level document object,
468 // and document section item
469 addMetadataWithFixedTagName(doc, metadataList, ex, EX);
470
471 // now the metadataList has been built up
472 docNode.appendChild(metadataList);
473
474 return docNode; // return <documentNode> containing the metadata
475 }
476
477 /** This method retrieves all the metadata elements in the metaDataStream
478 * parameter of the form &lt;"metadataSetNS:metadata"&gt;"value"&lt;/metadata&gt; where
479 * metadataSetNS is the namespace of each tag, and creates a new element of
480 * the form &lt;metadata name="metadataSetNS:metadata"&gt;"value"&lt;/metadata&gt; for
481 * each. Each of these are then appended to the metadataList parameter.
482 * @param doc is the Document object using which the new metadata Elements
483 * are to be constructed
484 * @param metadataList is the &lt;metadataList&gt; Element to which the new
485 * metadata Elements are to be appended as children.
486 * @param metaDatastream the metadata datastream in string form (e.g. the
487 * Dublin Core metadata stored in the Fedora repository).
488 * @param metadataSet is the constant datastream identifier, e.g. "DC".
489 * At present this method only applies to the DC metadata as that's the only
490 * one where each tagname is different except for the constant dc: namespace.
491 */
492 protected void addMetadataWithNamespacedTagNames(Document doc,
493 Element metadataList, String metaDatastream, String metadataSet)
494 throws SAXException, IOException
495 {
496 Document src = builder.parse(
497 new InputSource(new StringReader(metaDatastream)));
498
499 // The following doesn't work for some reason: to retrieve all elements
500 // whose namespace prefix starts with "dc", we pass "*" for localName
501 //NodeList dcMetaTags = src.getElementsByTagNameNS(DC.toLowerCase(), "*");
502
503 // Longer way: get the children of the root document
504 NodeList children = src.getDocumentElement().getChildNodes();
505
506 for(int i = 0; i < children.getLength(); i++) {
507 String nodeName = children.item(i).getNodeName();
508 // check that the nodename starts with the "dc" namespace,
509 // which simultaneously ensures that the node's an element:
510 if(nodeName.startsWith(DC.toLowerCase())) {
511 // need to have a period for Greenstone instead of Fedora's colon
512 nodeName = nodeName.replace(COLON, PERIOD);
513 Element metatag = (Element)children.item(i);
514 String value = FedoraCommons.getValue(metatag);
515 // <dc:tagname>value</dc:tagname>
516 // we're going to put use this in our metadata element as
517 // <metadata name="dc:tagname">value</metadata>
518
519 // create metadata of (name, value) pairs in target DOM (doc)
520 Element metadata = doc.createElement(GSXML.METADATA_ELEM);
521 Attr attribute = doc.createAttribute(GSXML.NAME_ATT);
522 attribute.setValue(nodeName);
523 metadata.setAttributeNode(attribute);
524 Text content = doc.createTextNode(value);
525 metadata.appendChild(content);
526 metadataList.appendChild(metadata);
527 }
528 }
529 }
530
531 /** This method retrieves all the metadata elements in the metaDataStream
532 * of the form &lt;"namespace:"metadata name="metadataName"&gt;value&lt;/metadata&gt;
533 * where "namespace" is the namespace prefix of each tag, and metadataName
534 * is the name of the metadata (like author, title). For each element
535 * it creates a corresponding new element of the form
536 * &lt;metadata name="namespace:metadataName"&gt;value&lt;/metadata&gt;. Each of these
537 * are then appended to the metadataList parameter.
538 * @param doc is the Document object using which the new metadata Elements
539 * are to be constructed
540 * @param metadataList is the &lt;metadataList&gt; Element to which the new
541 * metadata Elements are to be appended as children.
542 * @param metaDatastream the metadata datastream in string form (e.g. the
543 * EX/Greenstone extracted metadata or DLS metadata stored in the Fedora
544 * repository).
545 * @param metadataSet is the constant datastream identifier,
546 * e.g. "DLS" or "EX".
547 * At present this method applies to the DLS and EX metadata as they have
548 * constant tagnames throughout.
549 */
550 protected void addMetadataWithFixedTagName(Document doc,
551 Element metadataList, String metaDatastream, String metadataSet)
552 throws SAXException, IOException
553 {
554 // Namespace prefix can be "ex:" or "dls:"
555 String namespacePrefix = "";
556 if(!metadataSet.equals(EX)) {
557 // need to have a period for Greenstone instead of Fedora's colon
558 namespacePrefix = metadataSet.toLowerCase() + PERIOD;
559 }
560
561 Document src = builder.parse(
562 new InputSource(new StringReader(metaDatastream)));
563 NodeList metaTags = src.getElementsByTagName(
564 metadataSet.toLowerCase()+COLON+METADATA);
565 // Looking for tagnames: <ex:metadata> or <dls:metadata>
566
567 for(int i = 0; i < metaTags.getLength(); i++) {
568 Element metatag = (Element)metaTags.item(i);
569
570 // extract the metadata of (name, value) pairs from src DOM
571 // look for <metadata name="name">value</metadata>
572 String name = metatag.hasAttribute(NAME) ?
573 metatag.getAttribute(NAME) : "";
574 // sometimes, there are several metadata for the same name, in this
575 // case, look for a qualifier and append its value to the name to
576 // distinguish it uniquely:
577 if(metatag.hasAttribute(QUALIFIER)) {
578 name = name + HYPHEN + metatag.getAttribute(QUALIFIER);
579 }
580 String value = FedoraCommons.getValue(metatag);
581
582 // create metadata of (name, value) pairs in target DOM (doc)
583 Element metadata = doc.createElement(GSXML.METADATA_ELEM);
584 Attr attribute = doc.createAttribute(GSXML.NAME_ATT);
585 attribute.setValue(namespacePrefix + name);
586 // prefix with namespace, if any
587 metadata.setAttributeNode(attribute);
588 Text content = doc.createTextNode(value);
589 metadata.appendChild(content);
590
591 metadataList.appendChild(metadata);
592 }
593 }
594
595 /** Given a document identifier, returns a GS3 DocumentMetadataRetrieve
596 * response message containing ONLY the Title metadata for the document.
597 * @param docID is a document identifier (docID can either be a &lt;pid&gt;
598 * of an item (document) in the fedora repository, or it can be
599 * "&lt;pid&gt;-sectionNumber".
600 * @return a GS3 DocumentMetadataRetrieve response message containing the
601 * Title metadata for the requested document */
602 public String getTitleMetadata(String docID) {
603 return getTitleMetadata(new String[] { docID });
604 }
605
606 /** Given a document identifier, returns a GS3 DocumentMetadataRetrieve
607 * response message containing ONLY the Title metadata for the documents.
608 * @param docIDs is a list of document identifiers (where docID can either be
609 * a &lt;pid&gt; of an item (document) in the fedora repository, or it can be
610 * "&lt;pid&gt;-sectionNumber".
611 * @return a GS3 DocumentMetadataRetrieve response message containing the
612 * Title metadata for all the requested documents */
613 public String getTitleMetadata(String[] docIDs) {
614 // Must create message of the following form:
615 // <documentNodeList><documentNode nodeID="docID">
616 // <metadataList><metadata name="Title">sometitle</metadata>
617 // </metadataList></documentNode>
618
619 Document doc = builder.newDocument();
620 FedoraGS3RunException ex = null;
621
622 Element docNodeList = doc.createElement(
623 GSXML.DOC_NODE_ELEM+GSXML.LIST_MODIFIER);
624 try{
625 for(int i = 0; i < docIDs.length; i++) {
626 Element docNode = getTitleMetadata(doc, docIDs[i]);
627 docNodeList.appendChild(docNode);
628 }
629 }catch(Exception e) {
630 ex = new FedoraGS3RunException(e);
631 ex.setSpecifics("EX metadata datastream");
632 }
633
634 Element responseMsg = createResponseMessage(doc, docNodeList, ex,
635 GSXML.REQUEST_TYPE_PROCESS, "DocumentMetadataRetrieve");
636 try{
637 return FedoraCommons.elementToFormattedString(responseMsg);
638 } catch(TransformerException e) {
639 return FedoraGS3RunException.xmlToStringConversionFailureResponseMsg
640 + " " + e;
641 }
642 }
643
644 /** Method that takes a new DOM document, as well as an identifier of either
645 * a document or document section and returns a documentNode element containing
646 * the title metadata for it:
647 * &lt;documentNode nodeID="docID"&gt;&lt;metadataList&gt;
648 * &lt;metadata name="Title"&gt;sometitle&lt;/metadata&gt;
649 * &lt;/metadataList&gt;&lt;/documentNode&gt;
650 * @return documentNode containing the metadata for the collection or
651 * document given by parameter ID
652 * @param docID denotes the id of a document or a document section, so id
653 * is either a document-pid or it's of the form documentpid-sectionNumber */
654 protected Element getTitleMetadata(Document doc, String docID)
655 throws RemoteException, UnsupportedEncodingException,
656 SAXException, IOException
657 {
658 // Returns a docNode element of the following form:
659 // <documentNode nodeID="docID">
660 // <metadataList><metadata name="Title">sometitle</metadata></metadataList>
661 // </documentNode>
662
663 // <documentNode nodeID="docID">
664 Element docNode = doc.createElement(GSXML.DOC_NODE_ELEM);
665 Attr attribute = doc.createAttribute(GSXML.NODE_ID_ATT);
666 attribute.setValue(docID);
667 docNode.setAttributeNode(attribute);
668
669 // <metadataList>
670 Element metaList = doc.createElement(
671 GSXML.METADATA_ELEM+GSXML.LIST_MODIFIER);
672 // <metadata name="Title">
673 Element metadata = doc.createElement(GSXML.METADATA_ELEM);
674 // if we connect it all up (append children), we can immediately add
675 // the name attribute into the metadata element:
676 metaList.appendChild(metadata);
677 docNode.appendChild(metaList);
678 metadata.setAttribute(GSXML.NAME_ATT, TITLE); // immediately add attribute
679
680 String title = "";
681 String sectionID = getSectionIDFromDocID(docID);
682 String docPID = getDocPIDFromDocID(docID);
683
684 // check if title of toplevel document is requested
685 if(sectionID.equals(""))
686 title = this.getDocTitle(docPID);
687 else { // title of document section
688 title = this.getSectionTitle(docPID, sectionID);
689 }
690
691 metadata.appendChild(doc.createTextNode(title));
692
693 return docNode;
694 }
695
696
697 /** @return the documentStructure of the document or section given by docID.
698 * The structure is returned in the XML format of a Greenstone3
699 * DocumentStructureRetrieve response message. This method returns the entire
700 * subSection of the docID (that is, all descendants included).
701 * @param docID the identifier for the document whose structure is required.
702 * This is of the format "greenstone:&lt;collectionName&gt;-&lt;docPID&gt;"
703 * OR "greenstone:&lt;collectionName&gt;-&lt;docPID&gt;-&lt;sectioNumber&gt;"
704 * where "greenstone:&lt;collectionName&gt;-&lt;docPID&gt;-1" is the same as
705 * "greenstone:&lt;collectionName&gt;-&lt;docPID&gt;" and will return the
706 * same response */
707 public String getDocumentStructure(String docID) {
708 return getStructure(new String[]{docID}, DESCENDANTS);
709 }
710
711 /** @return a view of the structure of the document or section given by docID
712 * which contains only the section and its direct children. This structure is
713 * returned in the XML format of a Greenstone3 DocumentStructureRetrieve
714 * response message.
715 * @param docID the identifier for the document whose structure is required.
716 * This is of the format "greenstone:&lt;collectionName&gt;-&lt;docPID&gt;"
717 * OR "greenstone:&lt;collectionName&gt;-&lt;docPID&gt;-&lt;sectioNumber&gt;"
718 * where "greenstone:&lt;collectionName&gt;-&lt;docPID&gt;-1" is the same as
719 * "greenstone:&lt;collectionName&gt;-&lt;docPID&gt;" and will return the
720 * same response */
721 public String getChildren(String docID) {
722 return getStructure(new String[]{docID}, CHILDREN);
723 }
724
725 /** @return the documentStructure of the documents or sections given by docIDs.
726 * The structure is returned in the XML format of a Greenstone3
727 * DocumentStructureRetrieve response message. This method returns the entire
728 * subSection of each docID (that is, all descendants included).
729 * @param docIDs is an array of identifiers for the documents whose structures
730 * are required.
731 * This is of the format "greenstone:&lt;collectionName&gt;-&lt;docPID&gt;"
732 * OR "greenstone:&lt;collectionName&gt;-&lt;docPID&gt;-&lt;sectioNumber&gt;"
733 * where "greenstone:&lt;collectionName&gt;-&lt;docPID&gt;-1" is the same as
734 * "greenstone:&lt;collectionName&gt;-&lt;docPID&gt;" and will return the
735 * same response */
736 public String getDocumentStructure(String[] docIDs) {
737 return getStructure(docIDs, DESCENDANTS);
738 }
739
740 /** @return the documentStructure of the documents or sections given by docIDs
741 * but only the sections and their children (not any further descendants).
742 * The structure is returned in the XML format of a Greenstone3
743 * DocumentStructureRetrieve response message.
744 * @param docIDs the identifiers for the documents whose structures are
745 * required. The docids are of the format "greenstone:&lt;collectionName&gt;-&lt;docPID&gt;"
746 * OR "greenstone:&lt;collectionName&gt;-&lt;docPID&gt;-&lt;sectioNumber&gt;"
747 * where "greenstone:&lt;collectionName&gt;-&lt;docPID&gt;-1" is the same as
748 * "greenstone:&lt;collectionName&gt;-&lt;docPID&gt;" and will return the
749 * same response */
750 public String getChildren(String[] docIDs) {
751 return getStructure(docIDs, CHILDREN);
752 }
753
754 /**
755 * Returns a greenstone3 DocumentStructureRetrieve XML response message
756 * containing the document structures for the given docIDs.
757 * Similar to FedoraConnection.getTOC(), but instead of fedora formatted XML,
758 * greenstone formatted XML is returned. The requested section of the table
759 * of contents (TOC) for a document is converted into the greenstone3 xml
760 * format that is returned upon DocumentStructureRetrieve requests.
761 * @param docIDs the documentIDs for which the section's structure is returned;
762 * where a docID is either a fedora pid &lt;docPID&gt; or &lt;docPID&gt;-&lt;sectionNumber&gt;.
763 * @param levels - either CHILDREN or DESCENDANTS.
764 * CHILDREN returns only the first-level descendants (children) of the
765 * requested document sections indicated by docIDs.
766 * DESCENDANTS returns all descendants of all the document-sections denoted by
767 * docIDs.
768 * @return a greenstone3 DocumentStructureRetrieve XML response message in
769 * String format with the structure of the docIDs requested.
770 */
771 protected String getStructure(String[] docIDs, int levels)
772 {
773 Document doc = builder.newDocument();
774 FedoraGS3RunException ex = null;
775 // <documentNodeList>
776 Element docNodeList = doc.createElement(
777 GSXML.DOC_NODE_ELEM+GSXML.LIST_MODIFIER);
778
779 try{
780 // append the <documentNodes> for the docIDs
781 // to the docNodeList
782 getStructureElement(docNodeList, docIDs, levels);
783 } catch(Exception e) {
784 ex = new FedoraGS3RunException(e);
785 ex.setSpecifics("(requested portion of) TOC datastream");
786 }
787 // insert our <documentNodeList> into a GS3 response message
788 Element responseMsg = createResponseMessage(doc, docNodeList, ex,
789 GSXML.REQUEST_TYPE_PROCESS, "DocumentStructureRetrieve");
790 try{
791 return FedoraCommons.elementToFormattedString(responseMsg);
792 } catch(TransformerException e) {
793 return FedoraGS3RunException.xmlToStringConversionFailureResponseMsg
794 + " " + e;
795 }
796 }
797
798 /** Given a &lt;documentNodeList&gt; portion of a greenstone3
799 * DocumentStructureRetrieve XML response message, this method will populate
800 * it with the &lt;documentNodes&gt; that represent the structure of the given docIDs.
801 * @param docNodeList is a &lt;documentNodeList&gt; to which &lt;documentNodes&gt; of
802 * the doc structures are appended.
803 * @param docIDs the documentIDs for which the section's structure is returned;
804 * where a docID is either a fedora pid &lt;docPID&gt; or &lt;docPID&gt;-&lt;sectionNumber&gt;.
805 * @param levels - either CHILDREN or DESCENDANTS.
806 * CHILDREN returns only the first-level descendants (children) of the
807 * requested document sections indicated by docIDs.
808 * DESCENDANTS returns all descendants of all the document-sections denoted by
809 * docIDs.
810 */
811 protected void getStructureElement(Element docNodeList,
812 String[] docIDs, int levels)
813 throws RemoteException, UnsupportedEncodingException, SAXException,
814 IOException
815 {
816 // process each docID
817 for(int i = 0; i < docIDs.length; i++) {
818 // work out the document's fedora PID and section ID
819 String sectionID = getSectionIDFromDocID(docIDs[i]);
820 String docPID = getDocPIDFromDocID(docIDs[i]);
821
822 // get the required section, along with children or descendants
823 Element srcDocElement = null;
824 if(levels == CHILDREN) // get the requested section with its children
825 srcDocElement = this.getChildrenOfSectionXML(docPID, sectionID);
826 else // levels == DESCENDANTS, get the section with all its descendants
827 srcDocElement = this.getSubsectionXML(docPID, sectionID);
828
829 // copy-and-convert that structure into a structure format for GS3
830 Element docNode = getStructure(docNodeList.getOwnerDocument(),
831 docIDs[i], docPID, srcDocElement);
832
833 // add it to our list of documentNodes
834 docNodeList.appendChild(docNode);
835 }
836 }
837
838 /**
839 * Takes the portion of the XML document outlining the structure of the
840 * document (section)--in the format this is stored in Fedora--and returns
841 * Greenstone 3 DOM XML format for outlining document structure.
842 * @return a &lt;documentNode&gt; element that contains a greenstone3
843 * DocumentStructureRetrieve XML corresponding to the parameter Element section
844 * (which is in fedora XML), for the document indicated by docID.
845 * @param requestingDocID is the identifier of the document for which the
846 * structure was requested. It's this document's children or descendants that
847 * will be returned. Note that this is not always the same as (clear from)
848 * parameter docID.
849 * @param docID is the documentID for which the section's structure is
850 * returned where docID = "docPID-sectionNumber".
851 * @param section - the fedora section XML that is being mirrored in
852 * greenstone3 format.
853 */
854 protected Element getStructure(Document doc, String requestingDocID,
855 String docID, Element section)
856 {
857 // we want to mirror the section's DOM (given in fedora XML) in
858 // greenstone3's XML for a DocumentStructureRetrieve response.
859
860 // <documentNode nodeID="docID"> - the docNode on which a structure retrieve
861 // is being performed
862 Element docNode = doc.createElement(GSXML.DOC_NODE_ELEM);
863 Attr attribute = doc.createAttribute(GSXML.NODE_ID_ATT);
864 attribute.setValue(requestingDocID); //requestingDocID.replace(HYPHEN+SECTION, "")
865 docNode.setAttributeNode(attribute);
866
867 // <nodeStructure>
868 Element nodeStructure = doc.createElement(GSXML.NODE_STRUCTURE_ELEM);
869
870 // <documentNode nodeID="docID" docType="hierarchy" nodeType="root">
871 Element rootNode = createDocNodeFromSubsection(doc, section, docID);
872
873 // fills in the subtree of the rootNode in our nodeStructure element
874 createDocStructure(doc, section, rootNode, docID);
875 //where section represents the root section
876
877 nodeStructure.appendChild(rootNode);
878 docNode.appendChild(nodeStructure);
879 return docNode;
880 }
881
882 /** Recursive method that creates a documentStructure mirroring parameter
883 * section, starting from parameter parent down to all descendants
884 * @param section is the XML &lt;Section&gt; in the fedora repository's TOC
885 * for the docPID whose substructure is to be mirrored
886 * @param parent is the XML documentNode in the greenstone repository whose
887 * descendants created by this method will correspond to the descendants of
888 * parameter section.
889 * @param doc is the document containing the parent;
890 * @param docPID is the prefix of all nodeIDs in the parent's structure
891 */
892 protected void createDocStructure(
893 Document doc, Element section, Element parent, String docPID)
894 {
895 // get the section's children (if any)
896 NodeList children = section.getChildNodes();
897 for(int i = 0; i < children.getLength(); i++) {
898 Node n = children.item(i);
899
900 if(n.getNodeName().equals(SECTION_ELEMENT)) {
901 //then we know it's an element AND that its tagname is "Section"
902 Element subsection = (Element)n;
903 Element child = createDocNodeFromSubsection(doc, subsection, docPID);
904 parent.appendChild(child);
905
906 // recursion call on newly found child-element and subsection
907 createDocStructure(doc, subsection, child, docPID);
908 }
909 }
910 }
911
912 /** Given a particular subsection element, this method creates a
913 * Greenstone3 DocumentNode element that mirrors it.
914 * @param doc is the document that will contain the created DocumentNode
915 * @param docID is the prefix of all nodeIDs in the parent's structure
916 * @param subSection is the XML &lt;Section&gt; in the fedora repository's
917 * TOC for the docPID which will be mirrored in the greenstone XML
918 * documentNode that will be returned.
919 * @return a greenstone &lt;documentNode&gt; that represents the fedora TOC's
920 * &lt;Section&gt; element passed as parameter subSection. */
921 protected Element createDocNodeFromSubsection(
922 Document doc, Element subSection, String docID)
923 {
924 Element docNode = doc.createElement(GSXML.DOC_NODE_ELEM);
925 Attr docType = doc.createAttribute(GSXML.DOC_TYPE_ATT);
926 docType.setValue(GSXML.DOC_TYPE_HIERARCHY);
927 docNode.setAttributeNode(docType);
928
929 Attr nodeID = doc.createAttribute(GSXML.NODE_ID_ATT);
930 String sectionID = subSection.hasAttribute(ID) ?
931 subSection.getAttribute(ID) : "";
932 nodeID.setValue(docID + HYPHEN + sectionID);
933 docNode.setAttributeNode(nodeID);
934
935 Attr nodeType = doc.createAttribute(GSXML.NODE_TYPE_ATT);
936 if(sectionID.equals("1")) { // root case
937 nodeType.setValue(GSXML.NODE_TYPE_ROOT);
938 // reset the attribute without the section number
939 docNode.setAttribute(GSXML.NODE_ID_ATT, docID);
940 }
941 else if(subSection.getElementsByTagName(SECTION_ELEMENT).getLength() > 0)
942 // this section has further <Section> children, so it's an internal node
943 nodeType.setValue(GSXML.NODE_TYPE_INTERNAL);
944 else if(subSection.hasAttribute(TYPE))
945 nodeType.setValue(GSXML.NODE_TYPE_INTERNAL);
946 else // leaf
947 nodeType.setValue(GSXML.NODE_TYPE_LEAF);
948 docNode.setAttributeNode(nodeType);
949 return docNode;
950 }
951
952
953 /** Given an identifier that is either a docPID or a concatenation of
954 * docPID+sectionID, this method works out the fedora assigned docPID and
955 * sectionID and then calls getContentBody(docPID, sectionID) with those.
956 * @param docID is expected to be of the form
957 * "greenstone:&lt;collectionName&gt;-&lt;docPID&gt;-&lt;sectionNumber&gt;" or
958 * "greenstone:&lt;collectionName&gt;-&lt;docPID&gt;"
959 * If it is "greenstone:&lt;collectionName&gt;-&lt;docPID&gt;", then the content for
960 * "greenstone:&lt;collectionName&gt;-1" ("greenstone:&lt;collectionName&gt;-Section1")
961 * is returned! */
962 public String getContent(String docID) {
963 return this.getContent(new String[]{docID});
964 }
965
966 /** Given an identifier that is a concatenation of docID+sectionID, this
967 * method works out the fedora assigned docPID and sectionID and then calls
968 * getContentBody(docPID, sectionID) with those.
969 * @param docIDs is an array of document identifiers of the form
970 * "greenstone:&lt;collectionName&gt;-&lt;docPID&gt;-&lt;sectionNumber&gt;"
971 * If it is "greenstone:&lt;collectionName&gt;-&lt;docPID&gt;", then the content for
972 * "greenstone:&lt;collectionName&gt;-Section1" is returned! */
973 public String getContent(String[] docIDs) {
974 Document doc = builder.newDocument();
975 FedoraGS3RunException ex = null;
976
977 //<documentNodeList>
978 Element docNodeList = doc.createElement(
979 GSXML.DOC_NODE_ELEM+GSXML.LIST_MODIFIER);
980
981 try{
982 for(int i = 0; i < docIDs.length; i++) {
983 // get the sectionID and docPID from the docID
984 String sectionID = this.removePrefix(
985 getSectionIDFromDocID(docIDs[i]), SECTION);
986 String docPID = getDocPIDFromDocID(docIDs[i]);
987 if(sectionID.equals("")) // if no section is specified, get
988 sectionID = "1"; // get the content for Section id="1"
989
990 // Get the contents for the requested section of document docPID
991 String sectionContent = this.getContentBody(docPID, sectionID);
992
993 // set the nodeID attribute
994 Element docNode = doc.createElement(GSXML.DOC_NODE_ELEM);
995 Attr nodeId = doc.createAttribute(GSXML.NODE_ID_ATT);
996
997 nodeId.setValue(docIDs[i]); // just set the docID which will contain
998 // the docPID (and sectionID if already present)
999
1000 docNode.setAttributeNode(nodeId);
1001 // set the text content to what was retrieved
1002 Element nodeContent = doc.createElement(GSXML.NODE_CONTENT_ELEM);
1003 Text textNode = doc.createTextNode(sectionContent);
1004
1005 nodeContent.appendChild(textNode);
1006 docNode.appendChild(nodeContent);
1007 //add the documentNode to the docNodeList
1008 docNodeList.appendChild(docNode);
1009 }
1010 } catch(Exception e) {
1011 ex = new FedoraGS3RunException(e);
1012 ex.setSpecifics("requested doc Section datastream");
1013 }
1014 Element responseMsg = createResponseMessage(doc, docNodeList, ex,
1015 GSXML.REQUEST_TYPE_PROCESS, "DocumentContentRetrieve");
1016 try{
1017 return FedoraCommons.elementToFormattedString(responseMsg);
1018 } catch(TransformerException e) {
1019 return FedoraGS3RunException.xmlToStringConversionFailureResponseMsg
1020 + " " + e;
1021 }
1022 }
1023
1024 /** Gets the contents of a textNode from a section.
1025 * @return the text content of a section.
1026 * @param docPID the pid of the document from which a section's text is to
1027 * be retrieved.
1028 * @param sectionID is the section identifier of the document denoted by
1029 * docPID whose text is to be returned.
1030 */
1031 protected String getContentBody(String docPID, String sectionID)
1032 throws RemoteException, UnsupportedEncodingException,
1033 SAXException, IOException
1034 {
1035 String section = this.getSection(docPID, sectionID);
1036
1037 // the content is nested inside a <Section> element,
1038 // we extract it from there:
1039 InputSource source = new InputSource(new StringReader(section));
1040 Document doc = builder.parse(source);
1041
1042 // The document Element is the <Section> we want.
1043 // Get its text contents:
1044 section = FedoraCommons.getValue(doc.getDocumentElement());
1045
1046 // we are going to remove all occurrences of "_httpdocimg_/"
1047 // that precede associated filenames, because that's a GS3
1048 // defined macro for resolving relative urls. It won't help
1049 // with documents stored in fedora.
1050 section = section.replaceAll(GS3FilePathMacro+"/", "");
1051 return section;
1052 }
1053
1054 /** Here we create the greenstone's response message element:
1055 * &lt;message&lg;&lt;response&gt;&lt;content&gt;&lt;/response&gt;&lt;/message&gt;
1056 * @return a greenstone response-message element.
1057 * @param doc - the Document object which should me used to create the
1058 * &lt;message&gt; and &lt;response&gt; elements
1059 * @param content - the element that is to be nested inside &lt;response&gt;
1060 * @param ex - any exception that occurred when trying to create
1061 * the content parameter
1062 * @param responseType - the value for the type attribute of &lt;response&gt;,
1063 * such as "describe", "retrieve", "browse", "query"...
1064 * @param originator - indiates the collectionName or service (like
1065 * DocumentContentRetrieve) from where this response message originates
1066 */
1067 protected Element createResponseMessage(Document doc, Element content,
1068 Exception ex, String responseType, String originator)
1069 {
1070 Element response = doc.createElement(GSXML.RESPONSE_ELEM);
1071 // from = "FedoraGS3"
1072 Attr attribute = doc.createAttribute(GSXML.FROM_ATT);
1073 String from = originator.equals("") ? FEDORA_GS3
1074 : FEDORA_GS3+"/"+originator;
1075
1076 attribute.setValue(from);
1077 response.setAttributeNode(attribute);
1078
1079 // type = "describe" or "process" - whatever's given in requestType:
1080 attribute = doc.createAttribute(GSXML.TYPE_ATT);
1081 attribute.setValue(responseType);
1082 response.setAttributeNode(attribute);
1083
1084 if(content != null)
1085 response.appendChild(content);
1086
1087 // we'll create an error element for RemoteExceptions (web service problems)
1088 // and UnsupportedEncodingExceptions and
1089 if(ex != null) {
1090 Element error = doc.createElement(GSXML.ERROR_ELEM);
1091 error.appendChild(doc.createTextNode(ex.getMessage()));
1092 // now append the error to the <response> element (after
1093 // the content element whatever that was)
1094 response.appendChild(error);
1095 }
1096
1097 Element message = doc.createElement(GSXML.MESSAGE_ELEM);
1098 message.appendChild(response);
1099 doc.appendChild(message);
1100 return message;
1101 }
1102
1103 /** @return a &lt;serviceList&gt; Element as defined by GS3: containing all the
1104 * services (denoted by &lt;service&gt; elements) that are supported by FedoraGS3.
1105 * At present these are: DocumentContentRetrieve, DocumentMetadataRetrieve,
1106 * DocumentStructureRetrieve, TextQuery, FieldQuery, ClassifierBrowse,
1107 * ClassifierBrowseMetadataRetrieve (as indicated by member var serviceNames).
1108 * @param doc - the Document object which should me used to create the
1109 * &lt;serviceList&gt; element */
1110 protected Element createServiceList(Document doc)
1111 {
1112 Element serviceList = doc.createElement(
1113 GSXML.SERVICE_ELEM+GSXML.LIST_MODIFIER);
1114
1115 for(int i = 0; i < serviceNames.length; i++) {
1116 // create the <service name="serviceName[i]" type="servicetype" />
1117 Element service = doc.createElement(GSXML.SERVICE_ELEM);
1118
1119 Attr attribute = doc.createAttribute(GSXML.NAME_ATT);
1120 attribute.setValue(serviceNames[i]);
1121 service.setAttributeNode(attribute);
1122
1123 attribute = doc.createAttribute(GSXML.TYPE_ATT);
1124 if(serviceNames[i].equals("ClassifierBrowse")) //browseTitlesByLetter
1125 attribute.setValue(GSXML.SERVICE_TYPE_BROWSE);
1126 else if(serviceNames[i].contains("Query")) // search services
1127 attribute.setValue(GSXML.SERVICE_TYPE_QUERY);
1128 else
1129 attribute.setValue(GSXML.SERVICE_TYPE_RETRIEVE);
1130 service.setAttributeNode(attribute);
1131
1132 // add the service element to the serviceList element
1133 // <serviceList><service /></serviceList>
1134 serviceList.appendChild(service);
1135 }
1136 return serviceList;
1137 }
1138
1139 /** @return a GS3 response message for a describe services request:
1140 * indicating the list of services supported by the Fedora-Greenstone
1141 * interface. These are DocumentContentRetrieve, DocumentMetadataRetrieve,
1142 * DocumentStructureRetrieve, ClassifierBrowse, TextQuery, FieldQuery,
1143 * ClassifierBrowseMetadataRetrieve - as indicated by member variable
1144 * serviceNames. */
1145 public String getServiceList()
1146 {
1147 Document doc = builder.newDocument();
1148 Element serviceList = createServiceList(doc);
1149 // make <serviceList> the body of the responseMessage:
1150 // <message><response><serviceList></response></message>
1151 Element responseMsg = createResponseMessage(doc, serviceList, null,
1152 GSXML.REQUEST_TYPE_DESCRIBE, "");
1153 try {
1154 return FedoraCommons.elementToFormattedString(responseMsg);
1155 }catch(TransformerException e) {
1156 return FedoraGS3RunException.xmlToStringConversionFailureResponseMsg
1157 + " " + e;
1158 }
1159 }
1160
1161 /** @return a GS3 describe response message listing the collections and
1162 * collection-specific metadata stored in the Fedora-Greenstone repository. */
1163 public String getCollectionList()
1164 {
1165 Document doc = builder.newDocument();
1166 FedoraGS3RunException ex = null; // any RemoteException
1167
1168 // create the <collectionList /> element
1169 Element collectionList = doc.createElement(
1170 GSXML.COLLECTION_ELEM+GSXML.LIST_MODIFIER);
1171 try{
1172 String[] collectionNames = this.getCollectionNames(
1173 this.getCollections()); // this line could throw RemoteException
1174 for(int i = 0; i < collectionNames.length; i++) {
1175 // create the <collection name="somename" /> element
1176 Element collection = doc.createElement(GSXML.COLLECTION_ELEM);
1177 Attr attribute = doc.createAttribute(GSXML.NAME_ATT);
1178 attribute.setValue(collectionNames[i]);
1179 collection.setAttributeNode(attribute);
1180
1181 // append the <collection> element as child of <collectionList>
1182 collectionList.appendChild(collection);
1183
1184 //if(collection.hasAttribute(GSXML.NAME_ATT))
1185 //LOG.debug(collection.getAttribute(GSXML.NAME_ATT));
1186 }
1187 } catch(RemoteException e) { // if this happens, perhaps it's because it
1188 // can't find Greenstone collections in fedora repository?
1189 ex = new FedoraGS3RunException(e);
1190 ex.setSpecifics(
1191 "greenstone collections in fedora repository");
1192 }
1193
1194 // make <collectionList> the body of the responseMessage:
1195 // <message><response><collectionList></response></message>
1196 Element responseMsg = createResponseMessage(doc, collectionList, ex,
1197 GSXML.REQUEST_TYPE_DESCRIBE, "");
1198 try{
1199 return FedoraCommons.elementToFormattedString(responseMsg);
1200 }catch(TransformerException e) {
1201 return FedoraGS3RunException.xmlToStringConversionFailureResponseMsg
1202 + " " + e;
1203 }
1204 }
1205
1206 /** @return a GS3 describe response message for a collection in the
1207 * Fedora-Greenstone repository.
1208 * @param collectionName - the name of the collection that is to be described.
1209 * It will be converted to a fedora collection pid, which is of the form
1210 * "greenstone:&lt;collectionName&gt;-collection". */
1211 public String describeCollection(String collectionName)
1212 {
1213 Document doc = builder.newDocument();
1214 FedoraGS3RunException ex = null;
1215
1216 Element collection = doc.createElement(GSXML.COLLECTION_ELEM);
1217 Attr attribute = doc.createAttribute(GSXML.NAME_ATT);
1218 attribute.setValue(collectionName);
1219 collection.setAttributeNode(attribute);
1220
1221 //<displayItem assigned="true" lang="en" name="name">
1222 //"some display name"</displayItem>
1223 Element displayItem = doc.createElement(GSXML.DISPLAY_TEXT_ELEM);
1224
1225 attribute = doc.createAttribute(GSXML.LANG_ATT);
1226 attribute.setValue(this.lang);
1227 displayItem.setAttributeNode(attribute);
1228
1229 attribute = doc.createAttribute(GSXML.NAME_ATT);
1230 attribute.setValue(GSXML.DISPLAY_TEXT_NAME);
1231 displayItem.setAttributeNode(attribute);
1232
1233 try{
1234 Text textNode = doc.createTextNode(
1235 this.getCollectionTitle(getCollectionPID(collectionName)));
1236 displayItem.appendChild(textNode);
1237 } catch(Exception e) {
1238 // can't find Greenstone collections in fedora repository or problem
1239 // getting their titles from their metadata datastream?
1240 ex = new FedoraGS3RunException(e);
1241 ex.setSpecifics("greenstone collections or their metadata"
1242 + "in the fedora repository");
1243 }
1244 // now append the displayItem element as child of the collection element
1245 collection.appendChild(displayItem);
1246 // get the <serviceList> and add it into the collection description.
1247 // Services for all collections in the FedoraGS3 repository are the
1248 // same, offering a ClassifierBrowse to browse titles by starting letter
1249 // and DocRetrieve services: Content, Metadata and Structure.
1250
1251 Element serviceList = createServiceList(doc);
1252 collection.appendChild(serviceList);
1253
1254 Element responseMsg = createResponseMessage(doc, collection, ex,
1255 GSXML.REQUEST_TYPE_DESCRIBE, collectionName);
1256 try{
1257 return FedoraCommons.elementToFormattedString(responseMsg);
1258 }catch(TransformerException e) {
1259 return FedoraGS3RunException.xmlToStringConversionFailureResponseMsg
1260 + " " + e;
1261 }
1262 }
1263
1264 /** @return a GS3 describe response message for the services of a collection
1265 * in the Fedora-Greenstone repository. So far, these services are the same for
1266 * all fedora collections: they are the services given in member variable
1267 * serviceNames: DocumentContent/Metadata/StructureRetrieve, ClassifierBrowse,
1268 * ClassifierBrowseMetadataRetrieve.
1269 * @param collectionName - the name of the collection whose services are to
1270 * be described. It will be converted to a fedora collection pid, which is of
1271 * the form "greenstone:&lt;collectionName&gt;-collection". */
1272 public String describeCollectionServices(String collectionName)
1273 {
1274 Document doc = builder.newDocument();
1275
1276 Element collection = doc.createElement(GSXML.COLLECTION_ELEM);
1277 Attr attribute = doc.createAttribute(GSXML.NAME_ATT);
1278 attribute.setValue(collectionName);
1279 collection.setAttributeNode(attribute);
1280
1281 Element serviceList = createServiceList(doc);
1282 collection.appendChild(serviceList);
1283
1284 Element responseMsg = createResponseMessage(doc, collection, null,
1285 GSXML.REQUEST_TYPE_DESCRIBE, collectionName);
1286 try{
1287 return FedoraCommons.elementToFormattedString(responseMsg);
1288 }catch(TransformerException e) {
1289 return FedoraGS3RunException.xmlToStringConversionFailureResponseMsg
1290 + " " + e;
1291 }
1292 }
1293
1294 /** All collections in this Digital Library (Fedora Repository) share
1295 * the same services, so this method returns the same as
1296 * describeCollectionService(collName, serviceName).
1297 * @return a GS3 describe response message for the requested service
1298 * of the given collection. DocumentContent/Metadata/StructureRetrieve
1299 * return nothing special except their names; browse (and any query)
1300 * return more complex XML responses.
1301 * All collections in this Digital Library (Fedora Repository) share
1302 * the same services, so this method returns the same as
1303 * describeService(serviceName).
1304 * @param serviceName - the name of the service in the collection which is to
1305 * be described.*/
1306 public String describeService(String serviceName)
1307 {
1308 // For all the *retrieve* services (incl ClassifierBrowseMetadataRetrieve)
1309 // we return:
1310 // <message><response from="<name>Retrieve" type="describe">
1311 // <service name="<name>Retrieve" type="retrieve" /></response></message>
1312 // But for browse (and any query) service, we return the data necessary
1313 // for displaying it
1314
1315 Document doc = this.builder.newDocument();
1316 Element service = doc.createElement(GSXML.SERVICE_ELEM);
1317 Attr attribute = doc.createAttribute(GSXML.NAME_ATT);
1318 attribute.setValue(serviceName);
1319 service.setAttributeNode(attribute);
1320
1321 attribute = doc.createAttribute(GSXML.TYPE_ATT);
1322
1323 if(serviceName.toLowerCase().endsWith("retrieve"))
1324 attribute.setValue(GSXML.SERVICE_TYPE_RETRIEVE);
1325
1326 else if(serviceName.toLowerCase().contains("browse")) {
1327 attribute.setValue(GSXML.SERVICE_TYPE_BROWSE);
1328
1329 // we need name and description <displayItem> elements
1330 Element displayItem
1331 = createNameValuePairElement(doc,
1332 GSXML.DISPLAY_TEXT_ELEM, GSXML.DISPLAY_TEXT_NAME, "Browse");
1333 service.appendChild(displayItem);
1334
1335 displayItem = createNameValuePairElement(doc,
1336 GSXML.DISPLAY_TEXT_ELEM, GSXML.DISPLAY_TEXT_DESCRIPTION,
1337 "Browse pre-defined classification hierarchies");
1338 service.appendChild(displayItem);
1339
1340 // now need a classifierList
1341 Element classifierList = doc.createElement(
1342 GSXML.CLASSIFIER_ELEM+GSXML.LIST_MODIFIER);
1343
1344 int classifierNum = 1;
1345 // append a <classifier content="some letter" name="CL#">
1346 // for each letter of the alphabet:
1347 Element classifier = createClassifierElement(doc, "TitleByLetter",
1348 classifierNum++, "titles (by letter)", "Browse titles by letter");
1349 // now add this <classifier> to the <classifierList>
1350 classifierList.appendChild(classifier);
1351
1352 // ANY MORE CLASSIFIERS? ADD THEM HERE
1353
1354 service.appendChild(classifierList);
1355 } // ELSE check for whether it is a query service
1356 else if(serviceName.toLowerCase().contains("query")) {
1357 attribute.setValue(GSXML.SERVICE_TYPE_QUERY);
1358 if(serviceName.equals("TextQuery"))
1359 describeTextQueryService(service);
1360 else if(serviceName.equals("FieldQuery"))
1361 describeFieldQueryService(service);
1362 }
1363
1364 // don't forget to add the type attribute to the service!
1365 service.setAttributeNode(attribute);
1366
1367 String from = serviceName;
1368
1369 Element responseMsg = createResponseMessage(doc, service, null,
1370 GSXML.REQUEST_TYPE_DESCRIBE, from);
1371 try{
1372 return FedoraCommons.elementToFormattedString(responseMsg);
1373 }catch(TransformerException e) {
1374 return FedoraGS3RunException.xmlToStringConversionFailureResponseMsg
1375 + " " + e;
1376 }
1377 }
1378
1379 /** Appends children to the parameter service Element that make the
1380 * final service Element into a describe response XML for FedoraGS3's
1381 * TextQuery service.
1382 * @param service is the service Element that is being filled out. */
1383 protected void describeTextQueryService(Element service) {
1384 Document doc = service.getOwnerDocument();
1385 // we need name, submit (button) and description <displayItem> elements
1386 Element displayItem = createNameValuePairElement(doc,
1387 GSXML.DISPLAY_TEXT_ELEM, GSXML.DISPLAY_TEXT_NAME,
1388 "Text Search");
1389 service.appendChild(displayItem);
1390
1391 displayItem = createNameValuePairElement(doc,
1392 GSXML.DISPLAY_TEXT_ELEM, GSXML.DISPLAY_TEXT_SUBMIT, "Search");
1393 service.appendChild(displayItem);
1394
1395 displayItem = createNameValuePairElement(doc,
1396 GSXML.DISPLAY_TEXT_ELEM, GSXML.DISPLAY_TEXT_DESCRIPTION,
1397 "Title and full-text search service");
1398 service.appendChild(displayItem);
1399
1400 //create the <paramList>
1401 Element paramList = doc.createElement(
1402 GSXML.PARAM_ELEM+GSXML.LIST_MODIFIER);
1403
1404 // we ignore granularity to search at: it will always be
1405 // document and section level
1406 // we ignore casefolding: always on (that is, case is irrelevant)
1407 // we ignore document display order: always ranked
1408
1409 // Constructing the following:
1410 // <param default="100" name="maxDocs" type="integer">
1411 // <displayItem name="name">Maximum hits to return</displayItem>
1412 // </param>
1413 Element param = doc.createElement(GSXML.PARAM_ELEM);
1414
1415 Attr attribute = doc.createAttribute(GSXML.NAME_ATT);
1416 attribute.setValue(MAXDOCS);
1417 param.setAttributeNode(attribute);
1418
1419 attribute = doc.createAttribute(GSXML.DEFAULT_ATT);
1420 attribute.setValue("100");
1421 param.setAttributeNode(attribute);
1422
1423 attribute = doc.createAttribute(GSXML.TYPE_ATT);
1424 attribute.setValue(GSXML.PARAM_TYPE_INTEGER);
1425 param.setAttributeNode(attribute);
1426
1427 displayItem = createNameValuePairElement(doc,
1428 GSXML.DISPLAY_TEXT_ELEM, GSXML.DISPLAY_TEXT_NAME,
1429 "Maximum hits to return");
1430 param.appendChild(displayItem);
1431
1432 paramList.appendChild(param);
1433
1434 // Constructing the following:
1435 // <param name="query" type="string">
1436 // <displayItem name="name">Query string</displayItem>
1437 // </param>
1438 param = doc.createElement(GSXML.PARAM_ELEM);
1439
1440 attribute = doc.createAttribute(GSXML.NAME_ATT);
1441 attribute.setValue(QUERY);
1442 param.setAttributeNode(attribute);
1443
1444 attribute = doc.createAttribute(GSXML.TYPE_ATT);
1445 attribute.setValue(GSXML.PARAM_TYPE_STRING);
1446 param.setAttributeNode(attribute);
1447
1448 displayItem = createNameValuePairElement(doc,
1449 GSXML.DISPLAY_TEXT_ELEM, GSXML.DISPLAY_TEXT_NAME,
1450 "Query string");
1451 param.appendChild(displayItem);
1452
1453 paramList.appendChild(param);
1454
1455 service.appendChild(paramList);
1456 }
1457
1458 /** Appends children to the parameter service Element that make the
1459 * final service Element into a describe response XML for FedoraGS3's
1460 * FieldQuery service.
1461 * @param service is the service Element that is being filled out. */
1462 protected void describeFieldQueryService(Element service) {
1463 Document doc = service.getOwnerDocument();
1464 // we need name, submit (button) and description <displayItem> elements
1465 Element displayItem = createNameValuePairElement(doc,
1466 GSXML.DISPLAY_TEXT_ELEM, GSXML.DISPLAY_TEXT_NAME,
1467 "Form Search");
1468 service.appendChild(displayItem);
1469
1470 displayItem = createNameValuePairElement(doc,
1471 GSXML.DISPLAY_TEXT_ELEM, GSXML.DISPLAY_TEXT_SUBMIT, "Search");
1472 service.appendChild(displayItem);
1473
1474 displayItem = createNameValuePairElement(doc,
1475 GSXML.DISPLAY_TEXT_ELEM, GSXML.DISPLAY_TEXT_DESCRIPTION,
1476 "Simple fielded search");
1477 service.appendChild(displayItem);
1478
1479 //create the <paramList>
1480 Element paramList = doc.createElement(
1481 GSXML.PARAM_ELEM+GSXML.LIST_MODIFIER);
1482
1483 // we ignore granularity to search at: it will always be
1484 // document and section level
1485 // we ignore casefolding: always on (that is, case is irrelevant)
1486 // we ignore document display order: always ranked
1487
1488 // Constructing the following:
1489 // <param default="100" name="maxDocs" type="integer">
1490 // <displayItem name="name">Maximum hits to return</displayItem>
1491 // </param>
1492 Element param = doc.createElement(GSXML.PARAM_ELEM);
1493
1494 Attr attribute = doc.createAttribute(GSXML.NAME_ATT);
1495 attribute.setValue(MAXDOCS);
1496 param.setAttributeNode(attribute);
1497
1498 attribute = doc.createAttribute(GSXML.DEFAULT_ATT);
1499 attribute.setValue("100");
1500 param.setAttributeNode(attribute);
1501
1502 attribute = doc.createAttribute(GSXML.TYPE_ATT);
1503 attribute.setValue(GSXML.PARAM_TYPE_INTEGER);
1504 param.setAttributeNode(attribute);
1505
1506 displayItem = createNameValuePairElement(doc,
1507 GSXML.DISPLAY_TEXT_ELEM, GSXML.DISPLAY_TEXT_NAME,
1508 "Maximum hits to return");
1509 param.appendChild(displayItem);
1510
1511 paramList.appendChild(param);
1512
1513 // Constructing the following:
1514 // <param name="simpleField" occurs="4" type="multi">
1515 // <displayItem name="name"></displayItem>
1516 //
1517 // <param name="query" type="string">
1518 // <displayItem name="name">Word or phrase </displayItem>
1519 // </param>
1520 //
1521 // <param default="allFields" name="fieldname" type="enum_single">
1522 // <displayItem name="name">in field</displayItem>
1523 //
1524 // <option name="docTitles">
1525 // <displayItem name="name">document titles</displayItem>
1526 // </option>
1527 // <option name="allTitles">
1528 // <displayItem name="name">document and section titles</displayItem>
1529 // </option>
1530 // <option name="fullText">
1531 // <displayItem name="name">full text</displayItem>
1532 // </option>
1533 // <option name="all">
1534 // <displayItem name="name">titles and full text</displayItem>
1535 // </option>
1536 // <option name="">
1537 // <displayItem name="name"></displayItem>
1538 // </option>
1539 // </param>
1540 // </param>
1541 Element rowOfParams = doc.createElement(GSXML.PARAM_ELEM);
1542 attribute = doc.createAttribute(GSXML.NAME_ATT);
1543 attribute.setValue(SIMPLEFIELD_ATT);
1544 rowOfParams.setAttributeNode(attribute);
1545
1546 // we want the row of controls to occur multiple times
1547 attribute = doc.createAttribute(GSXML.TYPE_ATT);
1548 attribute.setValue(GSXML.PARAM_TYPE_MULTI);
1549 rowOfParams.setAttributeNode(attribute);
1550
1551 attribute = doc.createAttribute(OCCURS_ATT);
1552 attribute.setValue("4"); // we want this row to occur 4 times
1553 rowOfParams.setAttributeNode(attribute);
1554
1555 // <param name="query" type="string">
1556 // <displayItem name="name">Word or phrase </displayItem>
1557 // </param>
1558 param = doc.createElement(GSXML.PARAM_ELEM);
1559
1560 attribute = doc.createAttribute(GSXML.NAME_ATT);
1561 attribute.setValue(QUERY);
1562 param.setAttributeNode(attribute);
1563
1564 attribute = doc.createAttribute(GSXML.TYPE_ATT);
1565 attribute.setValue(GSXML.PARAM_TYPE_STRING);
1566 param.setAttributeNode(attribute);
1567
1568 displayItem = createNameValuePairElement(doc,
1569 GSXML.DISPLAY_TEXT_ELEM, GSXML.DISPLAY_TEXT_NAME,
1570 "Word or phrase");
1571 param.appendChild(displayItem);
1572 rowOfParams.appendChild(param);
1573
1574 // <param default="allFields" name="fieldName" type="enum_single">
1575 // <displayItem name="name">in field</displayItem>
1576 param = doc.createElement(GSXML.PARAM_ELEM);
1577 attribute = doc.createAttribute(GSXML.NAME_ATT);
1578 attribute.setValue(FIELDNAME_ATT);
1579 param.setAttributeNode(attribute);
1580
1581 attribute = doc.createAttribute(GSXML.TYPE_ATT);
1582 attribute.setValue(GSXML.PARAM_TYPE_ENUM_SINGLE);
1583 param.setAttributeNode(attribute);
1584
1585 attribute = doc.createAttribute(GSXML.DEFAULT_ATT);
1586 attribute.setValue(ALL_FIELDS);
1587 param.setAttributeNode(attribute);
1588
1589 displayItem = createNameValuePairElement(doc,
1590 GSXML.DISPLAY_TEXT_ELEM, GSXML.DISPLAY_TEXT_NAME,
1591 "in field");
1592 param.appendChild(displayItem);
1593
1594 String[] searchFieldNames
1595 = {ALL_FIELDS, DOC_TITLES, ALL_TITLES, FULLTEXT};
1596 String[] searchFieldDisplay = {"all titles and full-text",
1597 "document titles only", "document and section titles",
1598 "full-text only"};
1599
1600 // for each fieldName create an option element and insert
1601 // the option into the enum_multi drop-down param:
1602 // <option name="fieldName">
1603 // <displayItem name="name">fieldName</displayItem>
1604 // </option>
1605 for(int i = 0; i < searchFieldNames.length; i++) {
1606 Element option = doc.createElement(GSXML.PARAM_OPTION_ELEM);
1607 attribute = doc.createAttribute(GSXML.NAME_ATT);
1608 attribute.setValue(searchFieldNames[i]);
1609 option.setAttributeNode(attribute);
1610
1611 displayItem = createNameValuePairElement(doc,
1612 GSXML.DISPLAY_TEXT_ELEM, GSXML.DISPLAY_TEXT_NAME,
1613 searchFieldDisplay[i]);
1614 option.appendChild(displayItem);
1615 param.appendChild(option); // add option to the drop-down box
1616 }
1617
1618 rowOfParams.appendChild(param);
1619 paramList.appendChild(rowOfParams);
1620 service.appendChild(paramList);
1621 }
1622
1623 /**
1624 * @return a GS3 describe response message for the requested service
1625 * of the given collection. DocumentContent/Metadata/StructureRetrieve
1626 * return nothing special except their names; browse (and any query)
1627 * return more complex XML responses.
1628 * All collections in this Digital Library (Fedora Repository) share
1629 * the same services, so this method returns the same as
1630 * describeService(serviceName).
1631 * @param collectionName - the name of the collection whose service is to
1632 * be described. It will be converted to a fedora collection pid, which is of
1633 * the form "greenstone:&lt;collectionName&gt;-collection".
1634 * @param serviceName - the name of the service in the collection which is to
1635 * be described. */
1636 public String describeCollectionService(String collectionName,
1637 String serviceName) {
1638 // collectionName can be ignored, because all services are FedoraGS3
1639 // services and are not unique to any particular (greenstone) collection.
1640 return describeService(serviceName);
1641 }
1642
1643 /** This method performs the implemented browse operation: allowing the
1644 * user to browse the titles of documents in the given collection by letter
1645 * and returning the results.
1646 * @param classifierID is the id of the classifier on which to browse. In
1647 * this case, the classifier indicates whether we browse titles by letter, or
1648 * browse (documents) by collection; and it is of the form &lt;CL(letter)&gt;.
1649 * @param collectionName is the name of the collection whose documents
1650 * starting with the given letter will be returned.
1651 * @return a GS3 DocumentStructureRetrieve response message which lists all
1652 * the documents that start with the letter indicated by parameter classifier.
1653 */
1654 public String browse(String collectionName, String classifierID)
1655 {
1656 Document doc = builder.newDocument();
1657 FedoraGS3RunException ex = null; //any RemoteException or UnsupportedEncodingException
1658
1659 // <classifierNodeList>
1660 Element classifierNodeList = doc.createElement(
1661 GSXML.CLASS_NODE_ELEM+GSXML.LIST_MODIFIER);
1662
1663 // <classifierNode nodeID="classifierNum">
1664 Element requestedClassifierNode = doc.createElement(
1665 GSXML.CLASS_NODE_ELEM);
1666 Attr attribute = doc.createAttribute(GSXML.NODE_ID_ATT);
1667 attribute.setValue(classifierID);
1668 requestedClassifierNode.setAttributeNode(attribute);
1669 classifierNodeList.appendChild(requestedClassifierNode);
1670
1671 // <nodeStructure>
1672 Element nodeStructure = doc.createElement(GSXML.NODE_STRUCTURE_ELEM);
1673 requestedClassifierNode.appendChild(nodeStructure);
1674
1675 // And one more time, the top level classifierNode:
1676 Element classifierNode = doc.createElement(GSXML.CLASS_NODE_ELEM);
1677 attribute = doc.createAttribute(GSXML.NODE_ID_ATT);
1678 attribute.setValue(classifierID);
1679 classifierNode.setAttributeNode(attribute);
1680 nodeStructure.appendChild(classifierNode);
1681
1682 // Work out what we're browsing base on the classifierID's number
1683 // classifier CL1 = browse titles by letter;
1684 // classifier CL2 = browse by collection;
1685 //remove the CL prefix and obtain the number from the id:
1686 int classifierNum = Integer.parseInt(classifierID.replace("CL", ""));
1687 switch(classifierNum) {
1688 case 1:
1689 // we're going to loop to the end of the alphabet
1690 int num = 1;
1691 for(char ch = 'A'; ch <= 'Z'; ch++, num++) {
1692 // <classifierNode nodeID="CL3.1">
1693 Element subClassifier = doc.createElement(
1694 GSXML.CLASS_NODE_ELEM);
1695 attribute = doc.createAttribute(GSXML.NODE_ID_ATT);
1696 attribute.setValue(classifierID+"."+num);
1697 subClassifier.setAttributeNode(attribute);
1698 classifierNode.appendChild(subClassifier);
1699 // now we are going to retrieve the document structure for
1700 // this subClassifierID: all the documents that begin with
1701 // its letter.
1702 // remove the starting CL
1703 String letter = String.valueOf(ch);
1704 try{
1705 String[] docPIDs = this.browseTitlesByLetter(
1706 collectionName, letter);
1707 // append the <docNodes> for the docPIDs found as children
1708 // of subclassifier
1709 getStructureElement(subClassifier, docPIDs, DESCENDANTS);
1710 //CHILDREN); // for testing
1711 } catch(Exception e) {
1712 ex = new FedoraGS3RunException(e);
1713 ex.setSpecifics("requested portion of TOC file or "
1714 + "trouble with fielded search ");
1715 }
1716 }
1717 break;
1718 case 2:
1719 break;
1720 default:
1721 ex = new FedoraGS3RunException( // cause is regular exception
1722 new Exception("Unknown classifier ID: " + classifierID));
1723 }
1724 Element responseMsg = createResponseMessage(doc, classifierNodeList, ex,
1725 GSXML.REQUEST_TYPE_DESCRIBE, collectionName+"/ClassifierBrowse");
1726 try{
1727 return FedoraCommons.elementToFormattedString(responseMsg);
1728 }catch(TransformerException e) {
1729 return FedoraGS3RunException.xmlToStringConversionFailureResponseMsg
1730 + " " + e;
1731 }
1732 }
1733
1734 /** This method performs something equivalent to a greenstone3
1735 * ClassifierBrowseMetadataRetrieve on the classifierNodeIDs
1736 * @param classNodeIDs array of classifierNode IDs of for which the metadata
1737 * needs to be returned.
1738 * @return a GS3 ClassifierBrowseMetadataRetrieve response message which
1739 * lists the metadata for all the classifierNodes passed as parameter.*/
1740 public String browseMetadataRetrieve(String[] classNodeIDs)
1741 {
1742 Document doc = this.builder.newDocument();
1743 // <classifierNodeList>
1744 Element classifierNodeList = doc.createElement(
1745 GSXML.CLASS_NODE_ELEM+GSXML.LIST_MODIFIER);
1746
1747 // create <classifierNode><metadataList><metadata>s
1748 // </metadataList></classifierNode> for all letters of alphabet
1749 for(int i = 0; i < classNodeIDs.length; i++) {
1750 // strip ID of everything before the first '.' (i.e. remove "CL#.")
1751 int index = classNodeIDs[i].indexOf('.');
1752 String subClassifierNumber = classNodeIDs[i].substring(index+1);
1753 int subClassifierNum = Integer.parseInt(subClassifierNumber);
1754 char letter = (char)('A' + subClassifierNum - 1); // A = 1
1755
1756 // <classifierNode nodeID="CL#.subNum">
1757 Element classifierNode = doc.createElement(GSXML.CLASS_NODE_ELEM);
1758 Attr attribute = doc.createAttribute(GSXML.NODE_ID_ATT);
1759 attribute.setValue(classNodeIDs[i]);
1760 classifierNode.setAttributeNode(attribute);
1761
1762 // <metadataList>
1763 Element metadataList = doc.createElement(
1764 GSXML.METADATA_ELEM+GSXML.LIST_MODIFIER);
1765
1766 // at least one metadata element: that of the title of this
1767 // classifierNode:
1768 // <metadata name="Title">letter</metadata>
1769 Element metadata = this.createNameValuePairElement(doc,
1770 GSXML.METADATA_ELEM, "Title", String.valueOf(letter));
1771
1772 // now connect up everything
1773 metadataList.appendChild(metadata);
1774 classifierNode.appendChild(metadataList);
1775 classifierNodeList.appendChild(classifierNode);
1776 }
1777
1778 Element responseMsg = createResponseMessage(doc, classifierNodeList, null,
1779 GSXML.REQUEST_TYPE_PROCESS, //collName +
1780 "ClassifierBrowseMetadataRetrieve");
1781 try{
1782 return FedoraCommons.elementToFormattedString(responseMsg);
1783 }catch(TransformerException e) {
1784 return FedoraGS3RunException.xmlToStringConversionFailureResponseMsg
1785 + " " + e;
1786 }
1787 }
1788
1789 /** @return a newly created element of the following format:
1790 * &lt;classifier content="somecontent" name="CL+num"&gt;
1791 * &lt;displayItem name="name"&gt;someClassifierName&lt;/displayItem&gt;
1792 * &lt;displayItem name="description"&gt;Browse by classifier name&lt;/displayItem&gt;
1793 * &lt;/classifier&gt;
1794 * @param doc - the document used to create the element
1795 * @param content - value of the content attribute
1796 * @param classifierNum - the number suffixed to the CL, together forming
1797 * the classifier Node's ID
1798 * @param displayNameVal is the bodytext of a named displayItem element
1799 * @param displayDescrVal is the bodytext of a displayItem element with
1800 * description */
1801 protected Element createClassifierElement(Document doc, String content,
1802 int classifierNum, String displayNameVal, String displayDescrVal)
1803 {
1804 final String CL = "CL";
1805 Element classifier = doc.createElement(GSXML.CLASSIFIER_ELEM);
1806 // content attribute
1807 Attr att = doc.createAttribute(GSXML.CLASSIFIER_CONTENT_ATT);
1808 att.setValue(content);
1809 classifier.setAttributeNode(att);
1810 // name attribute
1811 att = doc.createAttribute(GSXML.NAME_ATT);
1812 att.setValue(CL + classifierNum);
1813 classifier.setAttributeNode(att);
1814
1815 // now create the displayItem children for classifier:
1816 // <displayItem name="name">#letter</displayItem>
1817 // <displayItem name="description">
1818 //Browse titles starting with #letter</displayItem>
1819 Element displayItem = createNameValuePairElement(doc,
1820 GSXML.DISPLAY_TEXT_ELEM, GSXML.DISPLAY_TEXT_NAME, displayNameVal);
1821 classifier.appendChild(displayItem);
1822 displayItem = createNameValuePairElement(doc, GSXML.DISPLAY_TEXT_ELEM,
1823 GSXML.DISPLAY_TEXT_DESCRIPTION, displayDescrVal);
1824 classifier.appendChild(displayItem);
1825
1826 return classifier;
1827 }
1828
1829
1830 /** @return a newly created element of the following format:
1831 * &lt;elementName name="somename"&gt;"some display value"&lt;/elementName&gt;
1832 * @param doc - the document used to create the element
1833 * @param elementName - the tag name
1834 * @param name - value of attribute name
1835 * @param value - the body text of the element */
1836 protected Element createNameValuePairElement(Document doc, String elementName,
1837 String name, String value) {
1838 // <elementName name="somename">"some display value"</elementName>
1839 Element element = doc.createElement(elementName);
1840 Attr attribute = doc.createAttribute(GSXML.NAME_ATT);
1841 attribute.setValue(name);
1842 element.setAttributeNode(attribute);
1843
1844 element.appendChild(doc.createTextNode(value));
1845 return element;
1846 }
1847
1848 /**
1849 * @param collection is the collection to search in
1850 * @param query is the query term to search for. It won't specify the
1851 * indexed field to search in, which will mean that GSearch will
1852 * search all default indexed fields.
1853 * @param maxDocs is the maximum number of results to return (which
1854 * at present we consider equivalent to FedoraGSearch's hitpageSize).
1855 */
1856 public String[] textQuery(String collection, String query,
1857 int maxDocs)
1858 throws Exception
1859 {
1860 // no need to search there is no query or query is empty spaces
1861 if(query.trim().equals(""))
1862 return new String[]{};
1863
1864 // QUERY value won't specify indexed field to search, Fedora
1865 // Gsearch will take that as meaning all default indexed fields.
1866 // Params to search() method below: string of fielded query terms;
1867 // hitpageStart, hitpageEnd, snippetsMax (leave that 0)
1868 query = query + " " + "PID" + COLON + GREENSTONE;
1869
1870 String searchResult = this.fedoraGSearch.search(query, 1, maxDocs, 0);
1871 // now we have the XML returned by FedoraGSearch, get the pids
1872 // of the documents returned (if any)
1873 String[] pids = this.fedoraGSearch.getPIDsFromSearchResult(
1874 collection, searchResult);
1875 return pids;
1876 }
1877
1878 /**
1879 * This method performs a fieldquery, searching for x number of phrases
1880 * in each of the 4 indexed fields.
1881 * @param collection is the collection to search in
1882 * @param nameValParamsMap is a Map of several(key, value) entries,
1883 * 4 of which we're concerned with here:
1884 * - the keys are ALL_FIELDS, DOC_TITLES, ALL_TITLES, FULLTEXT
1885 * - the values are a comma separated list of terms (phrases or single
1886 * words) to search that field in. There may be more than 1 or
1887 * there may be none (in which case there may be N empty values or
1888 * spaces separated by commas).
1889 * @param maxDocs is the maximum number of results to return (which
1890 * at present we consider equivalent to FedoraGSearch's hitpageSize).
1891 * */
1892 public String[] fieldQuery(String collection, Map nameValParamsMap,
1893 int maxDocs)
1894 throws Exception
1895 {
1896 // we're going to maintain a list of UNIQUE pids that were returned
1897 // in search results. Hence we use Set:
1898 java.util.Set set = new java.util.HashSet();
1899
1900 // (1) Use Fedora's search to search document titles, if they were
1901 // specified:
1902 String[] docTitlepids = {};
1903
1904 String docTitleTerms = (String)nameValParamsMap.get(DOC_TITLES);
1905 if(docTitleTerms != null) { // no doc titles may have been specified
1906 String[] phrases = docTitleTerms.split(COMMA);
1907
1908 // search the individual phrases first:
1909 for(int i = 0; i < phrases.length; i++) {
1910 if(phrases.equals("") || phrases.equals(" "))
1911 continue; //skip when there are no terms
1912 docTitlepids = this.searchDocumentTitles(
1913 collection, phrases[i], false);
1914 for(int j = 0; j < docTitlepids.length; j++)
1915 set.add(docTitlepids[j]);
1916 }
1917 }
1918 // (2) use FedoraGSearch to search doc AND section titles, and
1919 // fulltext (in case these were specified in nameValParamsMap):
1920 String searchResult = this.fedoraGSearch.search(
1921 nameValParamsMap, 1, maxDocs);
1922
1923 String[] pids = this.fedoraGSearch.getPIDsFromSearchResult(
1924 collection, searchResult);
1925
1926 for(int i = 0; i < pids.length; i++)
1927 set.add(pids[i]);
1928
1929 pids = null;
1930 pids = new String[set.size()];
1931 set.toArray(pids); // unique pids
1932 return pids;
1933 }
1934
1935 /** @return a String representing Greenstone3 XML for a query process
1936 * response returning the results for the query denoted by parameter
1937 * nameValParamsMap.
1938 * @param nameValParamsMap is a Hashmap of name and value pairs for all the
1939 * query field data values. The names match the field names that
1940 * describeCollectionService() would have returned for the query service.
1941 * @param collection is the name of the collection
1942 * @param service is the name of the query service
1943 * This method is only ever called when any of the services in the digital
1944 * library described themselves as type=query. Therefore any digital
1945 * libraries that have no query services, can just return emtpy message
1946 * strings (or even "") since this method will never be called on them
1947 * anyway. */
1948 public String query(String collection, String service,
1949 Map nameValParamsMap)
1950 {
1951 FedoraGS3RunException ex = null;
1952 // (1) obtain the requested number of maximum result documents
1953 int maxDocs = 100;
1954 try{
1955 maxDocs = Integer.parseInt((String)nameValParamsMap.get(MAXDOCS));
1956 } catch(NumberFormatException e) {
1957 maxDocs = 100;
1958 }
1959
1960 String pids[] = {};
1961 // (2) for Textquery, we simply search ALL_FIELDS using FedoraGSearch
1962 if(service.equals("TextQuery")) {
1963 try {
1964 // get the Query field:
1965 String query = (String)nameValParamsMap.get(QUERY);
1966 pids = textQuery(collection, query, maxDocs);
1967 }
1968 catch(Exception e) {
1969 LOG.error("Error in TextQuery processing: " + e);
1970 ex = new FedoraGS3RunException(
1971 "When trying to use FedoraGenericSearch for a TextQuery", e);
1972
1973 }
1974 } else { // (3) FieldQuery
1975 // first get the comma-separated lists
1976 String listOfFieldNames = (String)nameValParamsMap.get(FIELDNAME_ATT);
1977 String listOfSearchTerms = (String)nameValParamsMap.get(QUERY);
1978 // both are comma separated lists, so split both on 'comma'
1979 String[] fieldNames = listOfFieldNames.split(COMMA);
1980 String[] searchTerms = listOfSearchTerms.split(COMMA);
1981
1982 // In the fieldNames and searchTerms lists of nameValParamsMap,
1983 // each searchTerm element was matched with its correspondingly
1984 // indexed fieldName.
1985 // A new map is going to reorganise this, by putting all terms
1986 // for a particular fieldName together in a comma separated list
1987 // and associating that with the fieldName. I.e. (key, value) ->
1988 // (fieldName, comma-separated list of all terms in that field)
1989 Map map = new HashMap();
1990 for(int i = 0; i < searchTerms.length; i++) {
1991 // there may be fewer searchTerms than fieldNames (since some
1992 // fieldNames may have been left empty), so loop on searchTerms
1993 if(map.containsKey(fieldNames[i])) { //fieldName is already
1994 // in the list, so append comma with new value
1995 String termsList = (String)map.get(fieldNames[i]);
1996 termsList = termsList + COMMA + searchTerms[i];
1997 map.put(fieldNames[i], termsList);
1998 } else { // this is the first time this fieldName occurred
1999 // just put the fieldName with searchTerm as-is
2000 map.put(fieldNames[i], searchTerms[i]);
2001 }
2002 }
2003
2004 try {
2005 // For fieldquery, we search on all the fieldNames specified
2006 // - if DOC_TITLES is specified then we use Fedora's search
2007 // - for all other fieldNames specified, we use FedoraGSearch
2008 pids = fieldQuery(collection, map, maxDocs);
2009 }
2010 catch(Exception e) {
2011 LOG.error("Error in FieldQuery processing: " + e);
2012 ex = new FedoraGS3RunException(
2013 "When trying to use FedoraGenericSearch for a FieldQuery", e);
2014 }
2015 }
2016
2017 // Build Greenstone XML Query response message for from
2018 // the pids (which should be document identifiers)
2019 Document doc = builder.newDocument();
2020 // <metadataList><metadata name="numDocsMatched" value="n" />
2021 // </metadataList>
2022 Element metadataList = doc.createElement(
2023 GSXML.METADATA_ELEM+GSXML.LIST_MODIFIER);
2024 Element metadata = doc.createElement(GSXML.METADATA_ELEM);
2025
2026 Attr attribute = doc.createAttribute(GSXML.NAME_ATT);
2027 attribute.setValue(NUM_DOCS_MATCHED);
2028 metadata.setAttributeNode(attribute);
2029
2030 attribute = doc.createAttribute(GSXML.VALUE_ATT);
2031 attribute.setValue(Integer.toString(pids.length));
2032 metadata.setAttributeNode(attribute);
2033
2034 metadataList.appendChild(metadata);
2035
2036 // <documentNodeList>
2037 // <documentNode nodeID="HASHac0a04dd14571c60d7fbfd.4.2"
2038 // docType='hierarchy' nodeType="leaf" />
2039 // ...
2040 // ...
2041 // </documentNodeList>
2042 Element docNodeList = doc.createElement(
2043 GSXML.DOC_NODE_ELEM+GSXML.LIST_MODIFIER);
2044 // for each
2045 for(int i = 0; i < pids.length; i++) {
2046 Element docNode = doc.createElement(GSXML.DOC_NODE_ELEM);
2047 attribute = doc.createAttribute(GSXML.NODE_ID_ATT);
2048 attribute.setValue(pids[i]);
2049 docNode.setAttributeNode(attribute);
2050
2051 attribute = doc.createAttribute(GSXML.DOC_TYPE_ATT);
2052 attribute.setValue("hierarchy");
2053 docNode.setAttributeNode(attribute);
2054
2055 attribute = doc.createAttribute(GSXML.NODE_TYPE_ATT);
2056 attribute.setValue("root");
2057 docNode.setAttributeNode(attribute);
2058 docNodeList.appendChild(docNode);
2059 }
2060
2061 Element responseMsg = createResponseMessage(doc, docNodeList, ex,
2062 GSXML.REQUEST_TYPE_PROCESS, service);
2063 try{
2064 return FedoraCommons.elementToFormattedString(responseMsg);
2065 }catch(TransformerException e) {
2066 return FedoraGS3RunException.xmlToStringConversionFailureResponseMsg
2067 + " " + e;
2068 }
2069 }
2070
2071 public static void main(String args[]) {
2072 try{
2073 // testing default constructor
2074 //FedoraGS3Connection con = new FedoraGS3Connection();
2075
2076 // testing constructor that takes properties file to show initial
2077 // fedora server values
2078 java.io.File propertyFilename
2079 = new java.io.File("fedoraGS3.properties");
2080 FedoraGS3Connection con = new FedoraGS3Connection(propertyFilename);
2081
2082 // DESCRIBE: serviceList, collectionList
2083 System.out.println("serviceList:\n" + con.getServiceList());
2084
2085 System.out.println("collectionList:\n" + con.getCollectionList());
2086
2087 String[] colPIDs = con.getCollections();
2088 String[] collectionNames = con.getCollectionNames(con.getCollections());
2089
2090
2091 for(int i = 0; i < collectionNames.length; i++) {
2092 System.out.println("Describing collections:\n");
2093 System.out.println(con.describeCollection(collectionNames[i]));
2094 System.out.println("Describing collection services:\n"
2095 + con.describeCollectionServices(collectionNames[i]));
2096 }
2097
2098 String[] serviceNames = con.getServiceNames();
2099 for(int i = 0; i < serviceNames.length; i++) {
2100 System.out.println("Describing " + serviceNames[i] + ":\n"
2101 + con.describeCollectionService("demo", serviceNames[i]));
2102 }
2103
2104
2105 // TRYING OUT SPECIAL top-level document metadata retrieval (DLS, DC)
2106 // along with EX of the top-level document:
2107 System.out.println("\nGET META for greenstone:gs2mgdemo-HASH01d667303fe98545f03c14ae:");
2108 System.out.println(con.getDocumentMetadata(new String[]{"greenstone:gs2mgdemo-HASH01d667303fe98545f03c14ae"}));
2109
2110
2111 String[] docIDs = con.getCollectionDocs(colPIDs[0]);
2112 System.out.println("\nGET CONTENT:");
2113 for(int i = 0; i < docIDs.length; i++) {
2114 System.out.println(con.getContent(docIDs[i]));
2115 }
2116
2117 System.out.println("\nGET META:");
2118 for(int i = 0; i < docIDs.length; i++) {
2119 System.out.println(con.getDocumentMetadata(docIDs[i]));
2120 }
2121
2122 String[] getTitlesFor = {
2123 "greenstone:gs2mgdemo-HASH01d667303fe98545f03c14ae",
2124 "greenstone:gs2mgdemo-HASHa568bac1d8d7bd12a0938b",
2125 "greenstone:gs2mgdemo-HASHa568bac1d8d7bd12a0938b-1",
2126 "greenstone:gs2mgdemo-HASH01d667303fe98545f03c14ae-1.7",
2127 "greenstone:gs2mgdemo-HASHa568bac1d8d7bd12a0938b-1.5.1"
2128 };
2129
2130 // first let's display the regular meta for top-level docs and
2131 // their sections
2132 for(int i = 0; i < getTitlesFor.length; i++) {
2133 System.out.println(con.getDocumentMetadata(getTitlesFor[i]));
2134 }
2135
2136 System.out.println("\nTitles are:");
2137 System.out.println(con.getTitleMetadata(getTitlesFor));
2138
2139 System.out.println("\nGET STRUCTURE:");
2140 for(int i = 0; i < docIDs.length; i++) {
2141 System.out.println(con.getChildren(docIDs[i]));
2142 System.out.println(con.getDocumentStructure(docIDs[i]));
2143 }
2144
2145 // TEST ERROR CASES:
2146 System.out.println("\nTESTING ERROR CASES");
2147 System.out.println(con.getContent("greenstone:demo-pinky"));
2148 String[] errorCases = { "greenstone:demo-HASH23d1019b589e2ef6a680e3-1.5.1.5",
2149 "greenstone:demo-pinky" };
2150 System.out.println(con.getContent(errorCases));
2151 System.out.println(con.getDocumentMetadata(errorCases));
2152 System.out.println(con.getDocumentStructure(errorCases));
2153
2154 System.out.println("\nCLASSIFIER BROWSE");
2155 System.out.println(con.browse("gs2mgdemo", //"ClassifierBrowse",
2156 "CL1"));
2157
2158 System.out.println("\nCLASSIFIER BROWSE METADATA RETRIEVE");
2159 String[] classNodeIDs = new String[26];
2160 for(int i = 0; i < classNodeIDs.length; i++) {
2161 int subClassifierNum = i + 1;
2162 classNodeIDs[i] = "CL1." + subClassifierNum;
2163 }
2164 System.out.println(con.browseMetadataRetrieve(//"gs2mgdemo",
2165 classNodeIDs));
2166
2167 System.out.println("Testing query services");
2168 System.out.println("TEXT QUERY:");
2169 Map formControlValsMap = new HashMap();
2170 formControlValsMap.put(MAXDOCS, "100");
2171 formControlValsMap.put(QUERY, "snails");
2172 String searchResponse
2173 = con.query("gs2mgdemo", "TextQuery", formControlValsMap);
2174 System.out.println(searchResponse);
2175
2176 System.out.println("FIELD QUERY:");
2177 formControlValsMap.clear();
2178 formControlValsMap.put(MAXDOCS, "100");
2179 formControlValsMap.put(QUERY, "interview,Gender equality,cyclone");
2180 formControlValsMap.put(FIELDNAME_ATT,
2181 "allFields,docTitles,allFields,allFields");
2182 searchResponse
2183 = con.query("gs2mgdemo", "FieldQuery", formControlValsMap);
2184 System.out.println(searchResponse);
2185
2186 System.exit(0);
2187 }catch(Exception e) {
2188 JOptionPane.showMessageDialog(
2189 null, e, "Error", JOptionPane.ERROR_MESSAGE);
2190 //System.err.println("ERROR: " + e);
2191 e.printStackTrace();
2192 }
2193 }
2194}
Note: See TracBrowser for help on using the repository browser.