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

Last change on this file since 21924 was 21924, checked in by ak19, 14 years ago

The collection name or FedoraGS3 should not be prepended to the from location of the classifier browse and browse metaretrieve response XMLs.

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