View Javadoc

1   /*$Id: XqlMaker.java,v 1.2 2005/03/21 18:45:55 mch Exp $
2    * Created on 27-Nov-2003
3    *
4    * Copyright (C) AstroGrid. All rights reserved.
5    *
6    * This software is published under the terms of the AstroGrid
7    * Software License version 1.2, a copy of which has been included
8    * with this distribution in the LICENSE.txt file.
9    *
10  **/
11  package org.astrogrid.xdbserver.xql;
12  
13  import java.io.IOException;
14  import java.io.InputStream;
15  import java.io.StringWriter;
16  import javax.xml.parsers.ParserConfigurationException;
17  import javax.xml.transform.Transformer;
18  import javax.xml.transform.TransformerConfigurationException;
19  import javax.xml.transform.TransformerException;
20  import javax.xml.transform.TransformerFactory;
21  import javax.xml.transform.dom.DOMSource;
22  import javax.xml.transform.stream.StreamResult;
23  import javax.xml.transform.stream.StreamSource;
24  import org.apache.commons.logging.Log;
25  import org.apache.commons.logging.LogFactory;
26  import org.astrogrid.cfg.ConfigFactory;
27  import org.astrogrid.query.Query;
28  import org.astrogrid.query.QueryException;
29  import org.astrogrid.query.adql.Adql074Writer;
30  import org.astrogrid.xml.DomHelper;
31  import org.w3c.dom.Element;
32  import org.xml.sax.SAXException;
33  
34  /***
35   * Creates XML from the query using transformation sheets
36   */
37  public class XqlMaker {
38  
39     private static final Log log = LogFactory.getLog(XqlMaker.class);
40  
41        
42     /***
43      * Constructs an XQL statement for the given ADQL
44      */
45     public String fromAdql(Query query) throws QueryException, IOException {
46  
47        Element adql = null;
48        //get the ADQL from the query
49        try {
50           adql = DomHelper.newDocument(Adql074Writer.makeAdql(query)).getDocumentElement();
51        }
52        catch (SAXException e) {
53           throw new RuntimeException("Query2Adql074 procuced invalid XML from query "+query,e);
54        }
55        
56        //Create DOM
57        String namespaceURI = adql.getNamespaceURI();
58        if (namespaceURI == null) {
59              // maybe not using namespace aware parser - see if we can find an xmlns attribute instead
60              namespaceURI = adql.getAttribute("xmlns");
61          }
62          if (namespaceURI == null) {
63              DomHelper.PrettyElementToStream(adql,System.out);
64              throw new IllegalArgumentException("Query body has no namespace - cannot determine language");
65          }
66          
67          String xql = useXslt(adql, namespaceURI);
68          
69          return xql;
70  
71       }
72       
73     
74       /*** Uses Xslt to do the translations */
75     public String useXslt(Element queryBody, String namespaceURI) throws QueryException {
76  
77        String xsltDoc = null;
78  
79        //work out which translator sheet to use
80        
81        //default
82        if ((namespaceURI==null) || (namespaceURI.length()==0)) {
83           throw new QueryException("No namespace specified in query document, so don't know what it is");
84        }
85        else if (namespaceURI.equals("http://tempuri.org/adql")) { //assume v0.5
86           xsltDoc = "adql05-2-sql.xsl";
87        }
88        else if (namespaceURI.equals("http://adql.ivoa.net/v0.73")) {
89           //xsltDoc = "adql073-2-sql.xsl";
90           //xsltDoc = "ADQLToXQL-0_73.xsl";
91          xsltDoc = "adql073-2-xql_fits.xsl";
92        }
93        else if (namespaceURI.equals("http://www.ivoa.net/xml/ADQL/v0.7.4")) {
94           xsltDoc = "adql074-2-xql_fits.xsl";
95        }
96  //      else if (namespaceURI.equals("http://adql.ivoa.net/v0.8")) {
97  //         xsltDoc = "adql08-2-sql.xsl";
98  //      }
99        else if (namespaceURI.equals("http://astrogrid.org/sadql/v1.1")) {
100          xsltDoc = "sadql1.1-2-sql.xsl";
101       }
102       
103       //look up in config but using above softcoded as defaults
104       String key = "datacenter.sqlmaker.xslt."+namespaceURI.replaceAll(":","_");
105       xsltDoc = ConfigFactory.getCommonConfig().getString(key, xsltDoc);
106       
107       if (xsltDoc == null) {
108          throw new RuntimeException("No XSLT sheet given for ADQL (namespace '"+namespaceURI+"'); set configuration key '" + key+"'");
109       }
110 
111       Transformer transformer = null;
112       try {
113          //find specified sheet on classpath/working directory
114          //InputStream xsltIn = new BufferedInputStream(FitsMaker.class.getResourceAsStream("./xslt/"+xsltDoc));
115         ClassLoader loader = this.getClass().getClassLoader();
116         InputStream xsltIn = loader.getResourceAsStream(xsltDoc);
117       
118          if (xsltIn == null) {
119             throw new QueryException("Could not find/create ADQL->XQL transformer doc "+xsltDoc);
120          }
121          
122          log.debug("Transforming ADQL ["+namespaceURI+"] using Xslt doc at './xslt/"+xsltDoc+"'");
123          TransformerFactory tFactory = TransformerFactory.newInstance();
124          transformer = tFactory.newTransformer(new StreamSource(xsltIn));
125          try {
126             tFactory.setAttribute("UseNamespaces", Boolean.FALSE);
127          }
128          catch (IllegalArgumentException iae) {
129             //ignore - if UseNamepsaces is unsupported, it will chuck an exception, and
130             //we don't want to use namespaces anyway so taht's fine
131          }
132          
133          StringWriter sw = new StringWriter();
134          transformer.transform(new DOMSource(queryBody), new StreamResult(sw));
135          String xql = sw.toString();
136         
137          //tidy it up - remove new lines and double spaces
138          xql = xql.replaceAll("\n","");
139          xql = xql.replaceAll("\r","");
140          while (xql.indexOf("  ")>-1) { xql = xql.replaceAll("  ", " "); }
141          
142          //botch botch botch - for some reason transformers sometimes add <?xml tag to beginning
143          if (xql.startsWith("<?")) {
144             xql = xql.substring(xql.indexOf("?>")+2);
145          }
146          //botch botch botch - something funny with ADQL 0.7.3 schema to do with comparisons
147          xql = xql.replaceAll("&gt;", ">").replaceAll("&lt;", "<");
148          
149          log.debug("Used '"+xsltDoc+"' to translate ADQL ("+namespaceURI+") to '"+xql+"'");
150          
151          return xql;
152       }
153       catch (TransformerConfigurationException tce) {
154          throw new QueryException(tce+" (using xslt sheet "+xsltDoc+")",tce);
155       }
156       catch (TransformerException te) {
157          throw new QueryException(te+" translating ADQL->SQL using "+xsltDoc,te);
158       }
159 
160    }
161    
162 }
163 
164 
165 /*
166 $Log: XqlMaker.java,v $
167 Revision 1.2  2005/03/21 18:45:55  mch
168 Naughty big lump of changes
169 
170 Revision 1.1  2005/03/10 16:42:55  mch
171 Split fits, sql and xdb
172 
173 Revision 1.1.1.1  2005/02/17 18:37:35  mch
174 Initial checkin
175 
176 Revision 1.1.1.1  2005/02/16 17:11:24  mch
177 Initial checkin
178 
179 Revision 1.6.12.1  2004/12/08 18:36:40  mch
180 Added Vizier, rationalised SqlWriters etc, separated out TableResults from QueryResults
181 
182 Revision 1.6  2004/11/03 00:17:56  mch
183 PAL_MCH Candidate 2 merge
184 
185 Revision 1.2.8.1  2004/10/21 19:10:24  mch
186 Removed deprecated translators, moved SqlMaker back to server,
187 
188 Revision 1.2  2004/10/06 21:12:17  mch
189 Big Lump of changes to pass Query OM around instead of Query subclasses, and TargetIndicator mixed into Slinger
190 
191 Revision 1.1  2004/09/28 15:02:13  mch
192 Merged PAL and server packages
193 
194 Revision 1.5  2004/09/21 14:14:49  KevinBenson
195 added a xsl for fits on 0.7.4
196 
197 Revision 1.4  2004/09/07 00:54:20  mch
198 Tidied up Querier/Plugin/Results, and removed deprecated SPI-visitor-SQL-translator
199 
200 Revision 1.3  2004/08/10 12:07:03  KevinBenson
201 result of merge with kev_09_08_04_RT fixing the fits problem with xsl stylesheet
202 
203 Revision 1.2.10.1  2004/08/10 12:01:34  KevinBenson
204 small change to reference another xsl stylesheet
205 
206 Revision 1.2  2004/07/26 13:53:44  KevinBenson
207 Changes to Fits to do an xquery on an xml file dealing with fits data.
208 Small xsl style sheet to make the xql which will get the filename element
209 
210 Revision 1.1.2.1  2004/07/26 08:53:40  KevinBenson
211 Still need to make a few more corrections, but wanted to check this in now.
212 It is the fits querier that now uses exist for doing adql->xquery
213 
214 Revision 1.11  2004/07/12 23:26:51  mch
215 Fixed (somewhat) SQL for cone searches, added tests to Dummy DB
216 
217 Revision 1.10  2004/07/12 14:12:04  mch
218 Fixed ADQL 0.7.4 xslt
219 
220 Revision 1.9  2004/07/07 19:33:59  mch
221 Fixes to get Dummy db working and xslt sheets working both for unit tests and deployed
222 
223 Revision 1.8  2004/07/06 18:48:34  mch
224 Series of unit test fixes
225 
226 Revision 1.7  2004/07/01 23:07:14  mch
227 Introduced metadata generator
228 
229 Revision 1.6  2004/03/17 21:03:20  mch
230 Added SQL transformation tests
231 
232 Revision 1.5  2004/03/17 18:03:20  mch
233 Added v0.8 ADQL
234 
235 Revision 1.4  2004/03/17 01:47:26  mch
236 Added v05 Axis web interface
237 
238 Revision 1.3  2004/03/14 16:55:48  mch
239 Added XSLT ADQL->SQL support
240 
241 Revision 1.2  2004/03/12 20:04:57  mch
242 It05 Refactor (Client)
243 
244 Revision 1.1  2004/03/12 04:45:26  mch
245 It05 MCH Refactor
246 
247  
248 */