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

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

Sometimes (even the) top-level classifier ID contains a decimal point. Need to deal with this.

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