View Javadoc

1   /**
2    * Copyright 2010, CSIRO Australia.
3    *
4    * Licensed under the Apache License, Version 2.0 (the "License");
5    * you may not use this file except in compliance with the License.
6    * You may obtain a copy of the License at
7    *
8    *         http://www.apache.org/licenses/LICENSE-2.0
9    *
10   * Unless required by applicable law or agreed to in writing, software
11   * distributed under the License is distributed on an "AS IS" BASIS,
12   * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13   * See the License for the specific language governing permissions and
14   * limitations under the License.
15   */
16  
17  package au.csiro.pidclient;
18  
19  import java.io.BufferedReader;
20  import java.io.IOException;
21  import java.io.InputStream;
22  import java.io.InputStreamReader;
23  import java.io.StringReader;
24  import java.text.MessageFormat;
25  import java.util.ArrayList;
26  import java.util.List;
27  import java.util.Properties;
28  
29  import javax.xml.parsers.DocumentBuilder;
30  import javax.xml.parsers.DocumentBuilderFactory;
31  import javax.xml.parsers.ParserConfigurationException;
32  import javax.xml.xpath.XPath;
33  import javax.xml.xpath.XPathConstants;
34  import javax.xml.xpath.XPathExpression;
35  import javax.xml.xpath.XPathExpressionException;
36  import javax.xml.xpath.XPathFactory;
37  
38  import org.apache.commons.httpclient.HttpClient;
39  import org.apache.commons.httpclient.HttpException;
40  import org.apache.commons.httpclient.HttpStatus;
41  import org.apache.commons.httpclient.HttpsURL;
42  import org.apache.commons.httpclient.NameValuePair;
43  import org.apache.commons.httpclient.methods.PostMethod;
44  import org.apache.commons.httpclient.methods.RequestEntity;
45  import org.apache.commons.httpclient.methods.StringRequestEntity;
46  import org.apache.commons.lang.StringUtils;
47  import org.apache.log4j.Logger;
48  import org.w3c.dom.Document;
49  import org.w3c.dom.Node;
50  import org.w3c.dom.NodeList;
51  import org.xml.sax.InputSource;
52  import org.xml.sax.SAXException;
53  
54  import au.csiro.pidclient.business.AndsPidIdentity;
55  import au.csiro.pidclient.business.AndsPidResponseProperty;
56  
57  /**
58   * This is the main interface to the ANDS PID Client library. It allows the caller to 
59   * interact with the 
60   * <a href="http://www.ands.org.au/services/pid-m2m-identifiers.html">Persistent IDentifier Service</a> 
61   * provided by the 
62   * <a href="http://www.ands.org.au/">Australian National Data Service</a>. You will need to 
63   * register with ANDS to be able to use the service. 
64   * <p><b>Usage:</b>
65   * </p><p>
66   * Create a new instance of the class using either the empty constructor and 
67   * then calling the four setters, or using the constructors. This should be 
68   * compatible with use as a singleton bean in Spring or other DI (dependency 
69   * injection) frameworks. Example:
70   * </p>
71   * <UL>
72   * <li>pidServiceHost - test.ands.org.au</li>
73   * <li>pidServicePort - 8443</li>
74   * <li>pidServicePath - /pids</li>
75   * <li>requestorIdentity.appId - 5d9a4da3580c528ba98d8e6f088dab93f680dd6b</li>
76   * <li>requestorIdentity.identifier - scott</li>
77   * <li>requestorIdentity.authDomain - mycomputer.edu.au</li>
78   * </UL>
79   * <p>
80   * You can then mint new handles using the {@link #mintHandle(HandleType, String) mintHandle} 
81   * method, and manage the properties associated with the handle
82   * {@link #addValue(String, HandleType, String) addValue}, 
83   * {@link #modifyValueByIndex(String, int, String) modifyValueByIndex} and
84   * {@link #deleteValueByIndex(String, int) deleteValueByIndex} methods. Note that these 
85   * methods return the raw XML response as a string. You can also use the FormattedResponse 
86   * versions to get back an interpreted result as a standard Java bean.
87   * 
88   * </p>
89   * Copyright 2010, CSIRO Australia All rights reserved.
90   * 
91   * @author Robert Bridle on 05/02/2010
92   * @version $Revision: 7131 $ $Date: 2010-06-09 14:25:15 +1000 (Wed, 09 Jun 2010) $
93   */
94  public class AndsPidClient
95  {
96      /**
97       * Constant that defines the size of an array for storing triplet data.
98       */
99      private static final int TRIPLE = 3;
100 
101     /**
102      * Constant that defines the logger to be used.
103      */
104     private static final Logger LOG = Logger.getLogger(AndsPidClient.class.getName());
105 
106     /**
107      * Constant that defines the name of properties file to be used.
108      */
109     private static final String PROPERTIES_FILENAME = "/ands-pid-client.properties";
110 
111     /**
112      * The name of the application, to be used by the HTTP client.
113      */
114     private static String applicationName;
115 
116     /**
117      * The name of the method (RESTful web service) to call when minting a new handle.
118      */
119     private static String mintMethodName;
120     
121     /**
122      * The name of the method (RESTful web service) to call when associating a new value with an existing handle.
123      */
124     private static String addValueMethodName;
125     
126     /**
127      * The name of the method (RESTful web service) to call when associating a new value into the index of an existing
128      * handle.
129      */
130     private static String addValueByIndexMethodName;
131 
132     /**
133      * The name of the method (RESTful web service) to call when modifying an existing handle.
134      */
135     private static String modifyValueByIndexMethodName;
136 
137     /**
138      * The name of the method (RESTful web service) to call when deleting an existing handle value.
139      */
140     private static String deleteValueByIndexMethodName;
141     
142     /**
143      * The name of the method (RESTful web service) to call when listing the handles owned by the requestor.
144      */
145     private static String listHandlesMethodName;
146     
147     /**
148      * The name of the method (RESTful web service) to call when retrieving the values associated with a handle.
149      */
150     private static String getHandleMethodName;
151 
152     /**
153      * Represents the identity information of the caller.
154      */
155     private AndsPidIdentity requestorIdentity;
156 
157     /**
158      * The ANDS Persistent Identifier host name.
159      */
160     private String pidServiceHost;
161 
162     /**
163      * The ANDS Persistent Identifier port number.
164      */
165     private int pidServicePort;
166 
167     /**
168      * The ANDS Persistent Identifier path name (web application context name).
169      */
170     private String pidServicePath;
171 
172     /**
173      * The possible types of properties that can be associated with a handle. 
174      * Each handle (PID) can carry multiple (max of around 100) properties. 
175      */
176     public enum HandleType
177     {
178         /**
179          * A property with no associated value. 
180          */
181         EMPTY(""),
182         /**
183          * A property with a URL value.
184          */
185         URL("URL"),
186         /**
187          * A property with a descriptive text value.
188          */
189         DESC("DESC");
190 
191         /**
192          * The value of the enumeration understood by the ANDS PID service.
193          */
194         private final String value;
195 
196         HandleType(String value)
197         {
198             this.value = value;
199         }
200 
201         /**
202          * @return the value of the enumeration.
203          */
204         public String value()
205         {
206             return this.value;
207         }
208         
209         /**
210          * @return whether this enumeration is empty.
211          */
212         public boolean isEmpty()
213         {
214             return EMPTY.value().equals(this.value);
215         }
216     }
217 
218     /**
219      * Loads the specified properties file.
220      */
221     private static void loadProperties()
222     {
223         InputStream is = AndsPidResponse.class.getResourceAsStream(PROPERTIES_FILENAME);
224         Properties props = new Properties();
225         try
226         {
227             props.load(is);
228             applicationName = props.getProperty("application.name");
229             mintMethodName = props.getProperty("method.mint");
230             addValueMethodName = props.getProperty("method.addValue");
231             addValueByIndexMethodName = props.getProperty("method.addValueByIndex");
232             modifyValueByIndexMethodName = props.getProperty("method.modifyValueByIndex");
233             deleteValueByIndexMethodName = props.getProperty("method.deleteValueByIndex");
234             listHandlesMethodName = props.getProperty("method.listHandles");
235             getHandleMethodName = props.getProperty("method.getHandle");
236         }
237         catch (IOException e)
238         {
239             LOG.error("Could not load properties file: " + PROPERTIES_FILENAME, e);
240         }
241     }
242 
243     /**
244      * Default constructor. You will still need to supply the configuration data 
245      * via the public setters.
246      */
247     public AndsPidClient()
248     {
249         this(null, 0, null, null, null, null);
250     }
251 
252     /**
253      * @param pidServiceHost
254      *            the ANDS Persistent Identifier host name.
255      * @param pidServicePort
256      *            the ANDS Persistent Identifier port number.
257      * @param pidServicePath
258      *            the ANDS Persistent Identifier path name (web application context name).
259      * @param appId
260      *            the unique Id provided to the caller upon IP registration with the ANDS Persistent Identifier service.
261      * @param identifier
262      *            the identifier or name of the repository calling the service.
263      * @param authDomain
264      *            the domain of the organisation calling the service.
265      */
266     public AndsPidClient(String pidServiceHost, int pidServicePort, String pidServicePath, String appId,
267             String identifier, String authDomain)
268     {
269         this(pidServiceHost, pidServicePort, pidServicePath, new AndsPidIdentity(appId, identifier, authDomain));
270     }
271 
272     /**
273      * @param pidServiceHost
274      *            the ANDS Persistent Identifier host name.
275      * @param pidServicePort
276      *            the ANDS Persistent Identifier port number.
277      * @param pidServicePath
278      *            the ANDS Persistent Identifier path name (web application context name).
279      * @param requestorIdentity
280      *            represents the identity information of the caller {@link AndsPidIdentity}.
281      */
282     public AndsPidClient(String pidServiceHost, int pidServicePort, String pidServicePath,
283             AndsPidIdentity requestorIdentity)
284     {
285         this.setPidServiceHost(pidServiceHost);
286         this.setPidServicePort(pidServicePort);
287         this.setPidServicePath(pidServicePath);
288         this.setRequestorIdentity(requestorIdentity);
289         loadProperties();
290     }
291 
292     /**
293      * Responsible for the creation of a handle.
294      * <p>
295      * If the type and value arguments are both empty, a handle with no values is created. The handle is assigned to an
296      * owner, specified by the {@link AndsPidIdentity#getAppId()} value. If the owner is not known to the handle system,
297      * an owner is created from the {@link AndsPidIdentity#getIdentifier()} and {@link AndsPidIdentity#getIdentifier()}
298      * values.
299      * 
300      * @param type
301      *            the type {@link HandleType} of value which will be associated with the newly minted handle.
302      * @param value
303      *            the value which will be associated with the newly minted handle.
304      * @return a formatted XML response that contains a handle, the handle is associated with the value argument.
305      * @throws IllegalStateException
306      *             thrown if the parameters need to call the ANDS PID service have not been provided.
307      * @throws IllegalArgumentException
308      *             thrown when method is called with invalid arguments.
309      * @throws IOException
310      *             thrown when attempting to read response.
311      * @throws HttpException
312      *             thrown when attempting to execute method call.
313      */
314     public String mintHandle(HandleType type, String value) throws IllegalStateException, IllegalArgumentException,
315             HttpException, IOException
316     {
317         this.validateState();
318 
319         this.validateMintHandleArguments(type, value);
320 
321         NameValuePair[] queryParams = {
322                 new NameValuePair("type", type.value()),
323                 new NameValuePair("value", value)
324               };
325 
326         return executeMethod(queryParams, mintMethodName);
327     }
328 
329     /**
330      * Responsible for the creation of a handle.
331      * <p>
332      * If the type and value arguments are both empty, a handle with no values is created. The handle is assigned to an
333      * owner, specified by the {@link AndsPidIdentity#getAppId()} value. If the owner is not known to the handle system,
334      * an owner is created from the {@link AndsPidIdentity#getIdentifier()} and {@link AndsPidIdentity#getIdentifier()}
335      * values.
336      * <p>
337      * The XML response is parsed and returned by the object {@link AndsPidResponse}.
338      * 
339      * @param type
340      *            the type {@link HandleType} of value which will be associated with the newly minted handle.
341      * @param value
342      *            the value which will be associated with the newly minted handle.
343      * @return the ANDS Persistent Identifier service response represented by the object {@link AndsPidResponse}.
344      * @throws IllegalStateException
345      *             thrown if the parameters need to call the ANDS PID service have not been provided.
346      * @throws IllegalArgumentException
347      *             thrown when method is called with invalid arguments.
348      * @throws HttpException
349      *             thrown when attempting to execute method call.
350      * @throws IOException
351      *             thrown when attempting to read response.
352      * @throws XPathExpressionException
353      *             thrown when attempting to execute XPath on XML response.
354      * @throws ParserConfigurationException
355      *             thrown when attempting to convert response to an XML document.
356      * @throws SAXException
357      *             thrown when attempting to convert response to an XML document.
358      */
359     public AndsPidResponse mintHandleFormattedResponse(HandleType type, String value) throws IllegalStateException,
360             IllegalArgumentException, HttpException, IOException, XPathExpressionException,
361             ParserConfigurationException, SAXException
362     {
363         return populateAndsPidResponse(mintHandle(type, value));
364     }
365     
366     /**
367      * Responsible for the creation of a handle with a value at a specific index.
368      * <p>
369      * If the type and value arguments are both empty, a handle with no values is created. The handle is assigned
370      * to an owner, specified by the {@link AndsPidIdentity#getAppId()} value. If the owner is not known to the handle
371      * system, an owner is created from the {@link AndsPidIdentity#getIdentifier()} and
372      * {@link AndsPidIdentity#getIdentifier()} values.
373      * 
374      * @param type
375      *            the type {@link HandleType} of value which will be associated with the newly minted handle.
376      * @param index
377      *            the index of the value which will be associated with the newly minted handle.
378      * @param value
379      *            the value which will be associated with the newly minted handle.
380      * @return a formatted XML response that contains a handle, the handle is associated with the value argument.
381      * @throws IllegalStateException
382      *             thrown if the parameters need to call the ANDS PID service have not been provided.
383      * @throws IllegalArgumentException
384      *             thrown when method is called with invalid arguments.
385      * @throws IOException
386      *             thrown when attempting to read response.
387      * @throws HttpException
388      *             thrown when attempting to execute method call.
389      */
390     public String mintHandle(HandleType type, int index, String value) throws IllegalStateException,
391             IllegalArgumentException, HttpException, IOException
392     {
393         this.validateState();
394 
395         this.validateMintHandleArguments(type, value);
396 
397         NameValuePair[] queryParams = {
398                 new NameValuePair("type", type.value()),
399                 new NameValuePair("index", String.valueOf(index)),
400                 new NameValuePair("value", value)
401               };
402         return executeMethod(queryParams, mintMethodName);
403     }
404     
405     /**
406      * Responsible for the creation of a handle with a value at a specific index.
407      * <p>
408      * If the type and value arguments are both empty, a handle with no values is created. The handle is assigned
409      * to an owner, specified by the {@link AndsPidIdentity#getAppId()} value. If the owner is not known to the handle
410      * system, an owner is created from the {@link AndsPidIdentity#getIdentifier()} and
411      * {@link AndsPidIdentity#getIdentifier()} values.
412      * <p>
413      * The XML response is parsed and returned by the object {@link AndsPidResponse}.
414      * 
415      * @param type
416      *            the type {@link HandleType} of value which will be associated with the newly minted handle.
417      * @param index
418      *            the index of the value which will be associated with the newly minted handle.
419      * @param value
420      *            the value which will be associated with the newly minted handle.
421      * @return the ANDS Persistent Identifier service response represented by the object {@link AndsPidResponse}.
422      * @throws IllegalStateException
423      *             thrown if the parameters need to call the ANDS PID service have not been provided.
424      * @throws IllegalArgumentException
425      *             thrown when method is called with invalid arguments.
426      * @throws HttpException
427      *             thrown when attempting to execute method call.
428      * @throws IOException
429      *             thrown when attempting to read response.
430      * @throws XPathExpressionException
431      *             thrown when attempting to execute XPath on XML response.
432      * @throws ParserConfigurationException
433      *             thrown when attempting to convert response to an XML document.
434      * @throws SAXException
435      *             thrown when attempting to convert response to an XML document.
436      */
437     public AndsPidResponse mintHandleFormattedResponse(HandleType type, int index, String value)
438             throws IllegalStateException, IllegalArgumentException, HttpException, IOException,
439             XPathExpressionException, ParserConfigurationException, SAXException
440     {
441         return populateAndsPidResponse(mintHandle(type, index, value));
442     }
443 
444     /**
445      * Adds a value to an existing handle.
446      * <p>
447      * Only the owner of the handle is able to add a value to the handle and only values of type {@link HandleType#URL}
448      * or {@link HandleType#DESC} can be added.
449      * 
450      * @param handle
451      *            the handle to which a new value is to be associated.
452      * @param type
453      *            the type of the value to be added to the handle, must be either {@link HandleType#URL} or
454      *            {@link HandleType#DESC}.
455      * @param value
456      *            the value to be added to the handle.
457      * @return a formatted XML response that contains the details of the updated handle.
458      * @throws IllegalStateException
459      *             thrown if the parameters need to call the ANDS PID service have not been provided.
460      * @throws IllegalArgumentException
461      *             thrown when method is called with invalid arguments.
462      * @throws IOException
463      *             thrown when attempting to read response.
464      * @throws HttpException
465      *             thrown when attempting to execute method call.
466      */
467     @SuppressWarnings(value = "all")
468     public String addValue(String handle, HandleType type, String value) throws IllegalStateException,
469             IllegalArgumentException, HttpException, IOException
470     {
471         this.validateState();
472 
473         if (StringUtils.isEmpty(handle) || StringUtils.isEmpty(value) || type == null || type.equals(HandleType.EMPTY))
474         {
475             throw new IllegalArgumentException(MessageFormat.format(
476                     "The method addValue() can not be called with null or empty arguments:\n type= {0}\n value= {1}\n",
477                     new Object[] { (type == null) ? null : type.value(), value }));
478         }
479 
480         NameValuePair[] queryParams = {
481                 new NameValuePair("type", type.value()),
482                 new NameValuePair("handle", handle),
483                 new NameValuePair("value", value)
484               };
485         return executeMethod(queryParams, addValueMethodName);
486     }
487 
488     /**
489      * Adds a value to an existing handle.
490      * <p>
491      * Only the owner of the handle is able to add a value to the handle and only values of type {@link HandleType#URL}
492      * or {@link HandleType#DESC} can be added.
493      * <p>
494      * The XML response is parsed and returned by the object {@link AndsPidResponse}.
495      * 
496      * @param handle
497      *            the handle to which a new value is to be associated.
498      * @param type
499      *            the type of the value to be added to the handle, must be either {@link HandleType#URL} or
500      *            {@link HandleType#DESC}.
501      * @param value
502      *            the value to be minted.
503      * @return the ANDS Persistent Identifier service response represented by the object {@link AndsPidResponse}.
504      * @throws IllegalStateException
505      *             thrown if the parameters need to call the ANDS PID service have not been provided.
506      * @throws IllegalArgumentException
507      *             thrown when method is called with invalid arguments.
508      * @throws HttpException
509      *             thrown when attempting to execute method call.
510      * @throws IOException
511      *             thrown when attempting to read response.
512      * @throws XPathExpressionException
513      *             thrown when attempting to execute XPath on XML response.
514      * @throws ParserConfigurationException
515      *             thrown when attempting to convert response to an XML document.
516      * @throws SAXException
517      *             thrown when attempting to convert response to an XML document.
518      */
519     public AndsPidResponse addValueFormattedResponse(String handle, HandleType type, String value)
520             throws IllegalStateException, IllegalArgumentException, HttpException, IOException,
521             XPathExpressionException, ParserConfigurationException, SAXException
522     {
523         // populate and return the response object
524         return populateAndsPidResponse(this.addValue(handle, type, value));
525     }
526     
527     /**
528      * Adds a value to a particular index of an existing handle.
529      * <p>
530      * Only the owner of the handle is able to add a value to the handle and only values of type {@link HandleType#URL}
531      * or {@link HandleType#DESC} can be added.
532      * 
533      * @param handle
534      *            the handle to which a new value is to be associated.
535      * @param index
536      *            the index in which to add the value.
537      * @param type
538      *            the type of the value to be added to the handle, must be either {@link HandleType#URL} or
539      *            {@link HandleType#DESC}.
540      * @param value
541      *            the value to be added to the handle.
542      * @return a formatted XML response that contains the details of the updated handle.
543      * @throws IllegalStateException
544      *             thrown if the parameters need to call the ANDS PID service have not been provided.
545      * @throws IllegalArgumentException
546      *             thrown when method is called with invalid arguments.
547      * @throws IOException
548      *             thrown when attempting to read response.
549      * @throws HttpException
550      *             thrown when attempting to execute method call.
551      */
552     @SuppressWarnings(value = "all")
553     public String addValueByIndex(String handle, int index, HandleType type, String value)
554             throws IllegalStateException, IllegalArgumentException, HttpException, IOException
555     {
556         this.validateState();
557 
558         if (StringUtils.isEmpty(handle) || StringUtils.isEmpty(value) || type == null || type.isEmpty())
559         {
560             throw new IllegalArgumentException(MessageFormat.format(
561                     "The method addValueByIndex() can not be called with null or empty arguments:\n type= {0}\n value= {1}\n",
562                     new Object[] { (type == null) ? null : type.value(), value }));
563         }
564 
565         NameValuePair[] queryParams = {
566                 new NameValuePair("handle", handle),
567                 new NameValuePair("index", String.valueOf(index)),
568                 new NameValuePair("type", type.value()),                
569                 new NameValuePair("value", value)
570               };
571         return executeMethod(queryParams, addValueByIndexMethodName);
572     }
573 
574     /**
575      * Adds a value to a particular index of an existing handle.
576      * <p>
577      * Only the owner of the handle is able to add a value to the handle and only values of type {@link HandleType#URL}
578      * or {@link HandleType#DESC} can be added.
579      * <p>
580      * The XML response is parsed and returned by the object {@link AndsPidResponse}.
581      * 
582      * @param handle
583      *            the handle to which a new value is to be associated.
584      * @param index
585      *            the index in which to add the value.
586      * @param type
587      *            the type of the value to be added to the handle, must be either {@link HandleType#URL} or
588      *            {@link HandleType#DESC}.
589      * @param value
590      *            the value to be minted.
591      * @return the ANDS Persistent Identifier service response represented by the object {@link AndsPidResponse}.
592      * @throws IllegalStateException
593      *             thrown if the parameters need to call the ANDS PID service have not been provided.
594      * @throws IllegalArgumentException
595      *             thrown when method is called with invalid arguments.
596      * @throws HttpException
597      *             thrown when attempting to execute method call.
598      * @throws IOException
599      *             thrown when attempting to read response.
600      * @throws XPathExpressionException
601      *             thrown when attempting to execute XPath on XML response.
602      * @throws ParserConfigurationException
603      *             thrown when attempting to convert response to an XML document.
604      * @throws SAXException
605      *             thrown when attempting to convert response to an XML document.
606      */
607     public AndsPidResponse addValueByIndexFormattedResponse(String handle, int index, HandleType type, String value)
608             throws IllegalStateException, IllegalArgumentException, HttpException, IOException,
609             XPathExpressionException, ParserConfigurationException, SAXException
610     {
611         // populate and return the response object
612         return populateAndsPidResponse(this.addValueByIndex(handle, index, type, value));
613     }
614 
615     /**
616      * Changes a value associated with an existing handle.
617      * <p>
618      * Only the owner of the handle is able to modify a value associated with the handle and only values with the type
619      * {@link HandleType#URL} or {@link HandleType#DESC} can be modified.
620      * 
621      * @param handle
622      *            the handle that is to have one of its values modified.
623      * @param index
624      *            the index of the value to modify.
625      * @param newValue
626      *            the new value.
627      * @return a formatted XML response that contains the details of the updated handle.
628      * @throws IllegalStateException
629      *             thrown if the parameters need to call the ANDS PID service have not been provided.
630      * @throws IllegalArgumentException
631      *             thrown when method is called with invalid arguments.
632      * @throws HttpException
633      *             thrown when attempting to execute method call.
634      * @throws IOException
635      *             thrown when attempting to read response.
636      */
637     @SuppressWarnings(value = "all")
638     public String modifyValueByIndex(String handle, int index, String newValue) throws IllegalStateException,
639             IllegalArgumentException, HttpException, IOException
640     {
641         this.validateState();
642 
643         if (StringUtils.isEmpty(handle) || StringUtils.isEmpty(newValue))
644         {
645             throw new IllegalArgumentException(
646                     MessageFormat
647                             .format(
648                                     "The method modifyValueByIndex() can not be called with null or empty arguments:" +
649                                     "\n handle={0}\n newValue={1}\n",
650                                     new Object[] { handle, newValue }));
651         }
652 
653         NameValuePair[] queryParams = {
654                 new NameValuePair("index", String.valueOf(index)),
655                 new NameValuePair("handle", handle),
656                 new NameValuePair("value", newValue)
657               };
658         return executeMethod(queryParams, modifyValueByIndexMethodName);
659     }
660 
661     /**
662      * Changes a value associated with an existing handle.
663      * <p>
664      * Only the owner of the handle is able to modify a value associated with the handle and only values with the type
665      * {@link HandleType#URL} or {@link HandleType#DESC} can be modified.
666      * <p>
667      * The XML response is parsed and returned by the object {@link AndsPidResponse}.
668      * 
669      * @param handle
670      *            the handle that is to have one of its values modified.
671      * @param index
672      *            the index of the value to modify.
673      * @param newValue
674      *            the new value.
675      * @return the ANDS Persistent Identifier service response represented by the object {@link AndsPidResponse}.
676      * @throws IllegalStateException
677      *             thrown if the parameters need to call the ANDS PID service have not been provided.
678      * @throws IllegalArgumentException
679      *             thrown when method is called with invalid arguments.
680      * @throws HttpException
681      *             thrown when attempting to execute method call.
682      * @throws IOException
683      *             thrown when attempting to read response.
684      * @throws XPathExpressionException
685      *             thrown when attempting to execute XPath on XML response.
686      * @throws ParserConfigurationException
687      *             thrown when attempting to convert response to an XML document.
688      * @throws SAXException
689      *             thrown when attempting to convert response to an XML document.
690      */
691     public AndsPidResponse modifyValueByIndexFormattedResponse(String handle, int index, String newValue)
692             throws IllegalStateException, IllegalArgumentException, HttpException, IOException,
693             XPathExpressionException, ParserConfigurationException, SAXException
694     {
695         return populateAndsPidResponse(modifyValueByIndex(handle, index, newValue));
696     }
697 
698     /**
699      * Deletes a value associated with an existing handle.
700      * <p>
701      * Only the owner of the handle is able to delete a value associated to the handle and only values of type
702      * {@link HandleType#URL} or {@link HandleType#DESC} can be deleted.
703      * 
704      * @param handle
705      *            the handle that is to have one of its values deleted.
706      * @param index
707      *            the index of the value to be deleted.
708      * @return a formatted XML response that contains the details of the updated handle.
709      * @throws IllegalStateException
710      *             thrown if the parameters need to call the ANDS PID service have not been provided.
711      * @throws IllegalArgumentException
712      *             thrown when method is called with invalid arguments.
713      * @throws HttpException
714      *             thrown when attempting to execute method call.
715      * @throws IOException
716      *             thrown when attempting to read response.
717      */
718     public String deleteValueByIndex(String handle, int index) throws IllegalStateException, IllegalArgumentException,
719             HttpException, IOException
720     {
721         this.validateState();
722 
723         if (StringUtils.isEmpty(handle))
724         {
725             throw new IllegalArgumentException(MessageFormat.format(
726                     "The method deleteValueByIndex() can not be called with null or empty arguments:\n handle={0}\n",
727                     new Object[] { handle }));
728         }
729       
730         NameValuePair[] queryParams = {
731                 new NameValuePair("index", String.valueOf(index)),
732                 new NameValuePair("handle", handle)};
733         return executeMethod(queryParams, deleteValueByIndexMethodName);
734     }
735 
736     /**
737      * Deletes a value associated with an existing handle. Only values with the type {@link HandleType#URL} or
738      * {@link HandleType#DESC} can be deleted.
739      * <p>
740      * Only the owner of the handle is able to delete a value associated to the handle and only values of type
741      * {@link HandleType#URL} or {@link HandleType#DESC} can be deleted.
742      * <p>
743      * The XML response is parsed and returned by the object {@link AndsPidResponse}.
744      * 
745      * @param handle
746      *            the handle that is to have one of its indexes deleted.
747      * @param index
748      *            the index to be deleted.
749      * @return the ANDS Persistent Identifier service response represented by the object {@link AndsPidResponse}.
750      * @throws IllegalStateException
751      *             thrown if the parameters need to call the ANDS PID service have not been provided.
752      * @throws IllegalArgumentException
753      *             thrown when method is called with invalid arguments.
754      * @throws HttpException
755      *             thrown when attempting to execute method call.
756      * @throws IOException
757      *             thrown when attempting to read response.
758      * @throws XPathExpressionException
759      *             thrown when attempting to execute XPath on XML response.
760      * @throws ParserConfigurationException
761      *             thrown when attempting to convert response to an XML document.
762      * @throws SAXException
763      *             thrown when attempting to convert response to an XML document.
764      */
765     public AndsPidResponse deleteValueByIndexFormattedResponse(String handle, int index) throws IllegalStateException,
766             IllegalArgumentException, HttpException, IOException, XPathExpressionException,
767             ParserConfigurationException, SAXException
768     {
769         return populateAndsPidResponse(deleteValueByIndex(handle, index));
770     }
771 
772     /**
773      * List the handles owned by the caller of the ANDS PID service.
774      * <p>
775      * This service is intended for listing a small number of handles in a GUI environment, therefore its response is
776      * limited in the number of handles returned.
777      * 
778      * @return a formatted XML response that contains the details of the handles owned by the caller.
779      * @throws IllegalStateException
780      *             thrown if the parameters need to call the ANDS PID service have not been provided.
781      * @throws HttpException
782      *             thrown when attempting to execute method call.
783      * @throws IOException
784      *             thrown when attempting to read response.
785      */
786     @SuppressWarnings(value = "all")
787     public String listHandles() throws IllegalStateException, HttpException, IOException
788     {
789         this.validateState();
790         NameValuePair[] queryParams = {new NameValuePair()};
791         return executeMethod(queryParams, listHandlesMethodName);
792     }
793 
794     /**
795      * List the handles owned by the caller of the ANDS PID service.
796      * <p>
797      * This service is intended for listing a small number of handles in a GUI environment, therefore its response is
798      * limited in the number of handles returned.
799      * <p>
800      * The XML response is parsed and returned by the object {@link AndsPidResponse}.
801      * 
802      * @return the ANDS Persistent Identifier service response represented by the object {@link AndsPidResponse}.
803      * @throws IllegalStateException
804      *             thrown if the parameters need to call the ANDS PID service have not been provided.
805      * @throws HttpException
806      *             thrown when attempting to execute method call.
807      * @throws IOException
808      *             thrown when attempting to read response.
809      * @throws XPathExpressionException
810      *             thrown when attempting to execute XPath on XML response.
811      * @throws ParserConfigurationException
812      *             thrown when attempting to convert response to an XML document.
813      * @throws SAXException
814      *             thrown when attempting to convert response to an XML document.
815      */
816     public AndsPidResponse listHandlesFormattedResponse() throws IllegalStateException, HttpException, IOException,
817             XPathExpressionException, ParserConfigurationException, SAXException
818     {
819         return populateAndsPidResponse(listHandles());
820     }
821     
822     /**
823      * Retrieves the values associated with a given handle.
824      * 
825      * @param handle
826      *            the handle whose details are to be retrieved.
827      * @return a formatted XML response that contains the details of the handle.
828      * @throws IllegalStateException
829      *             thrown if the parameters need to call the ANDS PID service have not been provided.
830      * @throws IllegalArgumentException
831      *             thrown when method is called with invalid arguments.
832      * @throws HttpException
833      *             thrown when attempting to execute method call.
834      * @throws IOException
835      *             thrown when attempting to read response.
836      */
837     @SuppressWarnings(value = "all")
838     public String getHandle(String handle) throws IllegalStateException, IllegalArgumentException,
839             HttpException, IOException
840     {
841         this.validateState();
842 
843         if (StringUtils.isEmpty(handle))
844         {
845             throw new IllegalArgumentException(MessageFormat.format(
846                     "The method getHandle() can not be called with null or empty arguments:\n handle={0}\n",
847                     new Object[] { handle }));
848         }
849 
850         NameValuePair[] queryParams = {new NameValuePair("handle", handle)};
851         return executeMethod(queryParams, getHandleMethodName);
852     }
853 
854     /**
855      * Retrieves the values associated with a given handle.
856      * <p>
857      * The XML response is parsed and returned by the object {@link AndsPidResponse}.
858      * 
859      * @param handle
860      *            the handle whose details are to be retrieved.
861      * @return the ANDS Persistent Identifier service response represented by the object {@link AndsPidResponse}.
862      * @throws IllegalStateException
863      *             thrown if the parameters need to call the ANDS PID service have not been provided.
864      * @throws IllegalArgumentException
865      *             thrown when method is called with invalid arguments.
866      * @throws HttpException
867      *             thrown when attempting to execute method call.
868      * @throws IOException
869      *             thrown when attempting to read response.
870      * @throws XPathExpressionException
871      *             thrown when attempting to execute XPath on XML response.
872      * @throws ParserConfigurationException
873      *             thrown when attempting to convert response to an XML document.
874      * @throws SAXException
875      *             thrown when attempting to convert response to an XML document.
876      */
877     public AndsPidResponse getHandleFormattedResponse(String handle) throws IllegalStateException,
878             IllegalArgumentException, HttpException, IOException, XPathExpressionException,
879             ParserConfigurationException, SAXException
880     {
881         return populateAndsPidResponse(getHandle(handle));
882     }
883 
884     /**
885      * Constructs and executes an HTTP POST call.
886      * 
887      * @param queryParams
888      *            the array of query parameters to provide the POST call.
889      * @param methodName
890      *            the method to call.
891      * @return a formatted XML response.
892      * @throws IOException
893      *             thrown when attempting to read response.
894      * @throws HttpException
895      *             thrown when attempting to execute method call.
896      */
897     private String executeMethod(NameValuePair[] queryParams, String methodName) throws HttpException, IOException
898     {
899         HttpsURL url = new HttpsURL(/* String user */"", /* String password */"", this.getPidServiceHost(), this
900                 .getPidServicePort(), this.getPidServicePath());
901 
902         // if no path has been specified (i.e. path value is just '/') then we have:
903         // http://test.org.au:80/mint?type=URL&value=<some value>
904         if ("/".equals(url.getPath()))
905         {
906             url.setPath(url.getPath() + methodName);
907         }
908         else
909         // if a path has been specified then we have: http://test.org.au:80/<some path>/mint?type=URL&value=<some value>
910         {
911             url.setPath(url.getPath() + "/" + methodName);
912         }
913 
914         String identityXML = this.getRequestorIdentity().toXML(methodName);
915 
916         return executePostMethod(url.toString(), queryParams, identityXML);
917 
918     }
919 
920     /**
921      * Calls a POST method of the ANDS Persistent Identifier service in a RESTful web service manner. The query string
922      * of the URI defines the type of operation that is to be performed. The request body contains an XML fragment that
923      * identifies the caller.
924      * 
925      * @param postMethodURL
926      *            the URI of the RESTful ANDS Persistent Identifier web service.
927      * @param params
928      *            the array of query parameters to provide the POST call.
929      * @param identityXML
930      *            an XML fragment that details the identity of the caller.
931      * @return a formatted XML response.
932      * @throws IOException
933      *             thrown when attempting to read response.
934      * @throws HttpException
935      *             thrown when attempting to execute method call.
936      */
937     private String executePostMethod(String postMethodURL, NameValuePair[] params, String identityXML) throws HttpException, IOException
938     {
939         LOG.debug("Post method URL: " + postMethodURL);
940         LOG.debug("Identity XML: " + identityXML);
941 
942         HttpClient client = new HttpClient();
943         client.getParams().setParameter("http.useragent", applicationName);
944         client.getParams().setParameter("Content-Type", "text/xml");
945         client.getParams().setParameter("Content-Encoding", "UTF-8");
946 
947         PostMethod method = new PostMethod(postMethodURL);
948 
949         BufferedReader br = null;
950         StringBuffer strBuf = new StringBuffer();
951 
952         try
953         {
954             RequestEntity entity = new StringRequestEntity(identityXML, "text/xml", "UTF-8");
955             client.getParams().setParameter("Content-Length", entity.getContentLength());
956             method.setRequestEntity(entity);
957             method.setQueryString(params);
958             int returnCode = client.executeMethod(method);
959             if (returnCode == HttpStatus.SC_NOT_IMPLEMENTED)
960             {
961                 LOG.error("The post method is not implemented by this URI");
962                 // still consume the response body
963                 method.getResponseBodyAsString();
964             }
965             else
966             {
967                 br = new BufferedReader(new InputStreamReader(method.getResponseBodyAsStream()));
968                 String readLine;
969                 while (((readLine = br.readLine()) != null))
970                 {
971                     LOG.debug(readLine);
972                     strBuf.append(readLine);
973                 }
974             }
975         }
976         finally
977         {
978             if (br != null)
979             {
980                 br.close();
981             }
982             method.releaseConnection();
983         }
984 
985         return strBuf.toString();
986     }
987 
988     /**
989      * Parses an XML document which contains an ANDS PID service response for a node that specifies whether the service
990      * call was successful.
991      * 
992      * @param doc
993      *            an XML document of the ANDS PID service response.
994      * @return whether the response represents a success
995      * @throws XPathExpressionException
996      *             thrown when attempting to execute XPath on XML response.
997      * @throws ParserConfigurationException
998      *             thrown when attempting to convert response to an XML document.
999      * @throws SAXException
1000      *             thrown when attempting to convert response to an XML document.
1001      * @throws IOException
1002      *             thrown when attempting to read response.
1003      */
1004     @SuppressWarnings(value = "all")
1005     private boolean parseForSuccess(Document doc) throws XPathExpressionException, ParserConfigurationException,
1006             SAXException, IOException
1007     {
1008         XPathFactory factory = XPathFactory.newInstance();
1009         XPath xpath = factory.newXPath();
1010 
1011         // whether <response type="success"> was returned
1012         XPathExpression expr = xpath.compile("//response[@type]");
1013         Object result = expr.evaluate(doc, XPathConstants.NODESET);
1014         NodeList nodes = (NodeList) result;
1015         for (int i = 0; i < nodes.getLength(); i++)
1016         {
1017             for (int j = 0; j < nodes.item(i).getAttributes().getLength(); j++)
1018             {
1019                 Node node = (Node) nodes.item(i).getAttributes().item(j);
1020                 return "success".equals(node.getNodeValue());
1021             }
1022         }
1023         return false;
1024     }
1025 
1026     /**
1027      * Parses an XML document which contains an ANDS PID service response 
1028      * for a node that specifies what the response message is.
1029      * 
1030      * @param doc
1031      *            an XML document of the ANDS PID service response.
1032      * @return the response message
1033      * @throws XPathExpressionException
1034      *             thrown when attempting to execute XPath on XML response.
1035      * @throws ParserConfigurationException
1036      *             thrown when attempting to convert response to an XML document.
1037      * @throws SAXException
1038      *             thrown when attempting to convert response to an XML document.
1039      * @throws IOException
1040      *             thrown when attempting to read response.
1041      */
1042     @SuppressWarnings(value = "all")
1043     private String parseForMessage(Document doc) throws XPathExpressionException, ParserConfigurationException,
1044             SAXException, IOException
1045     {
1046         XPathFactory factory = XPathFactory.newInstance();
1047         XPath xpath = factory.newXPath();
1048 
1049         XPathExpression expr = xpath.compile("//response/message");
1050         Object result = expr.evaluate(doc, XPathConstants.NODESET);
1051         NodeList nodes = (NodeList) result;
1052         for (int i = 0; i < nodes.getLength(); i++)
1053         {
1054             return nodes.item(i).getTextContent();
1055         }
1056         return null;
1057     }
1058     
1059     /**
1060      * Parses an XML document which contains an ANDS PID service response for the nodes specifying the handles that were
1061      * used in the service call.
1062      * 
1063      * @param doc
1064      *            an XML document of the ANDS PID service response.
1065      * @return the handles associated with the service call.
1066      * @throws XPathExpressionException
1067      *             thrown when attempting to execute XPath on XML response.
1068      * @throws ParserConfigurationException
1069      *             thrown when attempting to convert response to an XML document.
1070      * @throws SAXException
1071      *             thrown when attempting to convert response to an XML document.
1072      * @throws IOException
1073      *             thrown when attempting to read response.
1074      */
1075     private List<String> parseForHandles(Document doc) throws XPathExpressionException, ParserConfigurationException,
1076             SAXException, IOException
1077     {
1078         List<String> handles = new ArrayList<String>();
1079 
1080         XPathFactory factory = XPathFactory.newInstance();
1081         XPath xpath = factory.newXPath();
1082 
1083         // look for the tag: <identifier handle="XXXX/X">
1084         XPathExpression expr = xpath.compile("//identifier[@handle]");
1085         Object result = expr.evaluate(doc, XPathConstants.NODESET);
1086         NodeList nodes = (NodeList) result;
1087         for (int i = 0; i < nodes.getLength(); i++)
1088         {
1089             for (int j = 0; j < nodes.item(i).getAttributes().getLength(); j++)
1090             {
1091                 Node node = (Node) nodes.item(i).getAttributes().item(j);
1092                 String handle = node.getNodeValue();
1093                 handles.add(handle);
1094             }
1095         }
1096         return handles;
1097     }
1098 
1099     /**
1100      * Parses an XML document which contains an ANDS PID service response for the nodes specifying the properties
1101      * associated with a handle.
1102      * 
1103      * @param doc
1104      *            an XML document of the ANDS PID service response.
1105      * @return the properties associated with the handle used in the service call.
1106      * @throws XPathExpressionException
1107      *             thrown when attempting to execute XPath on XML response.
1108      * @throws ParserConfigurationException
1109      *             thrown when attempting to convert response to an XML document.
1110      * @throws SAXException
1111      *             thrown when attempting to convert response to an XML document.
1112      * @throws IOException
1113      *             thrown when attempting to read response.
1114      */
1115     private static List<AndsPidResponseProperty> parseForProperties(Document doc)
1116             throws XPathExpressionException, ParserConfigurationException, SAXException, IOException
1117     {
1118         List<AndsPidResponseProperty> properties = new ArrayList<AndsPidResponseProperty>();
1119 
1120         XPathFactory factory = XPathFactory.newInstance();
1121         XPath xpath = factory.newXPath();
1122 
1123         // look for the tags: <property index="X" type="XXXX" values="XXXX"/>
1124         XPathExpression expr = xpath.compile("//property[@index]");
1125         Object result = expr.evaluate(doc, XPathConstants.NODESET);
1126         NodeList nodes = (NodeList) result;
1127         for (int i = 0; i < nodes.getLength(); i++)
1128         {
1129             String[] triple = new String[TRIPLE];
1130             for (int j = 0; j < Math.min(TRIPLE, nodes.item(i).getAttributes().getLength()); j++)
1131             {
1132                 Node node = (Node) nodes.item(i).getAttributes().item(j);
1133                 triple[j] = node.getNodeValue();
1134             }
1135             properties.add(new AndsPidResponseProperty(Integer.valueOf(triple[0]), triple[1], triple[2]));
1136         }
1137         return properties;
1138     }
1139 
1140     /**
1141      * Helper method for converting formatted XML response into an XML document.
1142      * 
1143      * @param xmlResponse
1144      *            a formatted XML response.
1145      * @return an XML document.
1146      * @throws ParserConfigurationException
1147      *             thrown when attempting to convert response to an XML document.
1148      * @throws SAXException
1149      *             thrown when attempting to convert response to an XML document.
1150      * @throws IOException
1151      *             thrown when attempting to read response.
1152      */
1153     private static Document parseXML(String xmlResponse) throws ParserConfigurationException, SAXException, IOException
1154     {
1155         DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
1156         factory.setNamespaceAware(true);
1157         DocumentBuilder builder = factory.newDocumentBuilder();
1158         StringReader reader = new StringReader(xmlResponse);
1159         InputSource inputSource = new InputSource(reader);
1160         Document doc = builder.parse(inputSource);
1161         reader.close();
1162         return doc;
1163     }
1164 
1165     /**
1166      * Populate a AndsPidResponse object from the XML response of an ANDS Persistent Identifier service call.
1167      * 
1168      * @param xmlResponse
1169      *            the raw xmlResponse from an ANDS Persistent Identifier service call.
1170      * @return an ANDS Persistent Identifier service response {@link AndsPidResponse}.
1171      * @throws XPathExpressionException
1172      *             thrown when attempting to execute XPath on XML response.
1173      * @throws ParserConfigurationException
1174      *             thrown when attempting to convert response to an XML document.
1175      * @throws SAXException
1176      *             thrown when attempting to convert response to an XML document.
1177      * @throws IOException
1178      *             thrown when attempting to read response.
1179      */
1180     private AndsPidResponse populateAndsPidResponse(String xmlResponse) throws XPathExpressionException,
1181             ParserConfigurationException, SAXException, IOException
1182     {
1183         AndsPidResponse response = new AndsPidResponse();
1184         response.setXmlResponse(xmlResponse);
1185         
1186         Document doc = parseXML(xmlResponse);
1187         response.setMessage(parseForMessage(doc));
1188         response.setSuccess(parseForSuccess(doc));
1189         response.setHandles(parseForHandles(doc));
1190         response.setProperties(parseForProperties(doc));
1191         return response;
1192     }
1193 
1194     /**
1195      * Checks that this class is in a valid state to call the ANDS PID service.
1196      * 
1197      * @throws IllegalStateException
1198      *             thrown if the parameters need to call the ANDS PID service have not been provided.
1199      */
1200     private void validateState() throws IllegalStateException
1201     {
1202         StringBuffer errorMsg = new StringBuffer();
1203         if (StringUtils.isEmpty(this.getPidServiceHost()))
1204         {
1205             errorMsg.append("The host name of the ANDS PID service has not been provided. e.g. test.org.au\n");
1206         }
1207         if (getRequestorIdentity() == null || StringUtils.isEmpty(this.getRequestorIdentity().getAppId()))
1208         {
1209             errorMsg
1210                     .append("The appID of the caller has not been provided. " +
1211                             "e.g. unique Id provided by ANDS upon IP registration.\n");
1212         }
1213         if (getRequestorIdentity() == null || StringUtils.isEmpty(this.getRequestorIdentity().getIdentifier()))
1214         {
1215             errorMsg
1216                     .append("The identifier of the caller has not been provided. " +
1217                             "e.g. identifier or name of the repository calling the service.\n");
1218         }
1219         if (getRequestorIdentity() == null || StringUtils.isEmpty(this.getRequestorIdentity().getAuthDomain()))
1220         {
1221             errorMsg
1222                     .append("The authDomain of the caller has not been provided. " +
1223                             "e.g. the domain of the organisation calling the service.");
1224         }
1225         // if we have error messages, throw the exception
1226         if (errorMsg.length() != 0)
1227         {
1228             throw new IllegalStateException(errorMsg.toString());
1229         }
1230     }
1231     
1232 
1233     /**
1234      * Checks the arguments passed to the {@link #mintHandle(HandleType, String)} and the
1235      * {@link #mintHandleByIndex(HandleType, int, String)} methods.
1236      * 
1237      * @param type
1238      *            the type of the value to be minted {@link HandleType}.
1239      * @param value
1240      *            the value to be minted.
1241      * @throws IllegalStateException
1242      *             thrown if the arguments provided to {@link #mintHandle(HandleType, String)} or to
1243      *             {@link #mintHandleByIndex(HandleType, int, String)} are not valid.
1244      */
1245     private void validateMintHandleArguments(HandleType type, String value) throws IllegalArgumentException
1246     {
1247         // we should never accept a null HandleType
1248         if (type == null)
1249         {
1250             throw new IllegalArgumentException(
1251                     "The method mintHandle() can not be called with a null HandleType argument.\n");
1252         }
1253 
1254         // we can only accept the arguments if and only if both arguments are empty or both arguments are not empty
1255         // (logical equality).
1256         if (type.isEmpty() != StringUtils.isEmpty(value))
1257         {
1258             throw new IllegalArgumentException(MessageFormat.format(
1259                     "The method mintHandle() can only be called if both arguments are empty "
1260                             + "or both arguments are not empty:\n type= {0}\n value={1}\n", new Object[] {
1261                             (type == null) ? null : type.value(), value }));
1262         }
1263     }
1264 
1265     /**
1266      * Retrieve the current ANDS Persistent Identifier host name
1267      * @return the ANDS Persistent Identifier host name
1268      */
1269     public String getPidServiceHost()
1270     {
1271         return pidServiceHost;
1272     }
1273 
1274     /**
1275      * Set the ANDS Persistent Identifier host name.
1276      * @param pidServiceHost
1277      *            the ANDS Persistent Identifier host name to set
1278      */
1279     public void setPidServiceHost(String pidServiceHost)
1280     {
1281         this.pidServiceHost = pidServiceHost;
1282     }
1283 
1284     /**
1285      * Retrieve the ANDS Persistent Identifier port number
1286      * @return the ANDS Persistent Identifier port number
1287      */
1288     public int getPidServicePort()
1289     {
1290         return pidServicePort;
1291     }
1292 
1293     /**
1294      * Set the ANDS Persistent Identifier port number
1295      * @param pidServicePort
1296      *            the ANDS Persistent Identifier port number to set
1297      */
1298     public void setPidServicePort(int pidServicePort)
1299     {
1300         this.pidServicePort = pidServicePort;
1301     }
1302 
1303     /**
1304      * Retrieve the current ANDS Persistent Identifier path name (web application context name)
1305      * @return the ANDS Persistent Identifier path name
1306      */
1307     public String getPidServicePath()
1308     {
1309         return pidServicePath;
1310     }
1311 
1312     /**
1313      * Set the current ANDS Persistent Identifier path name (web application context name)
1314      * @param pidServicePath
1315      *            the ANDS Persistent Identifier path name to set
1316      */
1317     public void setPidServicePath(String pidServicePath)
1318     {
1319         this.pidServicePath = pidServicePath;
1320     }
1321 
1322     /**
1323      * Retrieve the identity information of the calling application/organisation.
1324      * @return the identity of the caller
1325      */
1326     public AndsPidIdentity getRequestorIdentity()
1327     {
1328         return requestorIdentity;
1329     }
1330 
1331     /**
1332      * Set the identity information of the calling application/organisation.
1333      * @param requestorIdentity
1334      *            the identity object to set
1335      */
1336     public void setRequestorIdentity(AndsPidIdentity requestorIdentity)
1337     {
1338         this.requestorIdentity = requestorIdentity;
1339     }
1340 
1341 }