View Javadoc

1   package org.astrogrid.registry.server.query;
2   
3   
4   
5   import org.w3c.dom.*;
6   
7   import javax.xml.parsers.DocumentBuilderFactory;
8   import javax.xml.parsers.DocumentBuilder;
9   
10  import java.io.Reader;
11  import java.io.StringReader;
12  import org.xml.sax.InputSource;
13  import javax.xml.parsers.ParserConfigurationException;
14  import org.xml.sax.SAXException;
15  import java.io.IOException;
16  import org.astrogrid.util.DomHelper;
17  import org.astrogrid.config.Config;
18  import org.astrogrid.registry.server.XQueryExecution;
19  import org.astrogrid.registry.common.XSLHelper;
20  import java.net.URL;
21  
22  import java.net.MalformedURLException;
23  
24  import org.apache.commons.logging.Log;
25  import org.apache.commons.logging.LogFactory;
26  import java.io.*;
27  import org.apache.axis.AxisFault;
28  import org.astrogrid.xmldb.eXist.server.QueryDBService;
29  import org.astrogrid.registry.RegistryException;
30  import org.astrogrid.registry.server.harvest.RegistryHarvestService;
31  import org.astrogrid.registry.server.RegistryServerHelper;
32  import org.astrogrid.registry.server.QueryHelper;
33  
34  import java.util.ArrayList;
35  
36  /***
37   *
38   *
39   *
40   * @see org.astrogrid.registry.common.RegistryInterface
41   * @link http://www.ivoa.net/twiki/bin/view/IVOA/IVOARegWp03
42   * @author Kevin Benson
43   */
44  public class RegistryQueryService {
45  
46     /***
47     * Logging variable for writing information to the logs
48     */
49     private static final Log log = LogFactory.getLog(RegistryService.class);
50  
51     /***
52      * conf - Config variable to access the configuration for the server normally
53      * jndi to a config file.
54      * @see org.astrogrid.config.Config
55      */   
56     public static Config conf = null;
57  
58     /***
59      * final variable for the default AuthorityID associated to this registry.
60      */
61     private static final String AUTHORITYID_PROPERTY =
62                                            "org.astrogrid.registry.authorityid";
63  
64     /***
65      * Static to be used on the initiatian of this class for the config
66      */   
67     static {
68        if(conf == null) {
69           conf = org.astrogrid.config.SimpleConfig.getSingleton();
70        }
71     }
72     
73     /***
74      * Search - Web Service method to take ADQL DOM and perform a query on the
75      * registry.  Takes in a DOM so it can handle multiple versions of ADQL.
76      * 
77      * @param query - DOM object containing ADQL.
78      * @throws - AxisFault containing exceptions that might have occurred setting up
79      * or querying the registry.
80      * @return - Resource DOM object of the Resources from the query of the registry. 
81      * 
82      */
83     public Document Search(Document query) throws AxisFault {
84        log.debug("start Search");
85        long beginQ = System.currentTimeMillis();
86        XSLHelper xslHelper = new XSLHelper();
87  
88        //get the version of Resources we are querying on.
89        String attrVersion = getRegistryVersion(query);
90        String versionNumber = attrVersion.replace('.','_');
91  
92        //transform the ADQL to an XQuery for the registry.
93        String xqlQuery = getQuery(query,versionNumber);
94        log.info("The XQLQuery = " + xqlQuery);
95        
96        //the location in the eXist db to be queries on.
97        String collectionName = "astrogridv" + versionNumber;
98        log.info("Collection Name for query = " + collectionName);
99  
100       //perform the query and log how long it took to query.
101       Document resultDoc = queryExist(xqlQuery,collectionName);
102       log.info("Time taken to complete search on server = " +
103               (System.currentTimeMillis() - beginQ));
104       log.debug("end Search");
105       if(resultDoc != null) {
106           log.info("Number of Resources to be returned = " + 
107                    resultDoc.getElementsByTagNameNS("*","Resource").getLength());
108       }
109       
110       //To be correct we need to transform the results, with a correct response element 
111       //for the soap message and for the right root element around the resources.
112       return xslHelper.transformExistResult((Node)resultDoc,
113                                             versionNumber,"SearchResponse");
114    }
115 
116    
117    /***
118     * More of a convenience method to do direct Xqueries on the registry
119     * Gets the XQuery out of the XQLString element which is the wrapped method
120     * name in the SOAP body.
121     *  
122     * @param query - XQuery string to be used directly on the registry.
123     * @throws - AxisFault containing exceptions that might have occurred setting up
124     * or querying the registry. 
125     * @return - Resource DOM object of the Resources from the query of the registry.
126     */
127    public Document Query(Document query) throws AxisFault {
128       log.debug("start Query");
129       Document resultDoc = null;
130       try {
131          //get the xquery.
132          String xql = DomHelper.getNodeTextValue(query,"XQLString");
133          log.debug("end Query");
134          
135          String attrVersion = getRegistryVersion(query);
136          String versionNumber = attrVersion.replace('.','_');
137       
138          String collectionName = "astrogridv" + versionNumber;
139          log.info("Collection Name for query = " + collectionName);
140          //query the eXist db.
141          resultDoc = queryExist(xql,collectionName);
142          if(resultDoc != null) {
143              log.info("Number of Resources to be returned = " + 
144                      resultDoc.getElementsByTagNameNS("*","Resource").getLength());
145          }         
146       }catch(IOException ioe) {
147          throw new AxisFault("IO problem", ioe);
148       }
149       return resultDoc;
150    }
151 
152    /***
153     * More of a convenience method to do direct Xqueries on the registry
154     * and this method is for when a Web Service style does not wrap a method name
155     * in the soap body.
156 
157     * @param query - XQuery string to be used directly on the registry.
158     * @throws - AxisFault containing exceptions that might have occurred setting up
159     * or querying the registry. 
160     * @return - Resource DOM object of the Resources from the query of the registry.
161     */   
162    public Document XQLString(Document query) throws AxisFault {
163       log.debug("start XQLString");
164       Document resultDoc = null;
165       try {
166          String attrVersion = getRegistryVersion(query);
167          String versionNumber = attrVersion.replace('.','_');
168 
169          String collectionName = "astrogridv" + versionNumber;     
170          log.info("Collection Name for query = " + collectionName);
171          
172          String xql = DomHelper.getNodeTextValue(query,"XQLString");
173          log.debug("end XQLString");
174          resultDoc = queryExist(xql,collectionName);
175          if(resultDoc != null) {
176              log.info("Number of Resources to be returned = " + 
177                      resultDoc.getElementsByTagNameNS("*","Resource").getLength());
178          }               
179       }catch(IOException ioe) {
180          throw new AxisFault("IO problem", ioe);         
181       }
182       return resultDoc;
183       
184    }
185    
186    /***
187    * submitQuery queries the registry for Resources.  Currently uses
188    * an older xml query language that Astrogrid came up with, but will
189    * soon be rarely used for the ADQL version to be the standard for the
190    * IVOA.  Will be deprecated in itn07.
191    * 
192    * @param query XML document object representing the query language used on the registry.
193    * @throws - AxisFault containing exceptions that might have occurred setting up
194    * or querying the registry.
195    * @return XML docuemnt object representing the result of the query.
196    * @author Kevin Benson 
197    */
198    public Document submitQuery(Document query) throws AxisFault {
199       log.debug("start submitQuery");
200       long beginQ = System.currentTimeMillis();
201       XSLHelper xslHelper = new XSLHelper();
202       
203       String attrVersion = getRegistryVersion(query);
204       String versionNumber = attrVersion.replace('.','_');
205       String collectionName = "astrogridv" + versionNumber;
206       log.info("Collection Name for query = " + collectionName);
207       //log.info("received = " + DomHelper.DocumentToString(query));
208       //parse query right now actually does the query.
209       String xql = RegistryServerHelper.getXQLDeclarations(versionNumber) + XQueryExecution.createXQL(query);
210       log.info("Query to be performed on the db = " + xql);
211       Document resultDoc = queryExist(xql,collectionName);
212       log.info("Time taken to complete submitQuery on server = " +
213               (System.currentTimeMillis() - beginQ));
214       if(resultDoc != null) {
215           log.info("Number of Resources to be returned = " + 
216                   resultDoc.getElementsByTagNameNS("*","Resource").getLength());
217       }      
218       log.debug("end submitQuery");
219 
220       //To be correct we need to transform the results, with a correct response element 
221       //for the soap message and for the right root element around the resources.
222       return xslHelper.transformExistResult((Node)resultDoc,versionNumber,null);
223    }
224    
225    /***
226     * Queries for the Registry Resource element that is tied to this Registry.
227     * All Astrogrid Registries have one Registry Resource tied to the Registry.
228     * Which defines the AuthorityID's it manages and how to access the Registry.
229     * 
230     * @param query actually normally empty/null and is ignored.
231     * @throws - AxisFault containing exceptions that might have occurred setting up
232     * or querying the registry. 
233     * @return XML docuemnt object representing the result of the query.
234     */
235    public Document loadRegistry(Document query) throws AxisFault {
236       log.debug("start loadRegistry");
237       
238       //get the default autority id for this registry.      
239       Document doc = null;
240       Document responseDoc = null;
241       String attrVersion = getRegistryVersion(query);
242       String versionNumber = attrVersion.replace('.','_');
243       log.info("the versionNumber in loadRegistry = " + versionNumber);
244       return loadMainRegistry(versionNumber);
245    }
246    
247    public Document loadMainRegistry(String versionNumber) throws AxisFault {
248        long beginQ = System.currentTimeMillis();       
249        String collectionName = "astrogridv" + versionNumber;
250        log.info("Collection Name for query = " + collectionName);
251        String xqlString = QueryHelper.queryForMainRegistry(versionNumber);
252        log.info("XQL String = " + xqlString);
253        Document resultDoc = queryExist(xqlString,collectionName);
254        
255        XSLHelper xslHelper = new XSLHelper();
256        log.info("Time taken to complete loadRegistry on server = " +
257                (System.currentTimeMillis() - beginQ));
258        log.debug("end loadRegistry");
259        
260        //To be correct we need to transform the results, with a correct response element 
261        //for the soap message and for the right root element around the resources.
262        return xslHelper.transformExistResult((Node)resultDoc,versionNumber,null);
263    }
264    
265    /***
266     * Queries the eXist xml database, on the collection of the registry.
267     * @param xqlString an XQuery to query the database
268     * @param collectionName the location in the database to query (sort of like a table)
269     * @return xml DOM object returned from the database, which are Resource elements
270     * @throws - AxisFault containing exceptions that might have occurred setting up
271     * or querying the registry.
272     */
273    private Document queryExist(String xqlString, String collectionName) throws AxisFault {
274       log.debug("start queryExist");
275       QueryDBService qdb = new QueryDBService();
276       return qdb.query(collectionName,xqlString);
277    }
278    
279    public ArrayList getAstrogridVersions() {
280        QueryDBService qdb = new QueryDBService();
281        ArrayList al = new ArrayList();
282        try {
283            Document doc = qdb.getCollection("");
284            String xml = DomHelper.DocumentToString(doc);
285            int index = -1;
286            int temp = 0;
287            
288            while((index = xml.indexOf("astrogridv",temp)) != -1) {
289                temp = xml.indexOf("\"", index+10);
290                System.out.println("adding to the arraylist = " + ((String)xml.substring(index+10,temp)));
291                al.add(((String)xml.substring(index+10,temp)));
292            }
293        }catch(MalformedURLException mue) {
294            mue.printStackTrace();
295        }catch(ParserConfigurationException pce) {
296            pce.printStackTrace();
297        }catch(IOException ioe) {
298            ioe.printStackTrace();
299        }catch(SAXException sax) {
300            sax.printStackTrace();
301        }
302        return al;
303    }
304    
305    public Document keywordQuery(String keywords, boolean orKeywords) throws AxisFault {
306        return keywordQuery(keywords,orKeywords,RegistryServerHelper.getDefaultVersionNumber());
307    }
308    
309    public Document keywordQuery(String keywords, boolean orKeywords, String version) throws AxisFault {
310        long beginQ = System.currentTimeMillis();
311        if(version == null || version.trim().length() <= 0) {
312            version = RegistryServerHelper.getDefaultVersionNumber();
313        }       
314        String versionNumber = version.replace('.','_');
315        String []keyword = keywords.split(" ");
316        String xqlPaths = conf.getString("keyword.query.path." + versionNumber);
317        String []xqlPath = xqlPaths.split(",");
318        
319 
320        String xqlString = QueryHelper.getStartQuery(versionNumber);       
321        for(int i = 0;i < xqlPath.length;i++) {
322            xqlString += "(";
323            for(int j = 0;j < keyword.length;j++) {
324              xqlString += xqlPath[i] + " &= '*" + keyword[j] + "*'";
325              if(j != (keyword.length - 1)) {
326                  if(orKeywords) { 
327                      xqlString += " or ";
328                  }else {
329                      xqlString += " and ";
330                  }
331              }//if
332            }//for
333            xqlString += ") ";
334            if(i != (xqlPath.length-1)) {
335                xqlString += " or ";
336            }
337        }//for
338        xqlString += " return $x";
339        
340        String collectionName = "astrogridv" + versionNumber;
341        Document resultDoc = queryExist(xqlString,collectionName); 
342        if(resultDoc != null) {
343            log.info("Number of Resources to be returned = " + 
344                    resultDoc.getElementsByTagNameNS("*","Resource").getLength());
345        }
346        XSLHelper xslHelper = new XSLHelper();
347        log.info("Time taken to complete keywordsearch on server = " +
348                (System.currentTimeMillis() - beginQ));
349        log.debug("end keywordsearch");         
350        
351        //To be correct we need to transform the results, with a correct response element 
352        //for the soap message and for the right root element around the resources.
353        return xslHelper.transformExistResult((Node)resultDoc,
354                                              versionNumber,"KeywordSearchResponse");
355    }
356    
357    public Document getAll(String versionNumber) throws AxisFault {
358        XSLHelper xslHelper = new XSLHelper();
359        if(versionNumber == null || versionNumber.trim().length() <= 0) {
360            versionNumber = RegistryServerHelper.getDefaultVersionNumber();
361        }
362        String queryVersion = versionNumber.replace('.','_');
363        String collectionName = "astrogridv" + queryVersion;
364        log.info("collname=" + collectionName);
365        String xqlString = QueryHelper.getAllQuery(queryVersion);
366        Document resultDoc = queryExist(xqlString,collectionName);
367        return xslHelper.transformExistResult((Node)resultDoc,
368                queryVersion,"GetAllResponse");
369    }
370    
371    public Document GetResourcesByIdentifier(Document query) throws AxisFault {
372        log.debug("start GetResourcesByIdentifier");                   
373        String ident = null;
374        try {
375            ident = DomHelper.getNodeTextValue(query,"identifier");
376            log.info("found identifier in web service request = " + ident);
377        }catch(IOException ioe) {
378            throw new AxisFault("IO problem trying to get identifier");
379        }
380        String attrVersion = getRegistryVersion(query);
381        return getResourcesByIdentifier(ident,attrVersion);
382  }
383    
384    public Document getResourcesByIdentifier(String ivorn, String versionNumber) throws AxisFault {
385        XSLHelper xslHelper = new XSLHelper();
386        if(versionNumber == null || versionNumber.trim().length() <= 0) {
387            versionNumber = RegistryServerHelper.getDefaultVersionNumber();
388        }
389        if(ivorn == null || ivorn.trim().length() <= 0) {
390            throw new AxisFault("Cannot have empty or null identifier");
391        }
392        String queryVersion = versionNumber.replace('.','_');
393        String collectionName = "astrogridv" + queryVersion;
394        String xqlString = QueryHelper.queryForResource(ivorn,queryVersion);
395        Document resultDoc = queryExist(xqlString,collectionName);
396        return xslHelper.transformExistResult((Node)resultDoc,
397                queryVersion,"GetResourceByIdentifier");
398    }
399    
400    public Document getResourcesByAnyIdentifier(String ivorn, String versionNumber) throws AxisFault {
401        XSLHelper xslHelper = new XSLHelper();
402        if(versionNumber == null || versionNumber.trim().length() <= 0) {
403            versionNumber = RegistryServerHelper.getDefaultVersionNumber();
404        }
405        String queryVersion = versionNumber.replace('.','_');
406        String collectionName = "astrogridv" + queryVersion;
407        String xqlString = QueryHelper.queryForAllResource(ivorn,queryVersion);
408        Document resultDoc = queryExist(xqlString,collectionName);
409        return xslHelper.transformExistResult((Node)resultDoc,
410                queryVersion,"GetResourceByIdentifier");
411    }
412       
413    public Document getResourcesByAuthority(String ivorn, String versionNumber) throws AxisFault {
414        XSLHelper xslHelper = new XSLHelper();
415        if(versionNumber == null || versionNumber.trim().length() <= 0) {
416            versionNumber = RegistryServerHelper.getDefaultVersionNumber();
417        }
418        String queryVersion = versionNumber.replace('.','_');
419        String collectionName = "astrogridv" + queryVersion;
420        String xqlString = QueryHelper.queryForResourceByAuthority(ivorn,queryVersion);
421        Document resultDoc = queryExist(xqlString,collectionName);
422        return xslHelper.transformExistResult((Node)resultDoc,
423                queryVersion,"GetResourceByAuthroity");
424    }
425    
426       
427    public Document KeywordSearch(Document query) throws AxisFault {
428          log.debug("start keywordsearch");                   
429          String keywords = null;
430          String orValue = null;
431          try {
432              keywords = DomHelper.getNodeTextValue(query,"keywords");
433              orValue = DomHelper.getNodeTextValue(query,"orValue");
434          }catch(IOException ioe) {
435              throw new AxisFault("IO problem trying to get keywords and orValue");
436          }
437          String attrVersion = getRegistryVersion(query);
438          boolean orKeywords = new Boolean(orValue).booleanValue();
439          return keywordQuery(keywords,orKeywords,attrVersion);
440    }
441 
442    /***
443     * Queries and returns all the Resources that are Registry type resources.
444     * Used by other registries as a convenience query to discover other
445     * regiestries not known for harvesting.
446     * 
447     * @param query normally empty and is ignored, it is required though for the
448     * Axis Document style method.  At most it will contain nothing more than the method
449     * name.
450     * @return Resource entries of type Registries.
451     * @throws - AxisFault containing exceptions that might have occurred setting up
452     * or querying the registry.
453     */
454    public Document GetRegistries(Document query) throws AxisFault {
455       //DomHelper.DocumentToStream(query,System.out);
456 
457       String attrVersion = getRegistryVersion(query);
458       String versionNumber = attrVersion.replace('.','_');
459       return getRegistriesQuery(versionNumber);
460    }
461    
462    public Document getRegistriesQuery(String versionNumber) throws AxisFault {
463        long beginQ = System.currentTimeMillis();
464        if(versionNumber == null || versionNumber.trim().length() <= 0) {
465            versionNumber = RegistryServerHelper.getDefaultVersionNumber();
466        }
467        String queryVersion = versionNumber.replace('.','_');
468        String collectionName = "astrogridv" + queryVersion;
469        log.info("Collection Name for query = " + collectionName);
470        
471        //Should declare namespaces, but it is not required so will leave out for now.
472        String xqlString = QueryHelper.queryForRegistries(queryVersion);
473        log.info("XQL String = " + xqlString);      
474        Document resultDoc = queryExist(xqlString,collectionName);
475        XSLHelper xslHelper = new XSLHelper();
476        log.info("Time taken to complete GetRegistries on server = " +
477        (System.currentTimeMillis() - beginQ));
478        log.debug("end loadRegistry");
479        
480        return xslHelper.transformExistResult((Node)resultDoc,
481                queryVersion,"GetRegistriesResponse");       
482    }
483    
484    /***
485     * Used by all the OAI required method interfaces to get the OAI
486     * conformed Resources from a URL.  This URL is a servlet to query
487     * the eXist database and put the XML in a OAI form.  The XML DOM returned
488     * are all the Resources managed by this Registry.
489     * @param oaiServlet a url string 
490     * @return OAI conformed DOM object of all the Resourced managed by this Registry.
491     * @throws - AxisFault containing exceptions that might have occurred setting up
492     * or querying the registry.
493     */
494    private Document queryOAI(String oaiServlet) throws AxisFault {
495       try {
496         log.info("the oaiservlet url = '" + oaiServlet + "'");
497         return DomHelper.newDocument(new URL(oaiServlet));
498        }catch(MalformedURLException me) {
499         throw new AxisFault("Incorrect url for calling oai servlet", me);
500        }catch(ParserConfigurationException pce) {
501          throw new AxisFault("Parser Config error", pce);
502        }catch(SAXException sax) {
503          throw new AxisFault("SAX problem parsing xml" , sax);
504        }catch(IOException ioe) {
505          throw new AxisFault("IO Problem", ioe);
506        }    
507    }
508    
509    private String getOAIServletURL(Document query) {
510        String attrVersion = getRegistryVersion(query);
511        String versionNumber = attrVersion.replace('.','_');       
512        return conf.getString("oai.servlet.url." + versionNumber);       
513    }
514 
515    /***
516     * OAI-Identify conformed Web service method.
517     * 
518     * @param query actually this OAI mehtod requires nothing. 
519     * @return XML DOM object conforming to the OAI Identify.
520     * @throws - AxisFault containing exceptions that might have occurred
521     *  calling the servlet/url.
522     * @link http://www.openarchives.org 
523     */
524    public Document Identify(Document query) throws AxisFault {
525       String oaiServlet = getOAIServletURL(query) + "?verb=Identify";
526       Document resultDoc = queryOAI(oaiServlet);
527       Element currentRoot = resultDoc.getDocumentElement();
528       Element root = resultDoc.createElement("IdentifyResponse");
529       root.appendChild(currentRoot);
530       resultDoc.appendChild(root);
531       return resultDoc;
532    }
533 
534    /***
535     * OAI-ListMetadataFormats conformed Web service method.
536     * 
537     * @param query contains an optional identifier string. 
538     * @return XML DOM object conforming to the OAI ListMetadataFormats.
539     * @throws - AxisFault containing exceptions that might have occurred
540     *  calling the servlet/url.
541     * @link http://www.openarchives.org 
542     */
543    public Document ListMetadataFormats(Document query) throws AxisFault {
544       String oaiServlet = getOAIServletURL(query) + "?verb=ListMetadataFormats";       
545       NodeList nl = null;
546       if( (nl = query.getElementsByTagName("identifier")).getLength() > 0  )
547            oaiServlet += "&identifier=" + nl.item(0).getFirstChild().getNodeValue(); 
548       Document resultDoc = queryOAI(oaiServlet);
549       Element currentRoot = resultDoc.getDocumentElement();
550       Element root = resultDoc.createElement("ListMetadataFormatsResponse");
551       root.appendChild(currentRoot);
552       resultDoc.appendChild(root);
553       return resultDoc;
554    }
555 
556    /***
557     * OAI-ListSets conformed Web service method. Currently not implemented.
558     * 
559     * @param query 
560     * @return XML DOM object conforming to the OAI OAI-ListSets.
561     * @throws - AxisFault containing exceptions that might have occurred
562     *  calling the servlet/url.
563     * @link http://www.openarchives.org 
564     */   
565    public Document ListSets(Document query) throws AxisFault {
566     throw new AxisFault("Sorry but this method is currently not implemented");
567    }
568 
569    /***
570     * OAI-ResumeListSets conformed Web service method. Currently not implemented.
571     * 
572     * @param query 
573     * @return XML DOM object conforming to the OAI OAI-ResumeListSets.
574     * @throws - AxisFault containing exceptions that might have occurred
575     *  calling the servlet/url.
576     * @link http://www.openarchives.org 
577     */   
578    public Document ResumeListSets(Document query) throws AxisFault {
579       throw new AxisFault("Sorry but this method is currently not implemented");
580    }
581 
582    /***
583     * OAI-GetRecord conformed Web service method.
584     * 
585     * @param query contains an identifier string and metadataPrefix. The prefix
586     * is defaulted to the standard registry ivo_vor if not given. 
587     * @return XML DOM object conforming to the OAI GetRecord.
588     * @throws - AxisFault containing exceptions that might have occurred
589     *  calling the servlet/url.
590     * @link http://www.openarchives.org 
591     */   
592    public Document GetRecord(Document query) throws AxisFault {
593        String oaiServlet = getOAIServletURL(query) + "?verb=GetRecord";       
594        NodeList nl = null;
595        if( (nl = query.getElementsByTagName("identifier")).getLength() > 0  ) 
596           oaiServlet += "&identifier=" + nl.item(0).getFirstChild().getNodeValue();
597        else
598           throw new AxisFault("No Identifier given"); 
599        if( (nl = query.getElementsByTagName("metadataPrefix")).getLength() > 0  )
600         oaiServlet += "&metadataPrefix=" + nl.item(0).getFirstChild().getNodeValue();
601        else
602         oaiServlet += "&metadataPrefix=ivo_vor";
603        Document resultDoc = queryOAI(oaiServlet);
604        //wrap it with a response method element.
605        Element currentRoot = resultDoc.getDocumentElement();
606        Element root = resultDoc.createElement("GetRecordResponse");
607        root.appendChild(currentRoot);
608        resultDoc.appendChild(root);
609        return resultDoc;
610    }
611 
612    /***
613     * OAI-ListIdentifiers conformed Web service method.
614     * 
615     * @param query contains a metadataPrefix, and optional from and until 
616     * @return XML DOM object conforming to the OAI ListIdentifiers.
617     * @throws - AxisFault containing exceptions that might have occurred
618     *  calling the servlet/url.
619     * @link http://www.openarchives.org 
620     */   
621    public Document ListIdentifiers(Document query) throws AxisFault {
622       String oaiServlet = getOAIServletURL(query) + "?verb=ListIdentifiers";
623       NodeList nl = null;      
624       if( (nl = query.getElementsByTagName("metadataPrefix")).getLength() > 0  )
625        oaiServlet += "&metadataPrefix=" + nl.item(0).getFirstChild().getNodeValue();
626       else 
627         oaiServlet += "&metadataPrefix=ivo_vor";        
628       if( (nl = query.getElementsByTagName("from")).getLength() > 0  ) 
629         oaiServlet += "&from=" + nl.item(0).getFirstChild().getNodeValue();
630       if( (nl = query.getElementsByTagName("until")).getLength() > 0  )
631         oaiServlet += "&until=" + nl.item(0).getFirstChild().getNodeValue();
632       Document resultDoc = queryOAI(oaiServlet);
633       Element currentRoot = resultDoc.getDocumentElement();
634       Element root = resultDoc.createElement("ListIdentifiersResponse");
635       root.appendChild(currentRoot);
636       resultDoc.appendChild(root);
637       return resultDoc;
638 
639    }
640 
641    /***
642     * OAI-ResumeListIdentifiers conformed Web service method.
643     * 
644     * @param query contains a resumptionToken 
645     * @return XML DOM object conforming to the OAI ResumeListIdentifiers.
646     * @throws - AxisFault containing exceptions that might have occurred
647     *  calling the servlet/url.
648     * @link http://www.openarchives.org 
649     */
650    public Document ResumeListIdentifiers(Document query) throws AxisFault {
651         String oaiServlet = getOAIServletURL(query);
652         NodeList nl = null;
653         if( (nl = query.getElementsByTagName("resumptionToken")).getLength() > 0  ) 
654           oaiServlet += "?resumptionToken=" + nl.item(0).getFirstChild().getNodeValue();
655         else 
656           throw new AxisFault("No resumptionToken found in ResumeListIdentifiers");
657         Document resultDoc = queryOAI(oaiServlet);
658         Element currentRoot = resultDoc.getDocumentElement();
659         Element root = resultDoc.createElement("ResumeListIdentifiersResponse");
660         root.appendChild(currentRoot);
661         resultDoc.appendChild(root);
662         return resultDoc;
663    }
664 
665    /***
666     * OAI-ListRecords conformed Web service method.
667     * 
668     * @param query contains a metadataPrefix, optional from&until elements. 
669     * @return XML DOM object conforming to the OAI ListRecords.
670     * @throws - AxisFault containing exceptions that might have occurred
671     *  calling the servlet/url.
672     * @link http://www.openarchives.org 
673     */   
674    public Document ListRecords(Document query) throws AxisFault {
675         String oaiServlet = getOAIServletURL(query) + "?verb=ListRecords";
676         NodeList nl = null;        
677         if( (nl = query.getElementsByTagName("metadataPrefix")).getLength() > 0  )
678          oaiServlet += "&metadataPrefix=" + nl.item(0).getNodeValue();
679         else
680          oaiServlet += "&metadataPrefix=ivo_vor";
681         if( (nl = query.getElementsByTagName("from")).getLength() > 0  ) 
682           oaiServlet += "&from=" + nl.item(0).getFirstChild().getNodeValue();
683         if( (nl = query.getElementsByTagName("until")).getLength() > 0  )
684           oaiServlet += "&until=" + nl.item(0).getFirstChild().getNodeValue();
685         Document resultDoc = queryOAI(oaiServlet);
686         Element currentRoot = resultDoc.getDocumentElement();
687         Element root = resultDoc.createElement("ListRecordsResponse");
688         root.appendChild(currentRoot);
689         resultDoc.appendChild(root);
690         return resultDoc;
691    }
692 
693    /***
694     * OAI-ResumeListRecords conformed Web service method.
695     * 
696     * @param query contains a resumptionToken 
697     * @return XML DOM object conforming to the OAI ResumeListRecords.
698     * @throws - AxisFault containing exceptions that might have occurred
699     *  calling the servlet/url.
700     * @link http://www.openarchives.org
701     */
702    public Document ResumeListRecords(Document query) throws AxisFault {
703        String oaiServlet = getOAIServletURL(query);
704        NodeList nl = null;       
705        if( (nl = query.getElementsByTagName("resumptionToken")).getLength() > 0  ) 
706          oaiServlet += "?resumptionToken=" + nl.item(0).getFirstChild().getNodeValue();
707        else 
708            throw new AxisFault("No resumptionToken found in ResumeListRecords");       
709        Document resultDoc = queryOAI(oaiServlet);
710        Element currentRoot = resultDoc.getDocumentElement();
711        Element root = resultDoc.createElement("ResumeListRecordsResponse");
712        root.appendChild(currentRoot);
713        resultDoc.appendChild(root);
714        return resultDoc;          
715    }
716    
717    /***
718     * Transforms ADQL to XQuery, uses the namespace of ADQL to allow the
719     * transformations to handle different versions.  Transformations are done
720     * by XSL stylesheets.
721     * 
722     * @param query ADQL DOM object 
723     * @return xquery string
724     * @throws - AxisFault containing exceptions that might have occurred
725     *  calling the servlet/url.
726     */   
727    private String getQuery(Document query,String resourceVersion) throws AxisFault {
728        XSLHelper xslHelper = new XSLHelper();       
729        NodeList nl = query.getElementsByTagNameNS("*","Select");
730        //Get the main root element Select
731        if(nl.getLength() == 0) 
732            nl = query.getElementsByTagNameNS("*","Where");
733            
734        
735        //find the namespace.
736        String adqlVersion = null;
737        log.info("the adql in getquery nl.getLenth = " + nl.getLength());
738        if(nl.getLength() > 0) {
739            log.info("the namespaceuri for element = " + ((Element)nl.item(0)).getNamespaceURI());
740            adqlVersion = ((Element)nl.item(0)).getNamespaceURI();
741            /*
742            adqlVersion = DomHelper.getNodeAttrValue((Element)nl.item(0),"ad","xmlns");
743            if(adqlVersion == null || adqlVersion.trim().length() == 0) {
744                adqlVersion = DomHelper.getNodeAttrValue((Element)nl.item(0),"xmlns");
745            }//if
746            */
747        }//if
748        
749        //throw an error if no version was found.
750        if(adqlVersion == null || adqlVersion.trim().length() == 0) {
751            throw new AxisFault("Could not find a version of the ADQL");
752        }
753        //get only the actual version number.
754        adqlVersion = adqlVersion.substring(adqlVersion.lastIndexOf("v")+1);
755        adqlVersion = adqlVersion.replace('.','_');
756        //make the transformation using an xsl stylesheet.
757        return xslHelper.transformADQLToXQL(query, adqlVersion, 
758                         RegistryServerHelper.getRootNodeName(resourceVersion),
759                         RegistryServerHelper.getXQLDeclarations(resourceVersion));
760    }
761    
762    /***
763     * Looks for a registry version number in a DOM object.  By looking at the xmlns 
764     * (normally vr) of varoius elements. Because a Resource element may be a few 
765     * elements down it goes through a few child nodes.
766     * 
767     * @param query XML DOM of Resources
768     * @return version number of the Registry.
769     */
770    private String getRegistryVersion(Document query) {
771        log.info("in getRegistryversion");
772        //log.info("print in getRegistryVersion" + DomHelper.DocumentToString(query));
773        if(query == null) {
774            return RegistryServerHelper.getRegistryVersionFromNode(query);
775        }
776        Element elem = query.getDocumentElement();
777        if(elem == null) {
778            return RegistryServerHelper.getRegistryVersionFromNode(query);
779        }
780        if(elem.hasChildNodes()) {
781            return RegistryServerHelper.getRegistryVersionFromNode(
782                          query.getDocumentElement().getFirstChild());    
783        }
784        return RegistryServerHelper.getRegistryVersionFromNode(
785                                    query.getDocumentElement());    
786    }
787    
788    public Document harvestResource(Document resources)  throws AxisFault {
789        RegistryHarvestService rhs = new RegistryHarvestService();
790        try {   
791           rhs.harvestResource(resources,null);
792        }catch(IOException ioe) {
793           throw new AxisFault("IOE problem",ioe);
794        }catch(RegistryException re) {
795         throw new AxisFault("Registry exception", re);
796        }
797        return resources;      
798    }   
799    
800 }