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

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

Overriding init() method to work with recently modified (previously unused) additional constructor.

File size: 92.9 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 String from = originator.equals("") ? FEDORA_GS3
1127 : FEDORA_GS3+"/"+originator;
1128
1129 attribute.setValue(from);
1130 response.setAttributeNode(attribute);
1131
1132 // type = "describe" or "process" - whatever's given in requestType:
1133 attribute = doc.createAttribute(GSXML.TYPE_ATT);
1134 attribute.setValue(responseType);
1135 response.setAttributeNode(attribute);
1136
1137 if(content != null)
1138 response.appendChild(content);
1139
1140 // we'll create an error element for RemoteExceptions (web service problems)
1141 // and UnsupportedEncodingExceptions and
1142 if(ex != null) {
1143 Element error = doc.createElement(GSXML.ERROR_ELEM);
1144 error.appendChild(doc.createTextNode(ex.getMessage()));
1145 // now append the error to the <response> element (after
1146 // the content element whatever that was)
1147 response.appendChild(error);
1148 }
1149
1150 Element message = doc.createElement(GSXML.MESSAGE_ELEM);
1151 message.appendChild(response);
1152 doc.appendChild(message);
1153 return message;
1154 }
1155
1156 /** @return a &lt;serviceList&gt; Element as defined by GS3: containing all the
1157 * services (denoted by &lt;service&gt; elements) that are supported by FedoraGS3.
1158 * At present these are: DocumentContentRetrieve, DocumentMetadataRetrieve,
1159 * DocumentStructureRetrieve, TextQuery, FieldQuery, ClassifierBrowse,
1160 * ClassifierBrowseMetadataRetrieve (as indicated by member var serviceNames).
1161 * @param doc - the Document object which should me used to create the
1162 * &lt;serviceList&gt; element */
1163 protected Element createServiceList(Document doc)
1164 {
1165 Element serviceList = doc.createElement(
1166 GSXML.SERVICE_ELEM+GSXML.LIST_MODIFIER);
1167
1168 for(int i = 0; i < serviceNames.length; i++) {
1169 // create the <service name="serviceName[i]" type="servicetype" />
1170 Element service = doc.createElement(GSXML.SERVICE_ELEM);
1171
1172 Attr attribute = doc.createAttribute(GSXML.NAME_ATT);
1173 attribute.setValue(serviceNames[i]);
1174 service.setAttributeNode(attribute);
1175
1176 attribute = doc.createAttribute(GSXML.TYPE_ATT);
1177 if(serviceNames[i].equals("ClassifierBrowse")) //browseTitlesByLetter
1178 attribute.setValue(GSXML.SERVICE_TYPE_BROWSE);
1179 else if(serviceNames[i].contains("Query")) // search services
1180 attribute.setValue(GSXML.SERVICE_TYPE_QUERY);
1181 else
1182 attribute.setValue(GSXML.SERVICE_TYPE_RETRIEVE);
1183 service.setAttributeNode(attribute);
1184
1185 // add the service element to the serviceList element
1186 // <serviceList><service /></serviceList>
1187 serviceList.appendChild(service);
1188 }
1189 return serviceList;
1190 }
1191
1192 /** @return a GS3 response message for a describe services request:
1193 * indicating the list of services supported by the Fedora-Greenstone
1194 * interface. These are DocumentContentRetrieve, DocumentMetadataRetrieve,
1195 * DocumentStructureRetrieve, ClassifierBrowse, TextQuery, FieldQuery,
1196 * ClassifierBrowseMetadataRetrieve - as indicated by member variable
1197 * serviceNames. */
1198 public String getServiceList()
1199 {
1200 Document doc = builder.newDocument();
1201 Element serviceList = createServiceList(doc);
1202 // make <serviceList> the body of the responseMessage:
1203 // <message><response><serviceList></response></message>
1204 Element responseMsg = createResponseMessage(doc, serviceList, null,
1205 GSXML.REQUEST_TYPE_DESCRIBE, "");
1206 try {
1207 return FedoraCommons.elementToFormattedString(responseMsg);
1208 }catch(TransformerException e) {
1209 return FedoraGS3RunException.xmlToStringConversionFailureResponseMsg
1210 + " " + e;
1211 }
1212 }
1213
1214 /** @return a GS3 describe response message listing the collections and
1215 * collection-specific metadata stored in the Fedora-Greenstone repository. */
1216 public String getCollectionList()
1217 {
1218 Document doc = builder.newDocument();
1219 FedoraGS3RunException ex = null; // any RemoteException
1220
1221 // create the <collectionList /> element
1222 Element collectionList = doc.createElement(
1223 GSXML.COLLECTION_ELEM+GSXML.LIST_MODIFIER);
1224 try{
1225 String[] collectionNames = this.getCollectionNames(
1226 this.getCollections()); // this line could throw RemoteException
1227 for(int i = 0; i < collectionNames.length; i++) {
1228 // create the <collection name="somename" /> element
1229 Element collection = doc.createElement(GSXML.COLLECTION_ELEM);
1230 Attr attribute = doc.createAttribute(GSXML.NAME_ATT);
1231 attribute.setValue(collectionNames[i]);
1232 collection.setAttributeNode(attribute);
1233
1234 // append the <collection> element as child of <collectionList>
1235 collectionList.appendChild(collection);
1236
1237 //if(collection.hasAttribute(GSXML.NAME_ATT))
1238 //LOG.debug(collection.getAttribute(GSXML.NAME_ATT));
1239 }
1240 } catch(RemoteException e) { // if this happens, perhaps it's because it
1241 // can't find Greenstone collections in fedora repository?
1242 ex = new FedoraGS3RunException(e);
1243 ex.setSpecifics(
1244 "greenstone collections in fedora repository");
1245 }
1246
1247 // make <collectionList> the body of the responseMessage:
1248 // <message><response><collectionList></response></message>
1249 Element responseMsg = createResponseMessage(doc, collectionList, ex,
1250 GSXML.REQUEST_TYPE_DESCRIBE, "");
1251 try{
1252 return FedoraCommons.elementToFormattedString(responseMsg);
1253 }catch(TransformerException e) {
1254 return FedoraGS3RunException.xmlToStringConversionFailureResponseMsg
1255 + " " + e;
1256 }
1257 }
1258
1259 /** @return a GS3 describe response message for a collection in the
1260 * Fedora-Greenstone repository.
1261 * @param collectionName - the name of the collection that is to be described.
1262 * It will be converted to a fedora collection pid, which is of the form
1263 * "greenstone:&lt;collectionName&gt;-collection". */
1264 public String describeCollection(String collectionName)
1265 {
1266 Document doc = builder.newDocument();
1267 FedoraGS3RunException ex = null;
1268
1269 Element collection = doc.createElement(GSXML.COLLECTION_ELEM);
1270 Attr attribute = doc.createAttribute(GSXML.NAME_ATT);
1271 attribute.setValue(collectionName);
1272 collection.setAttributeNode(attribute);
1273
1274 //<displayItem assigned="true" lang="en" name="name">
1275 //"some display name"</displayItem>
1276 Element displayItem = doc.createElement(GSXML.DISPLAY_TEXT_ELEM);
1277
1278 attribute = doc.createAttribute(GSXML.LANG_ATT);
1279 attribute.setValue(this.lang);
1280 displayItem.setAttributeNode(attribute);
1281
1282 attribute = doc.createAttribute(GSXML.NAME_ATT);
1283 attribute.setValue(GSXML.DISPLAY_TEXT_NAME);
1284 displayItem.setAttributeNode(attribute);
1285
1286 try{
1287 Text textNode = doc.createTextNode(
1288 this.getCollectionTitle(getCollectionPID(collectionName)));
1289 displayItem.appendChild(textNode);
1290 } catch(Exception e) {
1291 // can't find Greenstone collections in fedora repository or problem
1292 // getting their titles from their metadata datastream?
1293 ex = new FedoraGS3RunException(e);
1294 ex.setSpecifics("greenstone collections or their metadata"
1295 + "in the fedora repository");
1296 }
1297 // now append the displayItem element as child of the collection element
1298 collection.appendChild(displayItem);
1299 // get the <serviceList> and add it into the collection description.
1300 // Services for all collections in the FedoraGS3 repository are the
1301 // same, offering a ClassifierBrowse to browse titles by starting letter
1302 // and DocRetrieve services: Content, Metadata and Structure.
1303
1304 Element serviceList = createServiceList(doc);
1305 collection.appendChild(serviceList);
1306
1307 Element responseMsg = createResponseMessage(doc, collection, ex,
1308 GSXML.REQUEST_TYPE_DESCRIBE, collectionName);
1309 try{
1310 return FedoraCommons.elementToFormattedString(responseMsg);
1311 }catch(TransformerException e) {
1312 return FedoraGS3RunException.xmlToStringConversionFailureResponseMsg
1313 + " " + e;
1314 }
1315 }
1316
1317 /** @return a GS3 describe response message for the services of a collection
1318 * in the Fedora-Greenstone repository. So far, these services are the same for
1319 * all fedora collections: they are the services given in member variable
1320 * serviceNames: DocumentContent/Metadata/StructureRetrieve, ClassifierBrowse,
1321 * ClassifierBrowseMetadataRetrieve.
1322 * All collections in this Digital Library (Fedora Repository) share the
1323 * same services, so this method returns the same services as getServiceList();
1324 * @param collectionName - the name of the collection whose services are to
1325 * be described. It will be converted to a fedora collection pid, which is of
1326 * the form "greenstone:&lt;collectionName&gt;-collection". */
1327 public String describeCollectionServices(String collectionName)
1328 {
1329 Document doc = builder.newDocument();
1330
1331 Element collection = doc.createElement(GSXML.COLLECTION_ELEM);
1332 Attr attribute = doc.createAttribute(GSXML.NAME_ATT);
1333 attribute.setValue(collectionName);
1334 collection.setAttributeNode(attribute);
1335
1336 Element serviceList = createServiceList(doc);
1337 collection.appendChild(serviceList);
1338
1339 Element responseMsg = createResponseMessage(doc, collection, null,
1340 GSXML.REQUEST_TYPE_DESCRIBE, collectionName);
1341 try{
1342 return FedoraCommons.elementToFormattedString(responseMsg);
1343 }catch(TransformerException e) {
1344 return FedoraGS3RunException.xmlToStringConversionFailureResponseMsg
1345 + " " + e;
1346 }
1347 }
1348
1349 /** All collections in this Digital Library (Fedora Repository) share
1350 * the same services, so this method returns the same as
1351 * describeCollectionService(collName, serviceName).
1352 * @return a GS3 describe response message for the requested service
1353 * of the given collection. DocumentContent/Metadata/StructureRetrieve
1354 * return nothing special except their names; browse (and any query)
1355 * return more complex XML responses.
1356 * @param serviceName - the name of the service in the collection which is to
1357 * be described.*/
1358 public String describeService(String serviceName)
1359 {
1360 // For all the *retrieve* services (incl ClassifierBrowseMetadataRetrieve)
1361 // we return:
1362 // <message><response from="<name>Retrieve" type="describe">
1363 // <service name="<name>Retrieve" type="retrieve" /></response></message>
1364 // But for browse (and any query) service, we return the data necessary
1365 // for displaying it
1366
1367 Document doc = this.builder.newDocument();
1368 Element service = doc.createElement(GSXML.SERVICE_ELEM);
1369 Attr attribute = doc.createAttribute(GSXML.NAME_ATT);
1370 attribute.setValue(serviceName);
1371 service.setAttributeNode(attribute);
1372
1373 attribute = doc.createAttribute(GSXML.TYPE_ATT);
1374
1375 if(serviceName.toLowerCase().endsWith("retrieve")) {
1376 attribute.setValue(GSXML.SERVICE_TYPE_RETRIEVE);
1377 }
1378 else if(serviceName.toLowerCase().contains("browse")) {
1379 attribute.setValue(GSXML.SERVICE_TYPE_BROWSE);
1380
1381 // we need name and description <displayItem> elements
1382 Element displayItem
1383 = createNameValuePairElement(doc,
1384 GSXML.DISPLAY_TEXT_ELEM, GSXML.DISPLAY_TEXT_NAME, "Browse");
1385 service.appendChild(displayItem);
1386
1387 displayItem = createNameValuePairElement(doc,
1388 GSXML.DISPLAY_TEXT_ELEM, GSXML.DISPLAY_TEXT_DESCRIPTION,
1389 "Browse pre-defined classification hierarchies");
1390 service.appendChild(displayItem);
1391
1392 // now need a classifierList
1393 Element classifierList = doc.createElement(
1394 GSXML.CLASSIFIER_ELEM+GSXML.LIST_MODIFIER);
1395
1396 int classifierNum = 1;
1397 // append a <classifier content="some letter" name="CL#">
1398 // for each letter of the alphabet:
1399 Element classifier = createClassifierElement(doc, "TitleByLetter",
1400 classifierNum++, "titles by letter", "Browse titles by letter");
1401 // now add this <classifier> to the <classifierList>
1402 classifierList.appendChild(classifier);
1403
1404 // ANY MORE CLASSIFIERS? ADD THEM HERE
1405
1406 service.appendChild(classifierList);
1407 } // ELSE check for whether it is a query service
1408 else if(serviceName.toLowerCase().contains("query")) {
1409 attribute.setValue(GSXML.SERVICE_TYPE_QUERY);
1410 if(serviceName.equals("TextQuery")) {
1411 describeTextQueryService(service);
1412 } else if(serviceName.equals("FieldQuery")) {
1413 describeFieldQueryService(service);
1414 }
1415 }
1416
1417 // don't forget to add the type attribute to the service!
1418 service.setAttributeNode(attribute);
1419
1420 String from = serviceName;
1421
1422 Element responseMsg = createResponseMessage(doc, service, null,
1423 GSXML.REQUEST_TYPE_DESCRIBE, from);
1424 try{
1425 return FedoraCommons.elementToFormattedString(responseMsg);
1426 }catch(TransformerException e) {
1427 return FedoraGS3RunException.xmlToStringConversionFailureResponseMsg
1428 + " " + e;
1429 }
1430 }
1431
1432 /** Appends children to the parameter service Element that make the
1433 * final service Element into a describe response XML for FedoraGS3's
1434 * TextQuery service.
1435 * @param service is the service Element that is being filled out. */
1436 protected void describeTextQueryService(Element service) {
1437 Document doc = service.getOwnerDocument();
1438 // we need name, submit (button) and description <displayItem> elements
1439 Element displayItem = createNameValuePairElement(doc,
1440 GSXML.DISPLAY_TEXT_ELEM, GSXML.DISPLAY_TEXT_NAME,
1441 "Text Search");
1442 service.appendChild(displayItem);
1443
1444 displayItem = createNameValuePairElement(doc,
1445 GSXML.DISPLAY_TEXT_ELEM, GSXML.DISPLAY_TEXT_SUBMIT, "Search");
1446 service.appendChild(displayItem);
1447
1448 displayItem = createNameValuePairElement(doc,
1449 GSXML.DISPLAY_TEXT_ELEM, GSXML.DISPLAY_TEXT_DESCRIPTION,
1450 "Title and full-text search service");
1451 service.appendChild(displayItem);
1452
1453 //create the <paramList>
1454 Element paramList = doc.createElement(
1455 GSXML.PARAM_ELEM+GSXML.LIST_MODIFIER);
1456
1457 // we ignore granularity to search at: it will always be
1458 // document and section level
1459 // we ignore casefolding: always on (that is, case is irrelevant)
1460 // we ignore document display order: always ranked
1461
1462 // Constructing the following:
1463 // <param default="100" name="maxDocs" type="integer">
1464 // <displayItem name="name">Maximum hits to return</displayItem>
1465 // </param>
1466 Element param = doc.createElement(GSXML.PARAM_ELEM);
1467
1468 Attr attribute = doc.createAttribute(GSXML.NAME_ATT);
1469 attribute.setValue(MAXDOCS);
1470 param.setAttributeNode(attribute);
1471
1472 attribute = doc.createAttribute(GSXML.DEFAULT_ATT);
1473 attribute.setValue("100");
1474 param.setAttributeNode(attribute);
1475
1476 attribute = doc.createAttribute(GSXML.TYPE_ATT);
1477 attribute.setValue(GSXML.PARAM_TYPE_INTEGER);
1478 param.setAttributeNode(attribute);
1479
1480 displayItem = createNameValuePairElement(doc,
1481 GSXML.DISPLAY_TEXT_ELEM, GSXML.DISPLAY_TEXT_NAME,
1482 "Maximum hits to return");
1483 param.appendChild(displayItem);
1484
1485 paramList.appendChild(param);
1486
1487 // Constructing the following:
1488 // <param name="query" type="string">
1489 // <displayItem name="name">Query string</displayItem>
1490 // </param>
1491 param = doc.createElement(GSXML.PARAM_ELEM);
1492
1493 attribute = doc.createAttribute(GSXML.NAME_ATT);
1494 attribute.setValue(QUERY);
1495 param.setAttributeNode(attribute);
1496
1497 attribute = doc.createAttribute(GSXML.TYPE_ATT);
1498 attribute.setValue(GSXML.PARAM_TYPE_STRING);
1499 param.setAttributeNode(attribute);
1500
1501 displayItem = createNameValuePairElement(doc,
1502 GSXML.DISPLAY_TEXT_ELEM, GSXML.DISPLAY_TEXT_NAME,
1503 "Query string");
1504 param.appendChild(displayItem);
1505
1506 paramList.appendChild(param);
1507
1508 service.appendChild(paramList);
1509 }
1510
1511 /** Appends children to the parameter service Element that make the
1512 * final service Element into a describe response XML for FedoraGS3's
1513 * FieldQuery service.
1514 * @param service is the service Element that is being filled out. */
1515 protected void describeFieldQueryService(Element service) {
1516 Document doc = service.getOwnerDocument();
1517 // we need name, submit (button) and description <displayItem> elements
1518 Element displayItem = createNameValuePairElement(doc,
1519 GSXML.DISPLAY_TEXT_ELEM, GSXML.DISPLAY_TEXT_NAME,
1520 "Form Search");
1521 service.appendChild(displayItem);
1522
1523 displayItem = createNameValuePairElement(doc,
1524 GSXML.DISPLAY_TEXT_ELEM, GSXML.DISPLAY_TEXT_SUBMIT, "Search");
1525 service.appendChild(displayItem);
1526
1527 displayItem = createNameValuePairElement(doc,
1528 GSXML.DISPLAY_TEXT_ELEM, GSXML.DISPLAY_TEXT_DESCRIPTION,
1529 "Simple fielded search");
1530 service.appendChild(displayItem);
1531
1532 //create the <paramList>
1533 Element paramList = doc.createElement(
1534 GSXML.PARAM_ELEM+GSXML.LIST_MODIFIER);
1535
1536 // we ignore granularity to search at: it will always be
1537 // document and section level
1538 // we ignore casefolding: always on (that is, case is irrelevant)
1539 // we ignore document display order: always ranked
1540
1541 // Constructing the following:
1542 // <param default="100" name="maxDocs" type="integer">
1543 // <displayItem name="name">Maximum hits to return</displayItem>
1544 // </param>
1545 Element param = doc.createElement(GSXML.PARAM_ELEM);
1546
1547 Attr attribute = doc.createAttribute(GSXML.NAME_ATT);
1548 attribute.setValue(MAXDOCS);
1549 param.setAttributeNode(attribute);
1550
1551 attribute = doc.createAttribute(GSXML.DEFAULT_ATT);
1552 attribute.setValue("100");
1553 param.setAttributeNode(attribute);
1554
1555 attribute = doc.createAttribute(GSXML.TYPE_ATT);
1556 attribute.setValue(GSXML.PARAM_TYPE_INTEGER);
1557 param.setAttributeNode(attribute);
1558
1559 displayItem = createNameValuePairElement(doc,
1560 GSXML.DISPLAY_TEXT_ELEM, GSXML.DISPLAY_TEXT_NAME,
1561 "Maximum hits to return");
1562 param.appendChild(displayItem);
1563
1564 paramList.appendChild(param);
1565
1566 // Constructing the following:
1567 // <param name="simpleField" occurs="4" type="multi">
1568 // <displayItem name="name"></displayItem>
1569 //
1570 // <param name="query" type="string">
1571 // <displayItem name="name">Word or phrase </displayItem>
1572 // </param>
1573 //
1574 // <param default="allFields" name="fieldname" type="enum_single">
1575 // <displayItem name="name">in field</displayItem>
1576 //
1577 // <option name="docTitles">
1578 // <displayItem name="name">document titles</displayItem>
1579 // </option>
1580 // <option name="allTitles">
1581 // <displayItem name="name">document and section titles</displayItem>
1582 // </option>
1583 // <option name="fullText">
1584 // <displayItem name="name">full text</displayItem>
1585 // </option>
1586 // <option name="all">
1587 // <displayItem name="name">titles and full text</displayItem>
1588 // </option>
1589 // <option name="">
1590 // <displayItem name="name"></displayItem>
1591 // </option>
1592 // </param>
1593 // </param>
1594 Element rowOfParams = doc.createElement(GSXML.PARAM_ELEM);
1595 attribute = doc.createAttribute(GSXML.NAME_ATT);
1596 attribute.setValue(SIMPLEFIELD_ATT);
1597 rowOfParams.setAttributeNode(attribute);
1598
1599 // we want the row of controls to occur multiple times
1600 attribute = doc.createAttribute(GSXML.TYPE_ATT);
1601 attribute.setValue(GSXML.PARAM_TYPE_MULTI);
1602 rowOfParams.setAttributeNode(attribute);
1603
1604 attribute = doc.createAttribute(OCCURS_ATT);
1605 attribute.setValue("4"); // we want this row to occur 4 times
1606 rowOfParams.setAttributeNode(attribute);
1607
1608 // <param name="query" type="string">
1609 // <displayItem name="name">Word or phrase </displayItem>
1610 // </param>
1611 param = doc.createElement(GSXML.PARAM_ELEM);
1612
1613 attribute = doc.createAttribute(GSXML.NAME_ATT);
1614 attribute.setValue(QUERY);
1615 param.setAttributeNode(attribute);
1616
1617 attribute = doc.createAttribute(GSXML.TYPE_ATT);
1618 attribute.setValue(GSXML.PARAM_TYPE_STRING);
1619 param.setAttributeNode(attribute);
1620
1621 displayItem = createNameValuePairElement(doc,
1622 GSXML.DISPLAY_TEXT_ELEM, GSXML.DISPLAY_TEXT_NAME,
1623 "Word or phrase");
1624 param.appendChild(displayItem);
1625 rowOfParams.appendChild(param);
1626
1627 // <param default="allFields" name="fieldName" type="enum_single">
1628 // <displayItem name="name">in field</displayItem>
1629 param = doc.createElement(GSXML.PARAM_ELEM);
1630 attribute = doc.createAttribute(GSXML.NAME_ATT);
1631 attribute.setValue(FIELDNAME_ATT);
1632 param.setAttributeNode(attribute);
1633
1634 attribute = doc.createAttribute(GSXML.TYPE_ATT);
1635 attribute.setValue(GSXML.PARAM_TYPE_ENUM_SINGLE);
1636 param.setAttributeNode(attribute);
1637
1638 attribute = doc.createAttribute(GSXML.DEFAULT_ATT);
1639 attribute.setValue(ALL_FIELDS);
1640 param.setAttributeNode(attribute);
1641
1642 displayItem = createNameValuePairElement(doc,
1643 GSXML.DISPLAY_TEXT_ELEM, GSXML.DISPLAY_TEXT_NAME,
1644 "in field");
1645 param.appendChild(displayItem);
1646
1647 String[] searchFieldNames
1648 = {ALL_FIELDS, DOC_TITLES, ALL_TITLES, FULLTEXT};
1649 String[] searchFieldDisplay = {"all titles and full-text",
1650 "document titles only", "document and section titles",
1651 "full-text only"};
1652
1653 // for each fieldName create an option element and insert
1654 // the option into the enum_multi drop-down param:
1655 // <option name="fieldName">
1656 // <displayItem name="name">fieldName</displayItem>
1657 // </option>
1658 for(int i = 0; i < searchFieldNames.length; i++) {
1659 Element option = doc.createElement(GSXML.PARAM_OPTION_ELEM);
1660 attribute = doc.createAttribute(GSXML.NAME_ATT);
1661 attribute.setValue(searchFieldNames[i]);
1662 option.setAttributeNode(attribute);
1663
1664 displayItem = createNameValuePairElement(doc,
1665 GSXML.DISPLAY_TEXT_ELEM, GSXML.DISPLAY_TEXT_NAME,
1666 searchFieldDisplay[i]);
1667 option.appendChild(displayItem);
1668 param.appendChild(option); // add option to the drop-down box
1669 }
1670
1671 rowOfParams.appendChild(param);
1672 paramList.appendChild(rowOfParams);
1673 service.appendChild(paramList);
1674 }
1675
1676 /**
1677 * @return a GS3 describe response message for the requested service
1678 * of the given collection. DocumentContent/Metadata/StructureRetrieve
1679 * return nothing special except their names; browse (and any query)
1680 * return more complex XML responses.
1681 * All collections in this Digital Library (Fedora Repository) share
1682 * the same services, so this method returns the same as
1683 * describeService(serviceName).
1684 * @param collectionName - the name of the collection whose service is to
1685 * be described. It will be converted to a fedora collection pid, which is of
1686 * the form "greenstone:&lt;collectionName&gt;-collection".
1687 * @param serviceName - the name of the service in the collection which is to
1688 * be described. */
1689 public String describeCollectionService(String collectionName,
1690 String serviceName) {
1691 // collectionName can be ignored, because all services are FedoraGS3
1692 // services and are not unique to any particular (greenstone) collection.
1693 return describeService(serviceName);
1694 }
1695
1696 /** This method performs the implemented browse operation: allowing the
1697 * user to browse the titles of documents in the given collection by letter
1698 * and returning the results.
1699 * @param classifierIDs are the ids of the classifiers on which to browse. In
1700 * this case, the classifier indicates whether we browse titles by letter, or
1701 * browse (documents) by collection; and it is of the form &lt;CL(letter)&gt;.
1702 * @param collectionName is the name of the collection whose documents
1703 * starting with the given letter will be returned.
1704 * @return a GS3 DocumentStructureRetrieve response message which lists all
1705 * the documents that start with the letter indicated by parameter classifier.
1706 */
1707 public String browse(String collectionName, String[] classifierIDs)
1708 {
1709 Document doc = builder.newDocument();
1710 FedoraGS3RunException ex = null; //any RemoteException or UnsupportedEncodingException
1711
1712 // <classifierNodeList>
1713 Element classifierNodeList = doc.createElement(
1714 GSXML.CLASS_NODE_ELEM+GSXML.LIST_MODIFIER);
1715
1716 for(int i = 0; i < classifierIDs.length; i++) {
1717 // <classifierNode nodeID="classifierNum">
1718 Element requestedClassifierNode = doc.createElement(
1719 GSXML.CLASS_NODE_ELEM);
1720 Attr attribute = doc.createAttribute(GSXML.NODE_ID_ATT);
1721 attribute.setValue(classifierIDs[i]);
1722 requestedClassifierNode.setAttributeNode(attribute);
1723 classifierNodeList.appendChild(requestedClassifierNode);
1724
1725 // <nodeStructure>
1726 Element nodeStructure = doc.createElement(GSXML.NODE_STRUCTURE_ELEM);
1727 requestedClassifierNode.appendChild(nodeStructure);
1728
1729 // And one more time, the top level classifierNode:
1730 Element classifierNode = doc.createElement(GSXML.CLASS_NODE_ELEM);
1731 attribute = doc.createAttribute(GSXML.NODE_ID_ATT);
1732 attribute.setValue(classifierIDs[i]);
1733 classifierNode.setAttributeNode(attribute);
1734 nodeStructure.appendChild(classifierNode);
1735
1736 // Work out what we're browsing base on the classifierID's number
1737 // classifier CL1 = browse titles by letter;
1738 // classifier CL2 = browse by collection;
1739 //remove the CL prefix and obtain the number from the id:
1740 int classifierNum = Integer.parseInt(classifierIDs[i].replace("CL", ""));
1741 switch(classifierNum) {
1742 case 1:
1743 // we're going to loop to the end of the alphabet
1744 int num = 1;
1745 for(char ch = 'A'; ch <= 'Z'; ch++, num++) {
1746 // Retrieve the document structure for each subClassifierID:
1747 // all the documents that begin with its letter.
1748 String letter = String.valueOf(ch);
1749 try {
1750 String[] docPIDs = this.browseTitlesByLetter(
1751 collectionName, letter);
1752 if(docPIDs.length == 0) {
1753 continue; // skip letters that don't have any kids
1754 }
1755
1756 // <classifierNode nodeID="CL3.1">
1757 Element subClassifier = doc.createElement(
1758 GSXML.CLASS_NODE_ELEM);
1759 attribute = doc.createAttribute(GSXML.NODE_ID_ATT);
1760 attribute.setValue(classifierIDs[i]+"."+num);
1761 subClassifier.setAttributeNode(attribute);
1762 classifierNode.appendChild(subClassifier);
1763
1764 // append the <docNodes> for the docPIDs found as children
1765 // of subclassifier
1766 getStructureElement(subClassifier, docPIDs, DESCENDANTS);
1767 //CHILDREN); // for testing
1768 } catch(Exception e) {
1769 ex = new FedoraGS3RunException(e);
1770 ex.setSpecifics("requested portion of TOC file or "
1771 + "trouble with fielded search ");
1772 }
1773 }
1774 // No titles in this collection that start with a letter at all
1775 if(!classifierNode.hasChildNodes()) {
1776 // <classifierNode nodeID="CL1.0"> which we will equate with A-Z
1777 Element subClassifier = doc.createElement(
1778 GSXML.CLASS_NODE_ELEM);
1779 attribute = doc.createAttribute(GSXML.NODE_ID_ATT);
1780 attribute.setValue(classifierIDs[i]+"."+0); //
1781 subClassifier.setAttributeNode(attribute);
1782 classifierNode.appendChild(subClassifier);
1783 }
1784 break;
1785 case 2:
1786 break;
1787 default:
1788 ex = new FedoraGS3RunException( // cause is regular exception
1789 new Exception("Unknown classifier ID: " + classifierIDs[i]));
1790 }
1791 }
1792 Element responseMsg = createResponseMessage(doc, classifierNodeList, ex,
1793 GSXML.REQUEST_TYPE_DESCRIBE, collectionName+"/ClassifierBrowse");
1794 try{
1795 return FedoraCommons.elementToFormattedString(responseMsg);
1796 }catch(TransformerException e) {
1797 return FedoraGS3RunException.xmlToStringConversionFailureResponseMsg
1798 + " " + e;
1799 }
1800 }
1801
1802 /** This method performs something equivalent to a greenstone3
1803 * ClassifierBrowseMetadataRetrieve on the classifierNodeIDs
1804 * @param classNodeIDs array of classifierNode IDs of for which the metadata
1805 * needs to be returned.
1806 * @return a GS3 ClassifierBrowseMetadataRetrieve response message which
1807 * lists the metadata for all the classifierNodes passed as parameter.*/
1808 public String browseMetadataRetrieve(String[] classNodeIDs)
1809 {
1810 Document doc = this.builder.newDocument();
1811 // <classifierNodeList>
1812 Element classifierNodeList = doc.createElement(
1813 GSXML.CLASS_NODE_ELEM+GSXML.LIST_MODIFIER);
1814
1815 // create <classifierNode><metadataList><metadata>s
1816 // </metadataList></classifierNode> for all letters of alphabet
1817 for(int i = 0; i < classNodeIDs.length; i++) {
1818 // strip ID of everything before the first '.' (i.e. remove "CL#.")
1819 int index = classNodeIDs[i].indexOf('.');
1820 String subClassifierNumber = classNodeIDs[i].substring(index+1);
1821 int subClassifierNum = Integer.parseInt(subClassifierNumber);
1822 String classifierName = "";
1823 if(subClassifierNum == 0) { // no document titles started with a letter
1824 classifierName = "A-Z";
1825 } else {
1826 char letter = (char)('A' + subClassifierNum - 1); // A = 1
1827 classifierName = String.valueOf(letter);
1828 }
1829
1830 // <classifierNode nodeID="CL#.subNum">
1831 Element classifierNode = doc.createElement(GSXML.CLASS_NODE_ELEM);
1832 Attr attribute = doc.createAttribute(GSXML.NODE_ID_ATT);
1833 attribute.setValue(classNodeIDs[i]);
1834 classifierNode.setAttributeNode(attribute);
1835
1836 // <metadataList>
1837 Element metadataList = doc.createElement(
1838 GSXML.METADATA_ELEM+GSXML.LIST_MODIFIER);
1839
1840 // at least one metadata element: that of the title of this
1841 // classifierNode:
1842 // <metadata name="Title">letter</metadata>
1843 Element metadata = this.createNameValuePairElement(doc,
1844 GSXML.METADATA_ELEM, "Title", classifierName);
1845
1846 // now connect up everything
1847 metadataList.appendChild(metadata);
1848 classifierNode.appendChild(metadataList);
1849 classifierNodeList.appendChild(classifierNode);
1850 }
1851
1852 Element responseMsg = createResponseMessage(doc, classifierNodeList, null,
1853 GSXML.REQUEST_TYPE_PROCESS, //collName +
1854 "ClassifierBrowseMetadataRetrieve");
1855 try{
1856 return FedoraCommons.elementToFormattedString(responseMsg);
1857 }catch(TransformerException e) {
1858 return FedoraGS3RunException.xmlToStringConversionFailureResponseMsg
1859 + " " + e;
1860 }
1861 }
1862
1863 /** @return a newly created element of the following format:
1864 * &lt;classifier content="somecontent" name="CL+num"&gt;
1865 * &lt;displayItem name="name"&gt;someClassifierName&lt;/displayItem&gt;
1866 * &lt;displayItem name="description"&gt;Browse by classifier name&lt;/displayItem&gt;
1867 * &lt;/classifier&gt;
1868 * @param doc - the document used to create the element
1869 * @param content - value of the content attribute
1870 * @param classifierNum - the number suffixed to the CL, together forming
1871 * the classifier Node's ID
1872 * @param displayNameVal is the bodytext of a named displayItem element
1873 * @param displayDescrVal is the bodytext of a displayItem element with
1874 * description */
1875 protected Element createClassifierElement(Document doc, String content,
1876 int classifierNum, String displayNameVal, String displayDescrVal)
1877 {
1878 final String CL = "CL";
1879 Element classifier = doc.createElement(GSXML.CLASSIFIER_ELEM);
1880 // content attribute
1881 Attr att = doc.createAttribute(GSXML.CLASSIFIER_CONTENT_ATT);
1882 att.setValue(content);
1883 classifier.setAttributeNode(att);
1884 // name attribute
1885 att = doc.createAttribute(GSXML.NAME_ATT);
1886 att.setValue(CL + classifierNum);
1887 classifier.setAttributeNode(att);
1888
1889 // now create the displayItem children for classifier:
1890 // <displayItem name="name">#letter</displayItem>
1891 // <displayItem name="description">
1892 //Browse titles starting with #letter</displayItem>
1893 Element displayItem = createNameValuePairElement(doc,
1894 GSXML.DISPLAY_TEXT_ELEM, GSXML.DISPLAY_TEXT_NAME, displayNameVal);
1895 classifier.appendChild(displayItem);
1896 displayItem = createNameValuePairElement(doc, GSXML.DISPLAY_TEXT_ELEM,
1897 GSXML.DISPLAY_TEXT_DESCRIPTION, displayDescrVal);
1898 classifier.appendChild(displayItem);
1899
1900 return classifier;
1901 }
1902
1903
1904 /** @return a newly created element of the following format:
1905 * &lt;elementName name="somename"&gt;"some display value"&lt;/elementName&gt;
1906 * @param doc - the document used to create the element
1907 * @param elementName - the tag name
1908 * @param name - value of attribute name
1909 * @param value - the body text of the element */
1910 protected Element createNameValuePairElement(Document doc, String elementName,
1911 String name, String value) {
1912 // <elementName name="somename">"some display value"</elementName>
1913 Element element = doc.createElement(elementName);
1914 Attr attribute = doc.createAttribute(GSXML.NAME_ATT);
1915 attribute.setValue(name);
1916 element.setAttributeNode(attribute);
1917
1918 element.appendChild(doc.createTextNode(value));
1919 return element;
1920 }
1921
1922 /**
1923 * @param collection is the collection to search in
1924 * @param query is the query term to search for. It won't specify the
1925 * indexed field to search in, which will mean that GSearch will
1926 * search all default indexed fields.
1927 * @param maxDocs is the maximum number of results to return (which
1928 * at present we consider equivalent to FedoraGSearch's hitpageSize).
1929 */
1930 public String[] textQuery(String collection, String query,
1931 int maxDocs)
1932 throws Exception
1933 {
1934 // no need to search there is no query or query is empty spaces
1935 if(query.trim().equals(""))
1936 return new String[]{};
1937
1938 // QUERY value won't specify indexed field to search, Fedora
1939 // Gsearch will take that as meaning all default indexed fields.
1940 // Params to search() method below: string of fielded query terms;
1941 // hitpageStart, hitpageEnd, snippetsMax (leave that 0)
1942 query = query + " " + "PID" + COLON + GREENSTONE;
1943
1944 String searchResult = this.fedoraGSearch.search(query, 1, maxDocs, 0);
1945 // now we have the XML returned by FedoraGSearch, get the pids
1946 // of the documents returned (if any)
1947 String[] pids = this.fedoraGSearch.getPIDsFromSearchResult(
1948 collection, searchResult);
1949 return pids;
1950 }
1951
1952 /**
1953 * This method performs a fieldquery, searching for x number of phrases
1954 * in each of the 4 indexed fields.
1955 * @param collection is the collection to search in
1956 * @param nameValParamsMap is a Map of several(key, value) entries,
1957 * 4 of which we're concerned with here:
1958 * - the keys are ALL_FIELDS, DOC_TITLES, ALL_TITLES, FULLTEXT
1959 * - the values are a comma separated list of terms (phrases or single
1960 * words) to search that field in. There may be more than 1 or
1961 * there may be none (in which case there may be N empty values or
1962 * spaces separated by commas).
1963 * @param maxDocs is the maximum number of results to return (which
1964 * at present we consider equivalent to FedoraGSearch's hitpageSize).
1965 * */
1966 public String[] fieldQuery(String collection, Map nameValParamsMap,
1967 int maxDocs)
1968 throws Exception
1969 {
1970 // we're going to maintain a list of UNIQUE pids that were returned
1971 // in search results. Hence we use Set:
1972 java.util.Set set = new java.util.HashSet();
1973
1974 // (1) Use Fedora's search to search document titles, if they were
1975 // specified:
1976 String[] docTitlepids = {};
1977
1978 String docTitleTerms = (String)nameValParamsMap.get(DOC_TITLES);
1979 if(docTitleTerms != null) { // no doc titles may have been specified
1980 String[] phrases = docTitleTerms.split(COMMA);
1981
1982 // search the individual phrases first:
1983 for(int i = 0; i < phrases.length; i++) {
1984 if(phrases.equals("") || phrases.equals(" "))
1985 continue; //skip when there are no terms
1986 docTitlepids = this.searchDocumentTitles(
1987 collection, phrases[i], false);
1988 for(int j = 0; j < docTitlepids.length; j++)
1989 set.add(docTitlepids[j]);
1990 }
1991 }
1992 // (2) use FedoraGSearch to search doc AND section titles, and
1993 // fulltext (in case these were specified in nameValParamsMap):
1994 String searchResult = this.fedoraGSearch.search(
1995 nameValParamsMap, 1, maxDocs);
1996
1997 String[] pids = this.fedoraGSearch.getPIDsFromSearchResult(
1998 collection, searchResult);
1999
2000 for(int i = 0; i < pids.length; i++)
2001 set.add(pids[i]);
2002
2003 pids = null;
2004 pids = new String[set.size()];
2005 set.toArray(pids); // unique pids
2006 return pids;
2007 }
2008
2009 /** @return a String representing Greenstone3 XML for a query process
2010 * response returning the results for the query denoted by parameter
2011 * nameValParamsMap.
2012 * @param nameValParamsMap is a Hashmap of name and value pairs for all the
2013 * query field data values. The names match the field names that
2014 * describeCollectionService() would have returned for the query service.
2015 * @param collection is the name of the collection
2016 * @param service is the name of the query service
2017 * This method is only ever called when any of the services in the digital
2018 * library described themselves as type=query. Therefore any digital
2019 * libraries that have no query services, can just return emtpy message
2020 * strings (or even "") since this method will never be called on them
2021 * anyway. */
2022 public String query(String collection, String service,
2023 Map nameValParamsMap)
2024 {
2025 FedoraGS3RunException ex = null;
2026 // (1) obtain the requested number of maximum result documents
2027 int maxDocs = 100;
2028 try{
2029 maxDocs = Integer.parseInt((String)nameValParamsMap.get(MAXDOCS));
2030 } catch(NumberFormatException e) {
2031 maxDocs = 100;
2032 }
2033
2034 String pids[] = {};
2035 // (2) for Textquery, we simply search ALL_FIELDS using FedoraGSearch
2036 if(service.equals("TextQuery")) {
2037 try {
2038 // get the Query field:
2039 String query = (String)nameValParamsMap.get(QUERY);
2040 pids = textQuery(collection, query, maxDocs);
2041 }
2042 catch(Exception e) {
2043 LOG.error("Error in TextQuery processing: " + e);
2044 ex = new FedoraGS3RunException(
2045 "When trying to use FedoraGenericSearch for a TextQuery", e);
2046
2047 }
2048 } else { // (3) FieldQuery
2049 // first get the comma-separated lists
2050 String listOfFieldNames = (String)nameValParamsMap.get(FIELDNAME_ATT);
2051 String listOfSearchTerms = (String)nameValParamsMap.get(QUERY);
2052 // both are comma separated lists, so split both on 'comma'
2053 String[] fieldNames = listOfFieldNames.split(COMMA);
2054 String[] searchTerms = listOfSearchTerms.split(COMMA);
2055
2056 // In the fieldNames and searchTerms lists of nameValParamsMap,
2057 // each searchTerm element was matched with its correspondingly
2058 // indexed fieldName.
2059 // A new map is going to reorganise this, by putting all terms
2060 // for a particular fieldName together in a comma separated list
2061 // and associating that with the fieldName. I.e. (key, value) ->
2062 // (fieldName, comma-separated list of all terms in that field)
2063 Map map = new HashMap();
2064 for(int i = 0; i < searchTerms.length; i++) {
2065 // there may be fewer searchTerms than fieldNames (since some
2066 // fieldNames may have been left empty), so loop on searchTerms
2067 if(map.containsKey(fieldNames[i])) { // fieldName is already
2068 // in the list, so append comma with new value
2069 String termsList = (String)map.get(fieldNames[i]);
2070 termsList = termsList + COMMA + searchTerms[i];
2071 map.put(fieldNames[i], termsList);
2072 } else { // this is the first time this fieldName occurred
2073 // just put the fieldName with searchTerm as-is
2074 map.put(fieldNames[i], searchTerms[i]);
2075 }
2076 }
2077
2078 try {
2079 // For fieldquery, we search on all the fieldNames specified
2080 // - if DOC_TITLES is specified then we use Fedora's search
2081 // - for all other fieldNames specified, we use FedoraGSearch
2082 pids = fieldQuery(collection, map, maxDocs);
2083 }
2084 catch(Exception e) {
2085 LOG.error("Error in FieldQuery processing: " + e);
2086 ex = new FedoraGS3RunException(
2087 "When trying to use FedoraGenericSearch for a FieldQuery", e);
2088 }
2089 }
2090
2091 // Build Greenstone XML Query response message for from
2092 // the pids (which should be document identifiers)
2093 Document doc = builder.newDocument();
2094 // <metadataList><metadata name="numDocsMatched" value="n" />
2095 // </metadataList>
2096 Element metadataList = doc.createElement(
2097 GSXML.METADATA_ELEM+GSXML.LIST_MODIFIER);
2098 Element metadata = doc.createElement(GSXML.METADATA_ELEM);
2099
2100 Attr attribute = doc.createAttribute(GSXML.NAME_ATT);
2101 attribute.setValue(NUM_DOCS_MATCHED);
2102 metadata.setAttributeNode(attribute);
2103
2104 attribute = doc.createAttribute(GSXML.VALUE_ATT);
2105 attribute.setValue(Integer.toString(pids.length));
2106 metadata.setAttributeNode(attribute);
2107
2108 metadataList.appendChild(metadata);
2109
2110 // <documentNodeList>
2111 // <documentNode nodeID="HASHac0a04dd14571c60d7fbfd.4.2"
2112 // docType='hierarchy' nodeType="leaf" />
2113 // ...
2114 // ...
2115 // </documentNodeList>
2116 Element docNodeList = doc.createElement(
2117 GSXML.DOC_NODE_ELEM+GSXML.LIST_MODIFIER);
2118 // for each
2119 for(int i = 0; i < pids.length; i++) {
2120 Element docNode = doc.createElement(GSXML.DOC_NODE_ELEM);
2121 attribute = doc.createAttribute(GSXML.NODE_ID_ATT);
2122 attribute.setValue(pids[i]);
2123 docNode.setAttributeNode(attribute);
2124
2125 attribute = doc.createAttribute(GSXML.DOC_TYPE_ATT);
2126 attribute.setValue("hierarchy");
2127 docNode.setAttributeNode(attribute);
2128
2129 attribute = doc.createAttribute(GSXML.NODE_TYPE_ATT);
2130 attribute.setValue("root");
2131 docNode.setAttributeNode(attribute);
2132 docNodeList.appendChild(docNode);
2133 }
2134
2135 Element responseMsg = createResponseMessage(doc, docNodeList, ex,
2136 GSXML.REQUEST_TYPE_PROCESS, service);
2137 try{
2138 return FedoraCommons.elementToFormattedString(responseMsg);
2139 }catch(TransformerException e) {
2140 return FedoraGS3RunException.xmlToStringConversionFailureResponseMsg
2141 + " " + e;
2142 }
2143 }
2144
2145 public static void main(String args[]) {
2146 try{
2147 // testing default constructor
2148 //FedoraGS3Connection con = new FedoraGS3Connection();
2149
2150 // testing constructor that takes properties file to show initial
2151 // fedora server values
2152 java.io.File propertyFilename
2153 = new java.io.File("fedoraGS3.properties");
2154 FedoraGS3Connection con = new FedoraGS3Connection(propertyFilename);
2155
2156 // DESCRIBE: serviceList, collectionList
2157 System.out.println("serviceList:\n" + con.getServiceList());
2158
2159 System.out.println("collectionList:\n" + con.getCollectionList());
2160
2161 String[] colPIDs = con.getCollections();
2162 String[] collectionNames = con.getCollectionNames(con.getCollections());
2163
2164
2165 for(int i = 0; i < collectionNames.length; i++) {
2166 System.out.println("Describing collections:\n");
2167 System.out.println(con.describeCollection(collectionNames[i]));
2168 System.out.println("Describing collection services:\n"
2169 + con.describeCollectionServices(collectionNames[i]));
2170 }
2171
2172 String[] serviceNames = con.getServiceNames();
2173 for(int i = 0; i < serviceNames.length; i++) {
2174 System.out.println("Describing " + serviceNames[i] + ":\n"
2175 + con.describeCollectionService("demo", serviceNames[i]));
2176 }
2177
2178
2179 // TRYING OUT SPECIAL top-level document metadata retrieval (DLS, DC)
2180 // along with EX of the top-level document:
2181 System.out.println("\nGET META for greenstone:gs2mgdemo-HASH01d667303fe98545f03c14ae:");
2182 System.out.println(con.getDocumentMetadata(new String[]{"greenstone:gs2mgdemo-HASH01d667303fe98545f03c14ae"}));
2183
2184
2185 String[] docIDs = con.getCollectionDocs(colPIDs[0]);
2186 System.out.println("\nGET CONTENT:");
2187 for(int i = 0; i < docIDs.length; i++) {
2188 System.out.println(con.getContent(docIDs[i]));
2189 }
2190
2191 System.out.println("\nGET META:");
2192 for(int i = 0; i < docIDs.length; i++) {
2193 System.out.println(con.getDocumentMetadata(docIDs[i]));
2194 }
2195
2196 String[] getTitlesFor = {
2197 "greenstone:gs2mgdemo-HASH01d667303fe98545f03c14ae",
2198 "greenstone:gs2mgdemo-HASHa568bac1d8d7bd12a0938b",
2199 "greenstone:gs2mgdemo-HASHa568bac1d8d7bd12a0938b-1",
2200 "greenstone:gs2mgdemo-HASH01d667303fe98545f03c14ae-1.7",
2201 "greenstone:gs2mgdemo-HASHa568bac1d8d7bd12a0938b-1.5.1"
2202 };
2203
2204 // first let's display the regular meta for top-level docs and
2205 // their sections
2206 for(int i = 0; i < getTitlesFor.length; i++) {
2207 System.out.println(con.getDocumentMetadata(getTitlesFor[i]));
2208 }
2209
2210 System.out.println("\nTitles are:");
2211 System.out.println(con.getTitleMetadata(getTitlesFor));
2212
2213 System.out.println("\nGET STRUCTURE:");
2214 for(int i = 0; i < docIDs.length; i++) {
2215 System.out.println(con.getChildren(docIDs[i]));
2216 System.out.println(con.getDocumentStructure(docIDs[i]));
2217 }
2218
2219 // TEST ERROR CASES:
2220 System.out.println("\nTESTING ERROR CASES");
2221 System.out.println(con.getContent("greenstone:demo-pinky"));
2222 String[] errorCases = { "greenstone:demo-HASH23d1019b589e2ef6a680e3-1.5.1.5",
2223 "greenstone:demo-pinky" };
2224 System.out.println(con.getContent(errorCases));
2225 System.out.println(con.getDocumentMetadata(errorCases));
2226 System.out.println(con.getDocumentStructure(errorCases));
2227
2228 System.out.println("\nCLASSIFIER BROWSE");
2229 System.out.println(con.browse("gs2mgdemo", //"ClassifierBrowse",
2230 new String[]{"CL1"}));
2231
2232 System.out.println("\nCLASSIFIER BROWSE METADATA RETRIEVE");
2233 String[] classNodeIDs = new String[26];
2234 for(int i = 0; i < classNodeIDs.length; i++) {
2235 int subClassifierNum = i + 1;
2236 classNodeIDs[i] = "CL1." + subClassifierNum;
2237 }
2238 System.out.println(con.browseMetadataRetrieve(//"gs2mgdemo",
2239 classNodeIDs));
2240
2241 System.out.println("Testing query services");
2242 System.out.println("TEXT QUERY:");
2243 Map formControlValsMap = new HashMap();
2244 formControlValsMap.put(MAXDOCS, "100");
2245 formControlValsMap.put(QUERY, "snails");
2246 String searchResponse
2247 = con.query("gs2mgdemo", "TextQuery", formControlValsMap);
2248 System.out.println(searchResponse);
2249
2250 System.out.println("FIELD QUERY:");
2251 formControlValsMap.clear();
2252 formControlValsMap.put(MAXDOCS, "100");
2253 formControlValsMap.put(QUERY, "interview,Gender equality,cyclone");
2254 formControlValsMap.put(FIELDNAME_ATT,
2255 "allFields,docTitles,allFields,allFields");
2256 searchResponse
2257 = con.query("gs2mgdemo", "FieldQuery", formControlValsMap);
2258 System.out.println(searchResponse);
2259
2260 System.exit(0);
2261 }catch(Exception e) {
2262 JOptionPane.showMessageDialog(
2263 null, e, "Error", JOptionPane.ERROR_MESSAGE);
2264 //System.err.println("ERROR: " + e);
2265 e.printStackTrace();
2266 }
2267 }
2268}
Note: See TracBrowser for help on using the repository browser.