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

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

FedoraConnection.java changed to work with files that have no TOC (Table of Contents) because they have only 1 section. Other source files only have cosmetic changes.

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