1
2
3
4
5
6
7
8
9
10
11 package org.astrogrid.datacenter.queriers.xql;
12
13 import java.io.BufferedInputStream;
14 import java.io.IOException;
15 import java.io.InputStream;
16 import java.io.StringWriter;
17 import javax.xml.parsers.ParserConfigurationException;
18 import javax.xml.transform.Transformer;
19 import javax.xml.transform.TransformerConfigurationException;
20 import javax.xml.transform.TransformerException;
21 import javax.xml.transform.TransformerFactory;
22 import javax.xml.transform.dom.DOMSource;
23 import javax.xml.transform.stream.StreamResult;
24 import javax.xml.transform.stream.StreamSource;
25 import org.apache.commons.logging.Log;
26 import org.apache.commons.logging.LogFactory;
27 import org.astrogrid.config.SimpleConfig;
28 import org.astrogrid.datacenter.query.Adql074Writer;
29 import org.astrogrid.datacenter.query.Query;
30 import org.astrogrid.datacenter.query.QueryException;
31 import org.astrogrid.util.DomHelper;
32 import org.w3c.dom.Element;
33 import org.xml.sax.SAXException;
34
35 /***
36 * Creates XQL (XQuery?) from the query using transformation sheets
37 */
38 public class XqlMaker {
39
40 private static final Log log = LogFactory.getLog(XqlMaker.class);
41
42
43 /***
44 * Constructs an XQL statement for the given ADQL
45 */
46 public String getXql(Query query) throws QueryException, IOException {
47
48 Element adql = null;
49
50 try {
51 adql = DomHelper.newDocument(Adql074Writer.makeAdql(query, null)).getDocumentElement();
52 }
53 catch (SAXException e) {
54 throw new RuntimeException("Query2Adql074 procuced invalid XML from query "+query,e);
55 }
56 catch (ParserConfigurationException e) {
57 throw new RuntimeException("Server configuration error:"+e,e);
58 }
59
60
61 String namespaceURI = adql.getNamespaceURI();
62 if (namespaceURI == null) {
63
64 namespaceURI = adql.getAttribute("xmlns");
65 }
66 if (namespaceURI == null) {
67 DomHelper.PrettyElementToStream(adql,System.out);
68 throw new IllegalArgumentException("Query body has no namespace - cannot determine language");
69 }
70
71 String xql = useXslt(adql, namespaceURI);
72
73 return xql;
74
75 }
76
77
78 /*** Uses Xslt to do the translations */
79 public String useXslt(Element queryBody, String namespaceURI) throws QueryException {
80
81 String xsltDoc = null;
82
83
84
85
86 if ((namespaceURI==null) || (namespaceURI.length()==0)) {
87 throw new QueryException("No namespace specified in query document, so don't know what it is");
88 }
89 else if (namespaceURI.equals("http://tempuri.org/adql")) { //assume v0.5
90 xsltDoc = "adql05-2-sql.xsl";
91 }
92 else if (namespaceURI.equals("http://adql.ivoa.net/v0.73")) {
93
94
95 xsltDoc = "adql073-2-xql_fits.xsl";
96 }
97 else if (namespaceURI.equals("http://www.ivoa.net/xml/ADQL/v0.7.4")) {
98 xsltDoc = "adql074-2-xql_fits.xsl";
99 }
100
101
102
103 else if (namespaceURI.equals("http://astrogrid.org/sadql/v1.1")) {
104 xsltDoc = "sadql1.1-2-sql.xsl";
105 }
106
107
108 String key = "datacenter.sqlmaker.xslt."+namespaceURI.replaceAll(":","_");
109 xsltDoc = SimpleConfig.getSingleton().getString(key, xsltDoc);
110
111 if (xsltDoc == null) {
112 throw new RuntimeException("No XSLT sheet given for ADQL (namespace '"+namespaceURI+"'); set configuration key '" + key+"'");
113 }
114
115 Transformer transformer = null;
116 try {
117
118 InputStream xsltIn = new BufferedInputStream(XqlMaker.class.getResourceAsStream("./xslt/"+xsltDoc));
119
120 if (xsltIn == null) {
121
122 ClassLoader loader = this.getClass().getClassLoader();
123 xsltIn = loader.getResourceAsStream(xsltDoc);
124 }
125
126 if (xsltIn == null) {
127 throw new QueryException("Could not find/create ADQL->XQL transformer doc "+xsltDoc);
128 }
129
130 log.debug("Transforming ADQL ["+namespaceURI+"] using Xslt doc at './xslt/"+xsltDoc+"'");
131 TransformerFactory tFactory = TransformerFactory.newInstance();
132 transformer = tFactory.newTransformer(new StreamSource(xsltIn));
133 try {
134 tFactory.setAttribute("UseNamespaces", Boolean.FALSE);
135 }
136 catch (IllegalArgumentException iae) {
137
138
139 }
140
141 StringWriter sw = new StringWriter();
142 transformer.transform(new DOMSource(queryBody), new StreamResult(sw));
143 String xql = sw.toString();
144
145
146 xql = xql.replaceAll("\n","");
147 xql = xql.replaceAll("\r","");
148 while (xql.indexOf(" ")>-1) { xql = xql.replaceAll(" ", " "); }
149
150
151 if (xql.startsWith("<?")) {
152 xql = xql.substring(xql.indexOf("?>")+2);
153 }
154
155 xql = xql.replaceAll(">", ">").replaceAll("<", "<");
156
157 log.debug("Used '"+xsltDoc+"' to translate ADQL ("+namespaceURI+") to '"+xql+"'");
158
159 return xql;
160 }
161 catch (TransformerConfigurationException tce) {
162 throw new QueryException(tce+" (using xslt sheet "+xsltDoc+")",tce);
163 }
164 catch (TransformerException te) {
165 throw new QueryException(te+" translating ADQL->SQL using "+xsltDoc,te);
166 }
167
168 }
169
170 }
171
172
173
174
175
176
177
178
179
180
181
182
183