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

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

gsearchWSDLSuffix rather than the entire gsearchWSDLURL is now written to the properties file. Otherwise, the program always ends up reading whatever wsdlURL was in the file for gsearch, rather than using the baseURL of Fedora

File size: 91.9 KB
Line 
1/**
2 *#########################################################################
3 * FedoraGS3Connection.java - works with the demo-client for Greenstone 3,
4 * of the Greenstone digital library suite from the New Zealand Digital
5 * Library Project at the * University of Waikato, New Zealand.
6 * <BR><BR>
7 * Copyright (C) 2008 New Zealand Digital Library Project
8 * <BR><BR>
9 * This program is free software; you can redistribute it and/or modify
10 * it under the terms of the GNU General Public License as published by
11 * the Free Software Foundation; either version 2 of the License, or
12 * (at your option) any later version.
13 * <BR><BR>
14 * This program is distributed in the hope that it will be useful,
15 * but WITHOUT ANY WARRANTY; without even the implied warranty of
16 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17 * GNU General Public License for more details.
18 *########################################################################
19 */
20
21package org.greenstone.fedora.services;
22
23
24import java.io.StringReader;
25
26import org.apache.log4j.Logger;
27import org.greenstone.fedora.services.FedoraGS3Exception.AuthenticationFailedException;
28import org.greenstone.fedora.services.FedoraGS3Exception.CancelledException;
29import org.greenstone.fedora.services.FedoraGS3Exception.FedoraGS3RunException;
30import org.greenstone.fedora.services.FedoraGS3Exception.NotAFedoraServerException;
31import org.greenstone.gsdl3.util.GSXML;
32import org.w3c.dom.Document;
33import org.w3c.dom.Element;
34import org.w3c.dom.Attr;
35import org.w3c.dom.Text;
36import org.w3c.dom.NodeList;
37import org.w3c.dom.Node;
38import org.xml.sax.InputSource;
39
40import java.io.File;
41import java.util.HashMap;
42import java.util.Properties;
43import java.util.Map;
44
45import javax.swing.JOptionPane;
46
47import org.xml.sax.SAXException;
48import java.io.UnsupportedEncodingException;
49import java.io.IOException;
50import javax.net.ssl.SSLHandshakeException;
51import java.net.ConnectException;
52import java.net.MalformedURLException;
53import java.rmi.RemoteException;
54import javax.xml.parsers.ParserConfigurationException;
55import javax.xml.transform.TransformerException;
56
57/**
58 * Class that extends FedoraConnection in order to be able to use
59 * Fedora's web services to retrieve the specific datastreams of
60 * Greenstone documents stored in Fedora's repository. This class
61 * provides methods that convert those datastreams into Greenstone3
62 * XML response messages which are returned.
63 * @author ak19
64*/
65public class FedoraGS3Connection
66 extends FedoraConnection implements FedoraToGS3Interface,
67 FedoraToGS3Interface.Constants
68{
69 /** The logging instance for this class */
70 private static final Logger LOG = Logger.getLogger(
71 FedoraGS3Connection.class.getName());
72
73 /** 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, they 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 "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");
665 }
666
667 Element responseMsg = createResponseMessage(doc, docNodeList, ex,
668 GSXML.REQUEST_TYPE_PROCESS, "DocumentMetadataRetrieve");
669 try{
670 return FedoraCommons.elementToFormattedString(responseMsg);
671 } catch(TransformerException e) {
672 return FedoraGS3RunException.xmlToStringConversionFailureResponseMsg
673 + " " + e;
674 }
675 }
676
677 /** Method that takes a new DOM document, as well as an identifier of either
678 * a document or document section and returns a documentNode element containing
679 * the title metadata for it:
680 * &lt;documentNode nodeID="docID"&gt;&lt;metadataList&gt;
681 * &lt;metadata name="Title"&gt;sometitle&lt;/metadata&gt;
682 * &lt;/metadataList&gt;&lt;/documentNode&gt;
683 * @return documentNode containing the metadata for the collection or
684 * document given by parameter ID
685 * @param docID denotes the id of a document or a document section, so id
686 * is either a document-pid or it's of the form documentpid-sectionNumber */
687 protected Element getTitleMetadata(Document doc, String docID)
688 throws RemoteException, UnsupportedEncodingException,
689 SAXException, IOException
690 {
691 // Returns a docNode element of the following form:
692 // <documentNode nodeID="docID">
693 // <metadataList><metadata name="Title">sometitle</metadata></metadataList>
694 // </documentNode>
695
696 // <documentNode nodeID="docID">
697 Element docNode = doc.createElement(GSXML.DOC_NODE_ELEM);
698 Attr attribute = doc.createAttribute(GSXML.NODE_ID_ATT);
699 attribute.setValue(docID);
700 docNode.setAttributeNode(attribute);
701
702 // <metadataList>
703 Element metaList = doc.createElement(
704 GSXML.METADATA_ELEM+GSXML.LIST_MODIFIER);
705 // <metadata name="Title">
706 Element metadata = doc.createElement(GSXML.METADATA_ELEM);
707 // if we connect it all up (append children), we can immediately add
708 // the name attribute into the metadata element:
709 metaList.appendChild(metadata);
710 docNode.appendChild(metaList);
711 metadata.setAttribute(GSXML.NAME_ATT, TITLE); // immediately add attribute
712
713 String title = "";
714 String sectionID = getSectionIDFromDocID(docID);
715 String docPID = getDocPIDFromDocID(docID);
716
717 // check if title of toplevel document is requested
718 if(sectionID.equals(""))
719 title = this.getDocTitle(docPID);
720 else { // title of document section
721 title = this.getSectionTitle(docPID, sectionID);
722 }
723
724 metadata.appendChild(doc.createTextNode(title));
725
726 return docNode;
727 }
728
729
730 /** @return the documentStructure of the document or section given by docID.
731 * The structure is returned in the XML format of a Greenstone3
732 * DocumentStructureRetrieve response message. This method returns the entire
733 * subSection of the docID (that is, all descendants included).
734 * @param docID the identifier for the document whose structure is required.
735 * This is of the format "greenstone:&lt;collectionName&gt;-&lt;docPID&gt;"
736 * OR "greenstone:&lt;collectionName&gt;-&lt;docPID&gt;-&lt;sectioNumber&gt;"
737 * where "greenstone:&lt;collectionName&gt;-&lt;docPID&gt;-1" is the same as
738 * "greenstone:&lt;collectionName&gt;-&lt;docPID&gt;" and will return the
739 * same response */
740 public String getDocumentStructure(String docID) {
741 return getStructure(new String[]{docID}, DESCENDANTS);
742 }
743
744 /** @return a view of the structure of the document or section given by docID
745 * which contains only the section and its direct children. This structure is
746 * returned in the XML format of a Greenstone3 DocumentStructureRetrieve
747 * response message.
748 * @param docID the identifier for the document whose structure is required.
749 * This is of the format "greenstone:&lt;collectionName&gt;-&lt;docPID&gt;"
750 * OR "greenstone:&lt;collectionName&gt;-&lt;docPID&gt;-&lt;sectioNumber&gt;"
751 * where "greenstone:&lt;collectionName&gt;-&lt;docPID&gt;-1" is the same as
752 * "greenstone:&lt;collectionName&gt;-&lt;docPID&gt;" and will return the
753 * same response */
754 public String getChildren(String docID) {
755 return getStructure(new String[]{docID}, CHILDREN);
756 }
757
758 /** @return the documentStructure of the documents or sections given by docIDs.
759 * The structure is returned in the XML format of a Greenstone3
760 * DocumentStructureRetrieve response message. This method returns the entire
761 * subSection of each docID (that is, all descendants included).
762 * @param docIDs is an array of identifiers for the documents whose structures
763 * are required.
764 * This is of the format "greenstone:&lt;collectionName&gt;-&lt;docPID&gt;"
765 * OR "greenstone:&lt;collectionName&gt;-&lt;docPID&gt;-&lt;sectioNumber&gt;"
766 * where "greenstone:&lt;collectionName&gt;-&lt;docPID&gt;-1" is the same as
767 * "greenstone:&lt;collectionName&gt;-&lt;docPID&gt;" and will return the
768 * same response */
769 public String getDocumentStructure(String[] docIDs) {
770 return getStructure(docIDs, DESCENDANTS);
771 }
772
773 /** @return the documentStructure of the documents or sections given by docIDs
774 * but only the sections and their children (not any further descendants).
775 * The structure is returned in the XML format of a Greenstone3
776 * DocumentStructureRetrieve response message.
777 * @param docIDs the identifiers for the documents whose structures are
778 * required. The docids are of the format "greenstone:&lt;collectionName&gt;-&lt;docPID&gt;"
779 * OR "greenstone:&lt;collectionName&gt;-&lt;docPID&gt;-&lt;sectioNumber&gt;"
780 * where "greenstone:&lt;collectionName&gt;-&lt;docPID&gt;-1" is the same as
781 * "greenstone:&lt;collectionName&gt;-&lt;docPID&gt;" and will return the
782 * same response */
783 public String getChildren(String[] docIDs) {
784 return getStructure(docIDs, CHILDREN);
785 }
786
787 /**
788 * Returns a greenstone3 DocumentStructureRetrieve XML response message
789 * containing the document structures for the given docIDs.
790 * Similar to FedoraConnection.getTOC(), but instead of fedora formatted XML,
791 * greenstone formatted XML is returned. The requested section of the table
792 * of contents (TOC) for a document is converted into the greenstone3 xml
793 * format that is returned upon DocumentStructureRetrieve requests.
794 * @param docIDs the documentIDs for which the section's structure is returned;
795 * where a docID is either a fedora pid &lt;docPID&gt; or &lt;docPID&gt;-&lt;sectionNumber&gt;.
796 * @param levels - either CHILDREN or DESCENDANTS.
797 * CHILDREN returns only the first-level descendants (children) of the
798 * requested document sections indicated by docIDs.
799 * DESCENDANTS returns all descendants of all the document-sections denoted by
800 * docIDs.
801 * @return a greenstone3 DocumentStructureRetrieve XML response message in
802 * String format with the structure of the docIDs requested.
803 */
804 protected String getStructure(String[] docIDs, int levels)
805 {
806 Document doc = builder.newDocument();
807 FedoraGS3RunException ex = null;
808 // <documentNodeList>
809 Element docNodeList = doc.createElement(
810 GSXML.DOC_NODE_ELEM+GSXML.LIST_MODIFIER);
811
812 try{
813 // append the <documentNodes> for the docIDs
814 // to the docNodeList
815 getStructureElement(docNodeList, docIDs, levels);
816 } catch(Exception e) {
817 ex = new FedoraGS3RunException(e);
818 ex.setSpecifics("(requested portion of) TOC datastream");
819 }
820 // insert our <documentNodeList> into a GS3 response message
821 Element responseMsg = createResponseMessage(doc, docNodeList, ex,
822 GSXML.REQUEST_TYPE_PROCESS, "DocumentStructureRetrieve");
823 try{
824 return FedoraCommons.elementToFormattedString(responseMsg);
825 } catch(TransformerException e) {
826 return FedoraGS3RunException.xmlToStringConversionFailureResponseMsg
827 + " " + e;
828 }
829 }
830
831 /** Given a &lt;documentNodeList&gt; portion of a greenstone3
832 * DocumentStructureRetrieve XML response message, this method will populate
833 * it with the &lt;documentNodes&gt; that represent the structure of the given docIDs.
834 * @param docNodeList is a &lt;documentNodeList&gt; to which &lt;documentNodes&gt; of
835 * the doc structures are appended.
836 * @param docIDs the documentIDs for which the section's structure is returned;
837 * where a docID is either a fedora pid &lt;docPID&gt; or &lt;docPID&gt;-&lt;sectionNumber&gt;.
838 * @param levels - either CHILDREN or DESCENDANTS.
839 * CHILDREN returns only the first-level descendants (children) of the
840 * requested document sections indicated by docIDs.
841 * DESCENDANTS returns all descendants of all the document-sections denoted by
842 * docIDs.
843 */
844 protected void getStructureElement(Element docNodeList,
845 String[] docIDs, int levels)
846 throws RemoteException, UnsupportedEncodingException, SAXException,
847 IOException
848 {
849 // process each docID
850 for(int i = 0; i < docIDs.length; i++) {
851 // work out the document's fedora PID and section ID
852 String sectionID = getSectionIDFromDocID(docIDs[i]);
853 String docPID = getDocPIDFromDocID(docIDs[i]);
854
855 // get the required section, along with children or descendants
856 Element srcDocElement = null;
857 if(levels == CHILDREN) // get the requested section with its children
858 srcDocElement = this.getChildrenOfSectionXML(docPID, sectionID);
859 else // levels == DESCENDANTS, get the section with all its descendants
860 srcDocElement = this.getSubsectionXML(docPID, sectionID);
861
862 // copy-and-convert that structure into a structure format for GS3
863 Element docNode = getStructure(docNodeList.getOwnerDocument(),
864 docIDs[i], docPID, srcDocElement);
865
866 // add it to our list of documentNodes
867 docNodeList.appendChild(docNode);
868 }
869 }
870
871 /**
872 * Takes the portion of the XML document outlining the structure of the
873 * document (section)--in the format this is stored in Fedora--and returns
874 * Greenstone 3 DOM XML format for outlining document structure.
875 * @return a &lt;documentNode&gt; element that contains a greenstone3
876 * DocumentStructureRetrieve XML corresponding to the parameter Element section
877 * (which is in fedora XML), for the document indicated by docID.
878 * @param requestingDocID is the identifier of the document for which the
879 * structure was requested. It's this document's children or descendants that
880 * will be returned. Note that this is not always the same as (clear from)
881 * parameter docID.
882 * @param docID is the documentID for which the section's structure is
883 * returned where docID = "docPID-sectionNumber".
884 * @param section - the fedora section XML that is being mirrored in
885 * greenstone3 format.
886 */
887 protected Element getStructure(Document doc, String requestingDocID,
888 String docID, Element section)
889 {
890 // we want to mirror the section's DOM (given in fedora XML) in
891 // greenstone3's XML for a DocumentStructureRetrieve response.
892
893 // <documentNode nodeID="docID"> - the docNode on which a structure retrieve
894 // is being performed
895 Element docNode = doc.createElement(GSXML.DOC_NODE_ELEM);
896 Attr attribute = doc.createAttribute(GSXML.NODE_ID_ATT);
897 attribute.setValue(requestingDocID); //requestingDocID.replace(HYPHEN+SECTION, "")
898 docNode.setAttributeNode(attribute);
899
900 // <nodeStructure>
901 Element nodeStructure = doc.createElement(GSXML.NODE_STRUCTURE_ELEM);
902
903 // <documentNode nodeID="docID" docType="hierarchy" nodeType="root">
904 Element rootNode = createDocNodeFromSubsection(doc, section, docID);
905
906 // fills in the subtree of the rootNode in our nodeStructure element
907 createDocStructure(doc, section, rootNode, docID);
908 //where section represents the root section
909
910 nodeStructure.appendChild(rootNode);
911 docNode.appendChild(nodeStructure);
912 return docNode;
913 }
914
915 /** Recursive method that creates a documentStructure mirroring parameter
916 * section, starting from parameter parent down to all descendants
917 * @param section is the XML &lt;Section&gt; in the fedora repository's TOC
918 * for the docPID whose substructure is to be mirrored
919 * @param parent is the XML documentNode in the greenstone repository whose
920 * descendants created by this method will correspond to the descendants of
921 * parameter section.
922 * @param doc is the document containing the parent;
923 * @param docPID is the prefix of all nodeIDs in the parent's structure
924 */
925 protected void createDocStructure(
926 Document doc, Element section, Element parent, String docPID)
927 {
928 // get the section's children (if any)
929 NodeList children = section.getChildNodes();
930 for(int i = 0; i < children.getLength(); i++) {
931 Node n = children.item(i);
932
933 if(n.getNodeName().equals(SECTION_ELEMENT)) {
934 //then we know it's an element AND that its tagname is "Section"
935 Element subsection = (Element)n;
936 Element child = createDocNodeFromSubsection(doc, subsection, docPID);
937 parent.appendChild(child);
938
939 // recursion call on newly found child-element and subsection
940 createDocStructure(doc, subsection, child, docPID);
941 }
942 }
943 }
944
945 /** Given a particular subsection element, this method creates a
946 * Greenstone3 DocumentNode element that mirrors it.
947 * @param doc is the document that will contain the created DocumentNode
948 * @param docID is the prefix of all nodeIDs in the parent's structure
949 * @param subSection is the XML &lt;Section&gt; in the fedora repository's
950 * TOC for the docPID which will be mirrored in the greenstone XML
951 * documentNode that will be returned.
952 * @return a greenstone &lt;documentNode&gt; that represents the fedora TOC's
953 * &lt;Section&gt; element passed as parameter subSection. */
954 protected Element createDocNodeFromSubsection(
955 Document doc, Element subSection, String docID)
956 {
957 Element docNode = doc.createElement(GSXML.DOC_NODE_ELEM);
958 Attr docType = doc.createAttribute(GSXML.DOC_TYPE_ATT);
959 docType.setValue(GSXML.DOC_TYPE_HIERARCHY);
960 docNode.setAttributeNode(docType);
961
962 Attr nodeID = doc.createAttribute(GSXML.NODE_ID_ATT);
963 String sectionID = subSection.hasAttribute(ID) ?
964 subSection.getAttribute(ID) : "";
965 nodeID.setValue(docID + HYPHEN + sectionID);
966 docNode.setAttributeNode(nodeID);
967
968 Attr nodeType = doc.createAttribute(GSXML.NODE_TYPE_ATT);
969 if(sectionID.equals("1")) { // root case
970 nodeType.setValue(GSXML.NODE_TYPE_ROOT);
971 // reset the attribute without the section number
972 docNode.setAttribute(GSXML.NODE_ID_ATT, docID);
973 }
974 else if(subSection.getElementsByTagName(SECTION_ELEMENT).getLength() > 0)
975 // this section has further <Section> children, so it's an internal node
976 nodeType.setValue(GSXML.NODE_TYPE_INTERNAL);
977 else if(subSection.hasAttribute(TYPE))
978 nodeType.setValue(GSXML.NODE_TYPE_INTERNAL);
979 else // leaf
980 nodeType.setValue(GSXML.NODE_TYPE_LEAF);
981 docNode.setAttributeNode(nodeType);
982 return docNode;
983 }
984
985
986 /** Given an identifier that is either a docPID or a concatenation of
987 * docPID+sectionID, this method works out the fedora assigned docPID and
988 * sectionID and then calls getContentBody(docPID, sectionID) with those.
989 * @param docID is expected to be of the form
990 * "greenstone:&lt;collectionName&gt;-&lt;docPID&gt;-&lt;sectionNumber&gt;" or
991 * "greenstone:&lt;collectionName&gt;-&lt;docPID&gt;"
992 * If it is "greenstone:&lt;collectionName&gt;-&lt;docPID&gt;", then the content for
993 * "greenstone:&lt;collectionName&gt;-1" ("greenstone:&lt;collectionName&gt;-Section1")
994 * is returned! */
995 public String getContent(String docID) {
996 return this.getContent(new String[]{docID});
997 }
998
999 /** Given an identifier that is a concatenation of docID+sectionID, this
1000 * method works out the fedora assigned docPID and sectionID and then calls
1001 * getContentBody(docPID, sectionID) with those.
1002 * @param docIDs is an array of document identifiers of the form
1003 * "greenstone:&lt;collectionName&gt;-&lt;docPID&gt;-&lt;sectionNumber&gt;"
1004 * If it is "greenstone:&lt;collectionName&gt;-&lt;docPID&gt;", then the content for
1005 * "greenstone:&lt;collectionName&gt;-Section1" is returned! */
1006 public String getContent(String[] docIDs) {
1007 Document doc = builder.newDocument();
1008 FedoraGS3RunException ex = null;
1009
1010 //<documentNodeList>
1011 Element docNodeList = doc.createElement(
1012 GSXML.DOC_NODE_ELEM+GSXML.LIST_MODIFIER);
1013
1014 try{
1015 for(int i = 0; i < docIDs.length; i++) {
1016 // get the sectionID and docPID from the docID
1017 String sectionID = this.removePrefix(
1018 getSectionIDFromDocID(docIDs[i]), SECTION);
1019 String docPID = getDocPIDFromDocID(docIDs[i]);
1020 if(sectionID.equals("")) // if no section is specified, get
1021 sectionID = "1"; // get the content for Section id="1"
1022
1023 // Get the contents for the requested section of document docPID
1024 String sectionContent = this.getContentBody(docPID, sectionID);
1025
1026 // set the nodeID attribute
1027 Element docNode = doc.createElement(GSXML.DOC_NODE_ELEM);
1028 Attr nodeId = doc.createAttribute(GSXML.NODE_ID_ATT);
1029
1030 nodeId.setValue(docIDs[i]); // just set the docID which will contain
1031 // the docPID (and sectionID if already present)
1032
1033 docNode.setAttributeNode(nodeId);
1034 // set the text content to what was retrieved
1035 Element nodeContent = doc.createElement(GSXML.NODE_CONTENT_ELEM);
1036 Text textNode = doc.createTextNode(sectionContent);
1037
1038 nodeContent.appendChild(textNode);
1039 docNode.appendChild(nodeContent);
1040 //add the documentNode to the docNodeList
1041 docNodeList.appendChild(docNode);
1042 }
1043 } catch(Exception e) {
1044 ex = new FedoraGS3RunException(e);
1045 ex.setSpecifics("requested doc Section datastream");
1046 }
1047 Element responseMsg = createResponseMessage(doc, docNodeList, ex,
1048 GSXML.REQUEST_TYPE_PROCESS, "DocumentContentRetrieve");
1049 try{
1050 return FedoraCommons.elementToFormattedString(responseMsg);
1051 } catch(TransformerException e) {
1052 return FedoraGS3RunException.xmlToStringConversionFailureResponseMsg
1053 + " " + e;
1054 }
1055 }
1056
1057 /** Gets the contents of a textNode from a section.
1058 * @return the text content of a section.
1059 * @param docPID the pid of the document from which a section's text is to
1060 * be retrieved.
1061 * @param sectionID is the section identifier of the document denoted by
1062 * docPID whose text is to be returned.
1063 */
1064 protected String getContentBody(String docPID, String sectionID)
1065 throws RemoteException, UnsupportedEncodingException,
1066 SAXException, IOException
1067 {
1068 String section = this.getSection(docPID, sectionID);
1069
1070 // the content is nested inside a <Section> element,
1071 // we extract it from there:
1072 InputSource source = new InputSource(new StringReader(section));
1073 Document doc = builder.parse(source);
1074
1075 // The document Element is the <Section> we want.
1076 // Get its text contents:
1077 section = FedoraCommons.getValue(doc.getDocumentElement());
1078
1079 // we are going to remove all occurrences of "_httpdocimg_/"
1080 // that precede associated filenames, because that's a GS3
1081 // defined macro for resolving relative urls. It won't help
1082 // with documents stored in fedora.
1083 section = section.replaceAll(GS3FilePathMacro+"/", "");
1084 return section;
1085 }
1086
1087 /** Here we create the greenstone's response message element:
1088 * &lt;message&lg;&lt;response&gt;&lt;content&gt;&lt;/response&gt;&lt;/message&gt;
1089 * @return a greenstone response-message element.
1090 * @param doc - the Document object which should me used to create the
1091 * &lt;message&gt; and &lt;response&gt; elements
1092 * @param content - the element that is to be nested inside &lt;response&gt;
1093 * @param ex - any exception that occurred when trying to create
1094 * the content parameter
1095 * @param responseType - the value for the type attribute of &lt;response&gt;,
1096 * such as "describe", "retrieve", "browse", "query"...
1097 * @param originator - indiates the collectionName or service (like
1098 * DocumentContentRetrieve) from where this response message originates
1099 */
1100 protected Element createResponseMessage(Document doc, Element content,
1101 Exception ex, String responseType, String originator)
1102 {
1103 Element response = doc.createElement(GSXML.RESPONSE_ELEM);
1104 // from = "FedoraGS3"
1105 Attr attribute = doc.createAttribute(GSXML.FROM_ATT);
1106 String from = originator.equals("") ? FEDORA_GS3
1107 : FEDORA_GS3+"/"+originator;
1108
1109 attribute.setValue(from);
1110 response.setAttributeNode(attribute);
1111
1112 // type = "describe" or "process" - whatever's given in requestType:
1113 attribute = doc.createAttribute(GSXML.TYPE_ATT);
1114 attribute.setValue(responseType);
1115 response.setAttributeNode(attribute);
1116
1117 if(content != null)
1118 response.appendChild(content);
1119
1120 // we'll create an error element for RemoteExceptions (web service problems)
1121 // and UnsupportedEncodingExceptions and
1122 if(ex != null) {
1123 Element error = doc.createElement(GSXML.ERROR_ELEM);
1124 error.appendChild(doc.createTextNode(ex.getMessage()));
1125 // now append the error to the <response> element (after
1126 // the content element whatever that was)
1127 response.appendChild(error);
1128 }
1129
1130 Element message = doc.createElement(GSXML.MESSAGE_ELEM);
1131 message.appendChild(response);
1132 doc.appendChild(message);
1133 return message;
1134 }
1135
1136 /** @return a &lt;serviceList&gt; Element as defined by GS3: containing all the
1137 * services (denoted by &lt;service&gt; elements) that are supported by FedoraGS3.
1138 * At present these are: DocumentContentRetrieve, DocumentMetadataRetrieve,
1139 * DocumentStructureRetrieve, TextQuery, FieldQuery, ClassifierBrowse,
1140 * ClassifierBrowseMetadataRetrieve (as indicated by member var serviceNames).
1141 * @param doc - the Document object which should me used to create the
1142 * &lt;serviceList&gt; element */
1143 protected Element createServiceList(Document doc)
1144 {
1145 Element serviceList = doc.createElement(
1146 GSXML.SERVICE_ELEM+GSXML.LIST_MODIFIER);
1147
1148 for(int i = 0; i < serviceNames.length; i++) {
1149 // create the <service name="serviceName[i]" type="servicetype" />
1150 Element service = doc.createElement(GSXML.SERVICE_ELEM);
1151
1152 Attr attribute = doc.createAttribute(GSXML.NAME_ATT);
1153 attribute.setValue(serviceNames[i]);
1154 service.setAttributeNode(attribute);
1155
1156 attribute = doc.createAttribute(GSXML.TYPE_ATT);
1157 if(serviceNames[i].equals("ClassifierBrowse")) //browseTitlesByLetter
1158 attribute.setValue(GSXML.SERVICE_TYPE_BROWSE);
1159 else if(serviceNames[i].contains("Query")) // search services
1160 attribute.setValue(GSXML.SERVICE_TYPE_QUERY);
1161 else
1162 attribute.setValue(GSXML.SERVICE_TYPE_RETRIEVE);
1163 service.setAttributeNode(attribute);
1164
1165 // add the service element to the serviceList element
1166 // <serviceList><service /></serviceList>
1167 serviceList.appendChild(service);
1168 }
1169 return serviceList;
1170 }
1171
1172 /** @return a GS3 response message for a describe services request:
1173 * indicating the list of services supported by the Fedora-Greenstone
1174 * interface. These are DocumentContentRetrieve, DocumentMetadataRetrieve,
1175 * DocumentStructureRetrieve, ClassifierBrowse, TextQuery, FieldQuery,
1176 * ClassifierBrowseMetadataRetrieve - as indicated by member variable
1177 * serviceNames. */
1178 public String getServiceList()
1179 {
1180 Document doc = builder.newDocument();
1181 Element serviceList = createServiceList(doc);
1182 // make <serviceList> the body of the responseMessage:
1183 // <message><response><serviceList></response></message>
1184 Element responseMsg = createResponseMessage(doc, serviceList, null,
1185 GSXML.REQUEST_TYPE_DESCRIBE, "");
1186 try {
1187 return FedoraCommons.elementToFormattedString(responseMsg);
1188 }catch(TransformerException e) {
1189 return FedoraGS3RunException.xmlToStringConversionFailureResponseMsg
1190 + " " + e;
1191 }
1192 }
1193
1194 /** @return a GS3 describe response message listing the collections and
1195 * collection-specific metadata stored in the Fedora-Greenstone repository. */
1196 public String getCollectionList()
1197 {
1198 Document doc = builder.newDocument();
1199 FedoraGS3RunException ex = null; // any RemoteException
1200
1201 // create the <collectionList /> element
1202 Element collectionList = doc.createElement(
1203 GSXML.COLLECTION_ELEM+GSXML.LIST_MODIFIER);
1204 try{
1205 String[] collectionNames = this.getCollectionNames(
1206 this.getCollections()); // this line could throw RemoteException
1207 for(int i = 0; i < collectionNames.length; i++) {
1208 // create the <collection name="somename" /> element
1209 Element collection = doc.createElement(GSXML.COLLECTION_ELEM);
1210 Attr attribute = doc.createAttribute(GSXML.NAME_ATT);
1211 attribute.setValue(collectionNames[i]);
1212 collection.setAttributeNode(attribute);
1213
1214 // append the <collection> element as child of <collectionList>
1215 collectionList.appendChild(collection);
1216
1217 //if(collection.hasAttribute(GSXML.NAME_ATT))
1218 //LOG.debug(collection.getAttribute(GSXML.NAME_ATT));
1219 }
1220 } catch(RemoteException e) { // if this happens, perhaps it's because it
1221 // can't find Greenstone collections in fedora repository?
1222 ex = new FedoraGS3RunException(e);
1223 ex.setSpecifics(
1224 "greenstone collections in fedora repository");
1225 }
1226
1227 // make <collectionList> the body of the responseMessage:
1228 // <message><response><collectionList></response></message>
1229 Element responseMsg = createResponseMessage(doc, collectionList, ex,
1230 GSXML.REQUEST_TYPE_DESCRIBE, "");
1231 try{
1232 return FedoraCommons.elementToFormattedString(responseMsg);
1233 }catch(TransformerException e) {
1234 return FedoraGS3RunException.xmlToStringConversionFailureResponseMsg
1235 + " " + e;
1236 }
1237 }
1238
1239 /** @return a GS3 describe response message for a collection in the
1240 * Fedora-Greenstone repository.
1241 * @param collectionName - the name of the collection that is to be described.
1242 * It will be converted to a fedora collection pid, which is of the form
1243 * "greenstone:&lt;collectionName&gt;-collection". */
1244 public String describeCollection(String collectionName)
1245 {
1246 Document doc = builder.newDocument();
1247 FedoraGS3RunException ex = null;
1248
1249 Element collection = doc.createElement(GSXML.COLLECTION_ELEM);
1250 Attr attribute = doc.createAttribute(GSXML.NAME_ATT);
1251 attribute.setValue(collectionName);
1252 collection.setAttributeNode(attribute);
1253
1254 //<displayItem assigned="true" lang="en" name="name">
1255 //"some display name"</displayItem>
1256 Element displayItem = doc.createElement(GSXML.DISPLAY_TEXT_ELEM);
1257
1258 attribute = doc.createAttribute(GSXML.LANG_ATT);
1259 attribute.setValue(this.lang);
1260 displayItem.setAttributeNode(attribute);
1261
1262 attribute = doc.createAttribute(GSXML.NAME_ATT);
1263 attribute.setValue(GSXML.DISPLAY_TEXT_NAME);
1264 displayItem.setAttributeNode(attribute);
1265
1266 try{
1267 Text textNode = doc.createTextNode(
1268 this.getCollectionTitle(getCollectionPID(collectionName)));
1269 displayItem.appendChild(textNode);
1270 } catch(Exception e) {
1271 // can't find Greenstone collections in fedora repository or problem
1272 // getting their titles from their metadata datastream?
1273 ex = new FedoraGS3RunException(e);
1274 ex.setSpecifics("greenstone collections or their metadata"
1275 + "in the fedora repository");
1276 }
1277 // now append the displayItem element as child of the collection element
1278 collection.appendChild(displayItem);
1279 // get the <serviceList> and add it into the collection description.
1280 // Services for all collections in the FedoraGS3 repository are the
1281 // same, offering a ClassifierBrowse to browse titles by starting letter
1282 // and DocRetrieve services: Content, Metadata and Structure.
1283
1284 Element serviceList = createServiceList(doc);
1285 collection.appendChild(serviceList);
1286
1287 Element responseMsg = createResponseMessage(doc, collection, ex,
1288 GSXML.REQUEST_TYPE_DESCRIBE, collectionName);
1289 try{
1290 return FedoraCommons.elementToFormattedString(responseMsg);
1291 }catch(TransformerException e) {
1292 return FedoraGS3RunException.xmlToStringConversionFailureResponseMsg
1293 + " " + e;
1294 }
1295 }
1296
1297 /** @return a GS3 describe response message for the services of a collection
1298 * in the Fedora-Greenstone repository. So far, these services are the same for
1299 * all fedora collections: they are the services given in member variable
1300 * serviceNames: DocumentContent/Metadata/StructureRetrieve, ClassifierBrowse,
1301 * ClassifierBrowseMetadataRetrieve.
1302 * @param collectionName - the name of the collection whose services are to
1303 * be described. It will be converted to a fedora collection pid, which is of
1304 * the form "greenstone:&lt;collectionName&gt;-collection". */
1305 public String describeCollectionServices(String collectionName)
1306 {
1307 Document doc = builder.newDocument();
1308
1309 Element collection = doc.createElement(GSXML.COLLECTION_ELEM);
1310 Attr attribute = doc.createAttribute(GSXML.NAME_ATT);
1311 attribute.setValue(collectionName);
1312 collection.setAttributeNode(attribute);
1313
1314 Element serviceList = createServiceList(doc);
1315 collection.appendChild(serviceList);
1316
1317 Element responseMsg = createResponseMessage(doc, collection, null,
1318 GSXML.REQUEST_TYPE_DESCRIBE, collectionName);
1319 try{
1320 return FedoraCommons.elementToFormattedString(responseMsg);
1321 }catch(TransformerException e) {
1322 return FedoraGS3RunException.xmlToStringConversionFailureResponseMsg
1323 + " " + e;
1324 }
1325 }
1326
1327 /** All collections in this Digital Library (Fedora Repository) share
1328 * the same services, so this method returns the same as
1329 * describeCollectionService(collName, serviceName).
1330 * @return a GS3 describe response message for the requested service
1331 * of the given collection. DocumentContent/Metadata/StructureRetrieve
1332 * return nothing special except their names; browse (and any query)
1333 * return more complex XML responses.
1334 * All collections in this Digital Library (Fedora Repository) share
1335 * the same services, so this method returns the same as
1336 * describeService(serviceName).
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 // don't forget to add the type attribute to the service!
1398 service.setAttributeNode(attribute);
1399
1400 String from = serviceName;
1401
1402 Element responseMsg = createResponseMessage(doc, service, null,
1403 GSXML.REQUEST_TYPE_DESCRIBE, from);
1404 try{
1405 return FedoraCommons.elementToFormattedString(responseMsg);
1406 }catch(TransformerException e) {
1407 return FedoraGS3RunException.xmlToStringConversionFailureResponseMsg
1408 + " " + e;
1409 }
1410 }
1411
1412 /** Appends children to the parameter service Element that make the
1413 * final service Element into a describe response XML for FedoraGS3's
1414 * TextQuery service.
1415 * @param service is the service Element that is being filled out. */
1416 protected void describeTextQueryService(Element service) {
1417 Document doc = service.getOwnerDocument();
1418 // we need name, submit (button) and description <displayItem> elements
1419 Element displayItem = createNameValuePairElement(doc,
1420 GSXML.DISPLAY_TEXT_ELEM, GSXML.DISPLAY_TEXT_NAME,
1421 "Text Search");
1422 service.appendChild(displayItem);
1423
1424 displayItem = createNameValuePairElement(doc,
1425 GSXML.DISPLAY_TEXT_ELEM, GSXML.DISPLAY_TEXT_SUBMIT, "Search");
1426 service.appendChild(displayItem);
1427
1428 displayItem = createNameValuePairElement(doc,
1429 GSXML.DISPLAY_TEXT_ELEM, GSXML.DISPLAY_TEXT_DESCRIPTION,
1430 "Title and full-text search service");
1431 service.appendChild(displayItem);
1432
1433 //create the <paramList>
1434 Element paramList = doc.createElement(
1435 GSXML.PARAM_ELEM+GSXML.LIST_MODIFIER);
1436
1437 // we ignore granularity to search at: it will always be
1438 // document and section level
1439 // we ignore casefolding: always on (that is, case is irrelevant)
1440 // we ignore document display order: always ranked
1441
1442 // Constructing the following:
1443 // <param default="100" name="maxDocs" type="integer">
1444 // <displayItem name="name">Maximum hits to return</displayItem>
1445 // </param>
1446 Element param = doc.createElement(GSXML.PARAM_ELEM);
1447
1448 Attr attribute = doc.createAttribute(GSXML.NAME_ATT);
1449 attribute.setValue(MAXDOCS);
1450 param.setAttributeNode(attribute);
1451
1452 attribute = doc.createAttribute(GSXML.DEFAULT_ATT);
1453 attribute.setValue("100");
1454 param.setAttributeNode(attribute);
1455
1456 attribute = doc.createAttribute(GSXML.TYPE_ATT);
1457 attribute.setValue(GSXML.PARAM_TYPE_INTEGER);
1458 param.setAttributeNode(attribute);
1459
1460 displayItem = createNameValuePairElement(doc,
1461 GSXML.DISPLAY_TEXT_ELEM, GSXML.DISPLAY_TEXT_NAME,
1462 "Maximum hits to return");
1463 param.appendChild(displayItem);
1464
1465 paramList.appendChild(param);
1466
1467 // Constructing the following:
1468 // <param name="query" type="string">
1469 // <displayItem name="name">Query string</displayItem>
1470 // </param>
1471 param = doc.createElement(GSXML.PARAM_ELEM);
1472
1473 attribute = doc.createAttribute(GSXML.NAME_ATT);
1474 attribute.setValue(QUERY);
1475 param.setAttributeNode(attribute);
1476
1477 attribute = doc.createAttribute(GSXML.TYPE_ATT);
1478 attribute.setValue(GSXML.PARAM_TYPE_STRING);
1479 param.setAttributeNode(attribute);
1480
1481 displayItem = createNameValuePairElement(doc,
1482 GSXML.DISPLAY_TEXT_ELEM, GSXML.DISPLAY_TEXT_NAME,
1483 "Query string");
1484 param.appendChild(displayItem);
1485
1486 paramList.appendChild(param);
1487
1488 service.appendChild(paramList);
1489 }
1490
1491 /** Appends children to the parameter service Element that make the
1492 * final service Element into a describe response XML for FedoraGS3's
1493 * FieldQuery service.
1494 * @param service is the service Element that is being filled out. */
1495 protected void describeFieldQueryService(Element service) {
1496 Document doc = service.getOwnerDocument();
1497 // we need name, submit (button) and description <displayItem> elements
1498 Element displayItem = createNameValuePairElement(doc,
1499 GSXML.DISPLAY_TEXT_ELEM, GSXML.DISPLAY_TEXT_NAME,
1500 "Form Search");
1501 service.appendChild(displayItem);
1502
1503 displayItem = createNameValuePairElement(doc,
1504 GSXML.DISPLAY_TEXT_ELEM, GSXML.DISPLAY_TEXT_SUBMIT, "Search");
1505 service.appendChild(displayItem);
1506
1507 displayItem = createNameValuePairElement(doc,
1508 GSXML.DISPLAY_TEXT_ELEM, GSXML.DISPLAY_TEXT_DESCRIPTION,
1509 "Simple fielded search");
1510 service.appendChild(displayItem);
1511
1512 //create the <paramList>
1513 Element paramList = doc.createElement(
1514 GSXML.PARAM_ELEM+GSXML.LIST_MODIFIER);
1515
1516 // we ignore granularity to search at: it will always be
1517 // document and section level
1518 // we ignore casefolding: always on (that is, case is irrelevant)
1519 // we ignore document display order: always ranked
1520
1521 // Constructing the following:
1522 // <param default="100" name="maxDocs" type="integer">
1523 // <displayItem name="name">Maximum hits to return</displayItem>
1524 // </param>
1525 Element param = doc.createElement(GSXML.PARAM_ELEM);
1526
1527 Attr attribute = doc.createAttribute(GSXML.NAME_ATT);
1528 attribute.setValue(MAXDOCS);
1529 param.setAttributeNode(attribute);
1530
1531 attribute = doc.createAttribute(GSXML.DEFAULT_ATT);
1532 attribute.setValue("100");
1533 param.setAttributeNode(attribute);
1534
1535 attribute = doc.createAttribute(GSXML.TYPE_ATT);
1536 attribute.setValue(GSXML.PARAM_TYPE_INTEGER);
1537 param.setAttributeNode(attribute);
1538
1539 displayItem = createNameValuePairElement(doc,
1540 GSXML.DISPLAY_TEXT_ELEM, GSXML.DISPLAY_TEXT_NAME,
1541 "Maximum hits to return");
1542 param.appendChild(displayItem);
1543
1544 paramList.appendChild(param);
1545
1546 // Constructing the following:
1547 // <param name="simpleField" occurs="4" type="multi">
1548 // <displayItem name="name"></displayItem>
1549 //
1550 // <param name="query" type="string">
1551 // <displayItem name="name">Word or phrase </displayItem>
1552 // </param>
1553 //
1554 // <param default="allFields" name="fieldname" type="enum_single">
1555 // <displayItem name="name">in field</displayItem>
1556 //
1557 // <option name="docTitles">
1558 // <displayItem name="name">document titles</displayItem>
1559 // </option>
1560 // <option name="allTitles">
1561 // <displayItem name="name">document and section titles</displayItem>
1562 // </option>
1563 // <option name="fullText">
1564 // <displayItem name="name">full text</displayItem>
1565 // </option>
1566 // <option name="all">
1567 // <displayItem name="name">titles and full text</displayItem>
1568 // </option>
1569 // <option name="">
1570 // <displayItem name="name"></displayItem>
1571 // </option>
1572 // </param>
1573 // </param>
1574 Element rowOfParams = doc.createElement(GSXML.PARAM_ELEM);
1575 attribute = doc.createAttribute(GSXML.NAME_ATT);
1576 attribute.setValue(SIMPLEFIELD_ATT);
1577 rowOfParams.setAttributeNode(attribute);
1578
1579 // we want the row of controls to occur multiple times
1580 attribute = doc.createAttribute(GSXML.TYPE_ATT);
1581 attribute.setValue(GSXML.PARAM_TYPE_MULTI);
1582 rowOfParams.setAttributeNode(attribute);
1583
1584 attribute = doc.createAttribute(OCCURS_ATT);
1585 attribute.setValue("4"); // we want this row to occur 4 times
1586 rowOfParams.setAttributeNode(attribute);
1587
1588 // <param name="query" type="string">
1589 // <displayItem name="name">Word or phrase </displayItem>
1590 // </param>
1591 param = doc.createElement(GSXML.PARAM_ELEM);
1592
1593 attribute = doc.createAttribute(GSXML.NAME_ATT);
1594 attribute.setValue(QUERY);
1595 param.setAttributeNode(attribute);
1596
1597 attribute = doc.createAttribute(GSXML.TYPE_ATT);
1598 attribute.setValue(GSXML.PARAM_TYPE_STRING);
1599 param.setAttributeNode(attribute);
1600
1601 displayItem = createNameValuePairElement(doc,
1602 GSXML.DISPLAY_TEXT_ELEM, GSXML.DISPLAY_TEXT_NAME,
1603 "Word or phrase");
1604 param.appendChild(displayItem);
1605 rowOfParams.appendChild(param);
1606
1607 // <param default="allFields" name="fieldName" type="enum_single">
1608 // <displayItem name="name">in field</displayItem>
1609 param = doc.createElement(GSXML.PARAM_ELEM);
1610 attribute = doc.createAttribute(GSXML.NAME_ATT);
1611 attribute.setValue(FIELDNAME_ATT);
1612 param.setAttributeNode(attribute);
1613
1614 attribute = doc.createAttribute(GSXML.TYPE_ATT);
1615 attribute.setValue(GSXML.PARAM_TYPE_ENUM_SINGLE);
1616 param.setAttributeNode(attribute);
1617
1618 attribute = doc.createAttribute(GSXML.DEFAULT_ATT);
1619 attribute.setValue(ALL_FIELDS);
1620 param.setAttributeNode(attribute);
1621
1622 displayItem = createNameValuePairElement(doc,
1623 GSXML.DISPLAY_TEXT_ELEM, GSXML.DISPLAY_TEXT_NAME,
1624 "in field");
1625 param.appendChild(displayItem);
1626
1627 String[] searchFieldNames
1628 = {ALL_FIELDS, DOC_TITLES, ALL_TITLES, FULLTEXT};
1629 String[] searchFieldDisplay = {"all titles and full-text",
1630 "document titles only", "document and section titles",
1631 "full-text only"};
1632
1633 // for each fieldName create an option element and insert
1634 // the option into the enum_multi drop-down param:
1635 // <option name="fieldName">
1636 // <displayItem name="name">fieldName</displayItem>
1637 // </option>
1638 for(int i = 0; i < searchFieldNames.length; i++) {
1639 Element option = doc.createElement(GSXML.PARAM_OPTION_ELEM);
1640 attribute = doc.createAttribute(GSXML.NAME_ATT);
1641 attribute.setValue(searchFieldNames[i]);
1642 option.setAttributeNode(attribute);
1643
1644 displayItem = createNameValuePairElement(doc,
1645 GSXML.DISPLAY_TEXT_ELEM, GSXML.DISPLAY_TEXT_NAME,
1646 searchFieldDisplay[i]);
1647 option.appendChild(displayItem);
1648 param.appendChild(option); // add option to the drop-down box
1649 }
1650
1651 rowOfParams.appendChild(param);
1652 paramList.appendChild(rowOfParams);
1653 service.appendChild(paramList);
1654 }
1655
1656 /**
1657 * @return a GS3 describe response message for the requested service
1658 * of the given collection. DocumentContent/Metadata/StructureRetrieve
1659 * return nothing special except their names; browse (and any query)
1660 * return more complex XML responses.
1661 * All collections in this Digital Library (Fedora Repository) share
1662 * the same services, so this method returns the same as
1663 * describeService(serviceName).
1664 * @param collectionName - the name of the collection whose service is to
1665 * be described. It will be converted to a fedora collection pid, which is of
1666 * the form "greenstone:&lt;collectionName&gt;-collection".
1667 * @param serviceName - the name of the service in the collection which is to
1668 * be described. */
1669 public String describeCollectionService(String collectionName,
1670 String serviceName) {
1671 // collectionName can be ignored, because all services are FedoraGS3
1672 // services and are not unique to any particular (greenstone) collection.
1673 return describeService(serviceName);
1674 }
1675
1676 /** This method performs the implemented browse operation: allowing the
1677 * user to browse the titles of documents in the given collection by letter
1678 * and returning the results.
1679 * @param classifierID is the id of the classifier on which to browse. In
1680 * this case, the classifier indicates whether we browse titles by letter, or
1681 * browse (documents) by collection; and it is of the form &lt;CL(letter)&gt;.
1682 * @param collectionName is the name of the collection whose documents
1683 * starting with the given letter will be returned.
1684 * @return a GS3 DocumentStructureRetrieve response message which lists all
1685 * the documents that start with the letter indicated by parameter classifier.
1686 */
1687 public String browse(String collectionName, String classifierID)
1688 {
1689 Document doc = builder.newDocument();
1690 FedoraGS3RunException ex = null; //any RemoteException or UnsupportedEncodingException
1691
1692 // <classifierNodeList>
1693 Element classifierNodeList = doc.createElement(
1694 GSXML.CLASS_NODE_ELEM+GSXML.LIST_MODIFIER);
1695
1696 // <classifierNode nodeID="classifierNum">
1697 Element requestedClassifierNode = doc.createElement(
1698 GSXML.CLASS_NODE_ELEM);
1699 Attr attribute = doc.createAttribute(GSXML.NODE_ID_ATT);
1700 attribute.setValue(classifierID);
1701 requestedClassifierNode.setAttributeNode(attribute);
1702 classifierNodeList.appendChild(requestedClassifierNode);
1703
1704 // <nodeStructure>
1705 Element nodeStructure = doc.createElement(GSXML.NODE_STRUCTURE_ELEM);
1706 requestedClassifierNode.appendChild(nodeStructure);
1707
1708 // And one more time, the top level classifierNode:
1709 Element classifierNode = doc.createElement(GSXML.CLASS_NODE_ELEM);
1710 attribute = doc.createAttribute(GSXML.NODE_ID_ATT);
1711 attribute.setValue(classifierID);
1712 classifierNode.setAttributeNode(attribute);
1713 nodeStructure.appendChild(classifierNode);
1714
1715 // Work out what we're browsing base on the classifierID's number
1716 // classifier CL1 = browse titles by letter;
1717 // classifier CL2 = browse by collection;
1718 //remove the CL prefix and obtain the number from the id:
1719 int classifierNum = Integer.parseInt(classifierID.replace("CL", ""));
1720 switch(classifierNum) {
1721 case 1:
1722 // we're going to loop to the end of the alphabet
1723 int num = 1;
1724 for(char ch = 'A'; ch <= 'Z'; ch++, num++) {
1725 // Retrieve the document structure for each subClassifierID:
1726 // all the documents that begin with its letter.
1727 // remove the starting CL
1728 String letter = String.valueOf(ch);
1729 try{
1730 String[] docPIDs = this.browseTitlesByLetter(
1731 collectionName, letter);
1732 if(docPIDs.length == 0) {
1733 continue; // skip letters that don't have any kids
1734 }
1735
1736 // <classifierNode nodeID="CL3.1">
1737 Element subClassifier = doc.createElement(
1738 GSXML.CLASS_NODE_ELEM);
1739 attribute = doc.createAttribute(GSXML.NODE_ID_ATT);
1740 attribute.setValue(classifierID+"."+num);
1741 subClassifier.setAttributeNode(attribute);
1742 classifierNode.appendChild(subClassifier);
1743
1744 // append the <docNodes> for the docPIDs found as children
1745 // of subclassifier
1746 getStructureElement(subClassifier, docPIDs, DESCENDANTS);
1747 //CHILDREN); // for testing
1748 } catch(Exception e) {
1749 ex = new FedoraGS3RunException(e);
1750 ex.setSpecifics("requested portion of TOC file or "
1751 + "trouble with fielded search ");
1752 }
1753 }
1754 // No titles in this collection that start with a letter at all
1755 if(!classifierNode.hasChildNodes()) {
1756 // <classifierNode nodeID="CL1.0"> which we will equate with A-Z
1757 Element subClassifier = doc.createElement(
1758 GSXML.CLASS_NODE_ELEM);
1759 attribute = doc.createAttribute(GSXML.NODE_ID_ATT);
1760 attribute.setValue(classifierID+"."+0); //
1761 subClassifier.setAttributeNode(attribute);
1762 classifierNode.appendChild(subClassifier);
1763 }
1764 break;
1765 case 2:
1766 break;
1767 default:
1768 ex = new FedoraGS3RunException( // cause is regular exception
1769 new Exception("Unknown classifier ID: " + classifierID));
1770 }
1771 Element responseMsg = createResponseMessage(doc, classifierNodeList, ex,
1772 GSXML.REQUEST_TYPE_DESCRIBE, collectionName+"/ClassifierBrowse");
1773 try{
1774 return FedoraCommons.elementToFormattedString(responseMsg);
1775 }catch(TransformerException e) {
1776 return FedoraGS3RunException.xmlToStringConversionFailureResponseMsg
1777 + " " + e;
1778 }
1779 }
1780
1781 /** This method performs something equivalent to a greenstone3
1782 * ClassifierBrowseMetadataRetrieve on the classifierNodeIDs
1783 * @param classNodeIDs array of classifierNode IDs of for which the metadata
1784 * needs to be returned.
1785 * @return a GS3 ClassifierBrowseMetadataRetrieve response message which
1786 * lists the metadata for all the classifierNodes passed as parameter.*/
1787 public String browseMetadataRetrieve(String[] classNodeIDs)
1788 {
1789 Document doc = this.builder.newDocument();
1790 // <classifierNodeList>
1791 Element classifierNodeList = doc.createElement(
1792 GSXML.CLASS_NODE_ELEM+GSXML.LIST_MODIFIER);
1793
1794 // create <classifierNode><metadataList><metadata>s
1795 // </metadataList></classifierNode> for all letters of alphabet
1796 for(int i = 0; i < classNodeIDs.length; i++) {
1797 // strip ID of everything before the first '.' (i.e. remove "CL#.")
1798 int index = classNodeIDs[i].indexOf('.');
1799 String subClassifierNumber = classNodeIDs[i].substring(index+1);
1800 int subClassifierNum = Integer.parseInt(subClassifierNumber);
1801 String classifierName = "";
1802 if(subClassifierNum == 0) { // no document titles started with a letter
1803 classifierName = "A-Z";
1804 } else {
1805 char letter = (char)('A' + subClassifierNum - 1); // A = 1
1806 classifierName = String.valueOf(letter);
1807 }
1808
1809 // <classifierNode nodeID="CL#.subNum">
1810 Element classifierNode = doc.createElement(GSXML.CLASS_NODE_ELEM);
1811 Attr attribute = doc.createAttribute(GSXML.NODE_ID_ATT);
1812 attribute.setValue(classNodeIDs[i]);
1813 classifierNode.setAttributeNode(attribute);
1814
1815 // <metadataList>
1816 Element metadataList = doc.createElement(
1817 GSXML.METADATA_ELEM+GSXML.LIST_MODIFIER);
1818
1819 // at least one metadata element: that of the title of this
1820 // classifierNode:
1821 // <metadata name="Title">letter</metadata>
1822 Element metadata = this.createNameValuePairElement(doc,
1823 GSXML.METADATA_ELEM, "Title", classifierName);
1824
1825 // now connect up everything
1826 metadataList.appendChild(metadata);
1827 classifierNode.appendChild(metadataList);
1828 classifierNodeList.appendChild(classifierNode);
1829 }
1830
1831 Element responseMsg = createResponseMessage(doc, classifierNodeList, null,
1832 GSXML.REQUEST_TYPE_PROCESS, //collName +
1833 "ClassifierBrowseMetadataRetrieve");
1834 try{
1835 return FedoraCommons.elementToFormattedString(responseMsg);
1836 }catch(TransformerException e) {
1837 return FedoraGS3RunException.xmlToStringConversionFailureResponseMsg
1838 + " " + e;
1839 }
1840 }
1841
1842 /** @return a newly created element of the following format:
1843 * &lt;classifier content="somecontent" name="CL+num"&gt;
1844 * &lt;displayItem name="name"&gt;someClassifierName&lt;/displayItem&gt;
1845 * &lt;displayItem name="description"&gt;Browse by classifier name&lt;/displayItem&gt;
1846 * &lt;/classifier&gt;
1847 * @param doc - the document used to create the element
1848 * @param content - value of the content attribute
1849 * @param classifierNum - the number suffixed to the CL, together forming
1850 * the classifier Node's ID
1851 * @param displayNameVal is the bodytext of a named displayItem element
1852 * @param displayDescrVal is the bodytext of a displayItem element with
1853 * description */
1854 protected Element createClassifierElement(Document doc, String content,
1855 int classifierNum, String displayNameVal, String displayDescrVal)
1856 {
1857 final String CL = "CL";
1858 Element classifier = doc.createElement(GSXML.CLASSIFIER_ELEM);
1859 // content attribute
1860 Attr att = doc.createAttribute(GSXML.CLASSIFIER_CONTENT_ATT);
1861 att.setValue(content);
1862 classifier.setAttributeNode(att);
1863 // name attribute
1864 att = doc.createAttribute(GSXML.NAME_ATT);
1865 att.setValue(CL + classifierNum);
1866 classifier.setAttributeNode(att);
1867
1868 // now create the displayItem children for classifier:
1869 // <displayItem name="name">#letter</displayItem>
1870 // <displayItem name="description">
1871 //Browse titles starting with #letter</displayItem>
1872 Element displayItem = createNameValuePairElement(doc,
1873 GSXML.DISPLAY_TEXT_ELEM, GSXML.DISPLAY_TEXT_NAME, displayNameVal);
1874 classifier.appendChild(displayItem);
1875 displayItem = createNameValuePairElement(doc, GSXML.DISPLAY_TEXT_ELEM,
1876 GSXML.DISPLAY_TEXT_DESCRIPTION, displayDescrVal);
1877 classifier.appendChild(displayItem);
1878
1879 return classifier;
1880 }
1881
1882
1883 /** @return a newly created element of the following format:
1884 * &lt;elementName name="somename"&gt;"some display value"&lt;/elementName&gt;
1885 * @param doc - the document used to create the element
1886 * @param elementName - the tag name
1887 * @param name - value of attribute name
1888 * @param value - the body text of the element */
1889 protected Element createNameValuePairElement(Document doc, String elementName,
1890 String name, String value) {
1891 // <elementName name="somename">"some display value"</elementName>
1892 Element element = doc.createElement(elementName);
1893 Attr attribute = doc.createAttribute(GSXML.NAME_ATT);
1894 attribute.setValue(name);
1895 element.setAttributeNode(attribute);
1896
1897 element.appendChild(doc.createTextNode(value));
1898 return element;
1899 }
1900
1901 /**
1902 * @param collection is the collection to search in
1903 * @param query is the query term to search for. It won't specify the
1904 * indexed field to search in, which will mean that GSearch will
1905 * search all default indexed fields.
1906 * @param maxDocs is the maximum number of results to return (which
1907 * at present we consider equivalent to FedoraGSearch's hitpageSize).
1908 */
1909 public String[] textQuery(String collection, String query,
1910 int maxDocs)
1911 throws Exception
1912 {
1913 // no need to search there is no query or query is empty spaces
1914 if(query.trim().equals(""))
1915 return new String[]{};
1916
1917 // QUERY value won't specify indexed field to search, Fedora
1918 // Gsearch will take that as meaning all default indexed fields.
1919 // Params to search() method below: string of fielded query terms;
1920 // hitpageStart, hitpageEnd, snippetsMax (leave that 0)
1921 query = query + " " + "PID" + COLON + GREENSTONE;
1922
1923 String searchResult = this.fedoraGSearch.search(query, 1, maxDocs, 0);
1924 // now we have the XML returned by FedoraGSearch, get the pids
1925 // of the documents returned (if any)
1926 String[] pids = this.fedoraGSearch.getPIDsFromSearchResult(
1927 collection, searchResult);
1928 return pids;
1929 }
1930
1931 /**
1932 * This method performs a fieldquery, searching for x number of phrases
1933 * in each of the 4 indexed fields.
1934 * @param collection is the collection to search in
1935 * @param nameValParamsMap is a Map of several(key, value) entries,
1936 * 4 of which we're concerned with here:
1937 * - the keys are ALL_FIELDS, DOC_TITLES, ALL_TITLES, FULLTEXT
1938 * - the values are a comma separated list of terms (phrases or single
1939 * words) to search that field in. There may be more than 1 or
1940 * there may be none (in which case there may be N empty values or
1941 * spaces separated by commas).
1942 * @param maxDocs is the maximum number of results to return (which
1943 * at present we consider equivalent to FedoraGSearch's hitpageSize).
1944 * */
1945 public String[] fieldQuery(String collection, Map nameValParamsMap,
1946 int maxDocs)
1947 throws Exception
1948 {
1949 // we're going to maintain a list of UNIQUE pids that were returned
1950 // in search results. Hence we use Set:
1951 java.util.Set set = new java.util.HashSet();
1952
1953 // (1) Use Fedora's search to search document titles, if they were
1954 // specified:
1955 String[] docTitlepids = {};
1956
1957 String docTitleTerms = (String)nameValParamsMap.get(DOC_TITLES);
1958 if(docTitleTerms != null) { // no doc titles may have been specified
1959 String[] phrases = docTitleTerms.split(COMMA);
1960
1961 // search the individual phrases first:
1962 for(int i = 0; i < phrases.length; i++) {
1963 if(phrases.equals("") || phrases.equals(" "))
1964 continue; //skip when there are no terms
1965 docTitlepids = this.searchDocumentTitles(
1966 collection, phrases[i], false);
1967 for(int j = 0; j < docTitlepids.length; j++)
1968 set.add(docTitlepids[j]);
1969 }
1970 }
1971 // (2) use FedoraGSearch to search doc AND section titles, and
1972 // fulltext (in case these were specified in nameValParamsMap):
1973 String searchResult = this.fedoraGSearch.search(
1974 nameValParamsMap, 1, maxDocs);
1975
1976 String[] pids = this.fedoraGSearch.getPIDsFromSearchResult(
1977 collection, searchResult);
1978
1979 for(int i = 0; i < pids.length; i++)
1980 set.add(pids[i]);
1981
1982 pids = null;
1983 pids = new String[set.size()];
1984 set.toArray(pids); // unique pids
1985 return pids;
1986 }
1987
1988 /** @return a String representing Greenstone3 XML for a query process
1989 * response returning the results for the query denoted by parameter
1990 * nameValParamsMap.
1991 * @param nameValParamsMap is a Hashmap of name and value pairs for all the
1992 * query field data values. The names match the field names that
1993 * describeCollectionService() would have returned for the query service.
1994 * @param collection is the name of the collection
1995 * @param service is the name of the query service
1996 * This method is only ever called when any of the services in the digital
1997 * library described themselves as type=query. Therefore any digital
1998 * libraries that have no query services, can just return emtpy message
1999 * strings (or even "") since this method will never be called on them
2000 * anyway. */
2001 public String query(String collection, String service,
2002 Map nameValParamsMap)
2003 {
2004 FedoraGS3RunException ex = null;
2005 // (1) obtain the requested number of maximum result documents
2006 int maxDocs = 100;
2007 try{
2008 maxDocs = Integer.parseInt((String)nameValParamsMap.get(MAXDOCS));
2009 } catch(NumberFormatException e) {
2010 maxDocs = 100;
2011 }
2012
2013 String pids[] = {};
2014 // (2) for Textquery, we simply search ALL_FIELDS using FedoraGSearch
2015 if(service.equals("TextQuery")) {
2016 try {
2017 // get the Query field:
2018 String query = (String)nameValParamsMap.get(QUERY);
2019 pids = textQuery(collection, query, maxDocs);
2020 }
2021 catch(Exception e) {
2022 LOG.error("Error in TextQuery processing: " + e);
2023 ex = new FedoraGS3RunException(
2024 "When trying to use FedoraGenericSearch for a TextQuery", e);
2025
2026 }
2027 } else { // (3) FieldQuery
2028 // first get the comma-separated lists
2029 String listOfFieldNames = (String)nameValParamsMap.get(FIELDNAME_ATT);
2030 String listOfSearchTerms = (String)nameValParamsMap.get(QUERY);
2031 // both are comma separated lists, so split both on 'comma'
2032 String[] fieldNames = listOfFieldNames.split(COMMA);
2033 String[] searchTerms = listOfSearchTerms.split(COMMA);
2034
2035 // In the fieldNames and searchTerms lists of nameValParamsMap,
2036 // each searchTerm element was matched with its correspondingly
2037 // indexed fieldName.
2038 // A new map is going to reorganise this, by putting all terms
2039 // for a particular fieldName together in a comma separated list
2040 // and associating that with the fieldName. I.e. (key, value) ->
2041 // (fieldName, comma-separated list of all terms in that field)
2042 Map map = new HashMap();
2043 for(int i = 0; i < searchTerms.length; i++) {
2044 // there may be fewer searchTerms than fieldNames (since some
2045 // fieldNames may have been left empty), so loop on searchTerms
2046 if(map.containsKey(fieldNames[i])) { //fieldName is already
2047 // in the list, so append comma with new value
2048 String termsList = (String)map.get(fieldNames[i]);
2049 termsList = termsList + COMMA + searchTerms[i];
2050 map.put(fieldNames[i], termsList);
2051 } else { // this is the first time this fieldName occurred
2052 // just put the fieldName with searchTerm as-is
2053 map.put(fieldNames[i], searchTerms[i]);
2054 }
2055 }
2056
2057 try {
2058 // For fieldquery, we search on all the fieldNames specified
2059 // - if DOC_TITLES is specified then we use Fedora's search
2060 // - for all other fieldNames specified, we use FedoraGSearch
2061 pids = fieldQuery(collection, map, maxDocs);
2062 }
2063 catch(Exception e) {
2064 LOG.error("Error in FieldQuery processing: " + e);
2065 ex = new FedoraGS3RunException(
2066 "When trying to use FedoraGenericSearch for a FieldQuery", e);
2067 }
2068 }
2069
2070 // Build Greenstone XML Query response message for from
2071 // the pids (which should be document identifiers)
2072 Document doc = builder.newDocument();
2073 // <metadataList><metadata name="numDocsMatched" value="n" />
2074 // </metadataList>
2075 Element metadataList = doc.createElement(
2076 GSXML.METADATA_ELEM+GSXML.LIST_MODIFIER);
2077 Element metadata = doc.createElement(GSXML.METADATA_ELEM);
2078
2079 Attr attribute = doc.createAttribute(GSXML.NAME_ATT);
2080 attribute.setValue(NUM_DOCS_MATCHED);
2081 metadata.setAttributeNode(attribute);
2082
2083 attribute = doc.createAttribute(GSXML.VALUE_ATT);
2084 attribute.setValue(Integer.toString(pids.length));
2085 metadata.setAttributeNode(attribute);
2086
2087 metadataList.appendChild(metadata);
2088
2089 // <documentNodeList>
2090 // <documentNode nodeID="HASHac0a04dd14571c60d7fbfd.4.2"
2091 // docType='hierarchy' nodeType="leaf" />
2092 // ...
2093 // ...
2094 // </documentNodeList>
2095 Element docNodeList = doc.createElement(
2096 GSXML.DOC_NODE_ELEM+GSXML.LIST_MODIFIER);
2097 // for each
2098 for(int i = 0; i < pids.length; i++) {
2099 Element docNode = doc.createElement(GSXML.DOC_NODE_ELEM);
2100 attribute = doc.createAttribute(GSXML.NODE_ID_ATT);
2101 attribute.setValue(pids[i]);
2102 docNode.setAttributeNode(attribute);
2103
2104 attribute = doc.createAttribute(GSXML.DOC_TYPE_ATT);
2105 attribute.setValue("hierarchy");
2106 docNode.setAttributeNode(attribute);
2107
2108 attribute = doc.createAttribute(GSXML.NODE_TYPE_ATT);
2109 attribute.setValue("root");
2110 docNode.setAttributeNode(attribute);
2111 docNodeList.appendChild(docNode);
2112 }
2113
2114 Element responseMsg = createResponseMessage(doc, docNodeList, ex,
2115 GSXML.REQUEST_TYPE_PROCESS, service);
2116 try{
2117 return FedoraCommons.elementToFormattedString(responseMsg);
2118 }catch(TransformerException e) {
2119 return FedoraGS3RunException.xmlToStringConversionFailureResponseMsg
2120 + " " + e;
2121 }
2122 }
2123
2124 public static void main(String args[]) {
2125 try{
2126 // testing default constructor
2127 //FedoraGS3Connection con = new FedoraGS3Connection();
2128
2129 // testing constructor that takes properties file to show initial
2130 // fedora server values
2131 java.io.File propertyFilename
2132 = new java.io.File("fedoraGS3.properties");
2133 FedoraGS3Connection con = new FedoraGS3Connection(propertyFilename);
2134
2135 // DESCRIBE: serviceList, collectionList
2136 System.out.println("serviceList:\n" + con.getServiceList());
2137
2138 System.out.println("collectionList:\n" + con.getCollectionList());
2139
2140 String[] colPIDs = con.getCollections();
2141 String[] collectionNames = con.getCollectionNames(con.getCollections());
2142
2143
2144 for(int i = 0; i < collectionNames.length; i++) {
2145 System.out.println("Describing collections:\n");
2146 System.out.println(con.describeCollection(collectionNames[i]));
2147 System.out.println("Describing collection services:\n"
2148 + con.describeCollectionServices(collectionNames[i]));
2149 }
2150
2151 String[] serviceNames = con.getServiceNames();
2152 for(int i = 0; i < serviceNames.length; i++) {
2153 System.out.println("Describing " + serviceNames[i] + ":\n"
2154 + con.describeCollectionService("demo", serviceNames[i]));
2155 }
2156
2157
2158 // TRYING OUT SPECIAL top-level document metadata retrieval (DLS, DC)
2159 // along with EX of the top-level document:
2160 System.out.println("\nGET META for greenstone:gs2mgdemo-HASH01d667303fe98545f03c14ae:");
2161 System.out.println(con.getDocumentMetadata(new String[]{"greenstone:gs2mgdemo-HASH01d667303fe98545f03c14ae"}));
2162
2163
2164 String[] docIDs = con.getCollectionDocs(colPIDs[0]);
2165 System.out.println("\nGET CONTENT:");
2166 for(int i = 0; i < docIDs.length; i++) {
2167 System.out.println(con.getContent(docIDs[i]));
2168 }
2169
2170 System.out.println("\nGET META:");
2171 for(int i = 0; i < docIDs.length; i++) {
2172 System.out.println(con.getDocumentMetadata(docIDs[i]));
2173 }
2174
2175 String[] getTitlesFor = {
2176 "greenstone:gs2mgdemo-HASH01d667303fe98545f03c14ae",
2177 "greenstone:gs2mgdemo-HASHa568bac1d8d7bd12a0938b",
2178 "greenstone:gs2mgdemo-HASHa568bac1d8d7bd12a0938b-1",
2179 "greenstone:gs2mgdemo-HASH01d667303fe98545f03c14ae-1.7",
2180 "greenstone:gs2mgdemo-HASHa568bac1d8d7bd12a0938b-1.5.1"
2181 };
2182
2183 // first let's display the regular meta for top-level docs and
2184 // their sections
2185 for(int i = 0; i < getTitlesFor.length; i++) {
2186 System.out.println(con.getDocumentMetadata(getTitlesFor[i]));
2187 }
2188
2189 System.out.println("\nTitles are:");
2190 System.out.println(con.getTitleMetadata(getTitlesFor));
2191
2192 System.out.println("\nGET STRUCTURE:");
2193 for(int i = 0; i < docIDs.length; i++) {
2194 System.out.println(con.getChildren(docIDs[i]));
2195 System.out.println(con.getDocumentStructure(docIDs[i]));
2196 }
2197
2198 // TEST ERROR CASES:
2199 System.out.println("\nTESTING ERROR CASES");
2200 System.out.println(con.getContent("greenstone:demo-pinky"));
2201 String[] errorCases = { "greenstone:demo-HASH23d1019b589e2ef6a680e3-1.5.1.5",
2202 "greenstone:demo-pinky" };
2203 System.out.println(con.getContent(errorCases));
2204 System.out.println(con.getDocumentMetadata(errorCases));
2205 System.out.println(con.getDocumentStructure(errorCases));
2206
2207 System.out.println("\nCLASSIFIER BROWSE");
2208 System.out.println(con.browse("gs2mgdemo", //"ClassifierBrowse",
2209 "CL1"));
2210
2211 System.out.println("\nCLASSIFIER BROWSE METADATA RETRIEVE");
2212 String[] classNodeIDs = new String[26];
2213 for(int i = 0; i < classNodeIDs.length; i++) {
2214 int subClassifierNum = i + 1;
2215 classNodeIDs[i] = "CL1." + subClassifierNum;
2216 }
2217 System.out.println(con.browseMetadataRetrieve(//"gs2mgdemo",
2218 classNodeIDs));
2219
2220 System.out.println("Testing query services");
2221 System.out.println("TEXT QUERY:");
2222 Map formControlValsMap = new HashMap();
2223 formControlValsMap.put(MAXDOCS, "100");
2224 formControlValsMap.put(QUERY, "snails");
2225 String searchResponse
2226 = con.query("gs2mgdemo", "TextQuery", formControlValsMap);
2227 System.out.println(searchResponse);
2228
2229 System.out.println("FIELD QUERY:");
2230 formControlValsMap.clear();
2231 formControlValsMap.put(MAXDOCS, "100");
2232 formControlValsMap.put(QUERY, "interview,Gender equality,cyclone");
2233 formControlValsMap.put(FIELDNAME_ATT,
2234 "allFields,docTitles,allFields,allFields");
2235 searchResponse
2236 = con.query("gs2mgdemo", "FieldQuery", formControlValsMap);
2237 System.out.println(searchResponse);
2238
2239 System.exit(0);
2240 }catch(Exception e) {
2241 JOptionPane.showMessageDialog(
2242 null, e, "Error", JOptionPane.ERROR_MESSAGE);
2243 //System.err.println("ERROR: " + e);
2244 e.printStackTrace();
2245 }
2246 }
2247}
Note: See TracBrowser for help on using the repository browser.