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

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

Browse takes a list of classifierIDs, not a single one.

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