1 /*
2 * $Id: FitsQuerierPlugin.java,v 1.3 2005/03/21 18:45:55 mch Exp $
3 *
4 * (C) Copyright Astrogrid...
5 */
6
7 package org.astrogrid.fitsserver.fits;
8
9 import java.awt.geom.Area;
10 import java.awt.geom.Ellipse2D;
11 import java.awt.geom.GeneralPath;
12 import java.io.File;
13 import java.io.IOException;
14 import java.net.URL;
15 import java.security.Principal;
16 import java.util.Hashtable;
17 import javax.xml.parsers.ParserConfigurationException;
18 import org.astrogrid.cfg.ConfigException;
19 import org.astrogrid.cfg.ConfigFactory;
20 import org.astrogrid.dataservice.queriers.DefaultPlugin;
21 import org.astrogrid.dataservice.queriers.Querier;
22 import org.astrogrid.dataservice.queriers.UrlListResults;
23 import org.astrogrid.dataservice.queriers.status.QuerierQuerying;
24 import org.astrogrid.query.Query;
25 import org.astrogrid.query.xql.XqlMaker;
26 import org.astrogrid.xml.DomHelper;
27 import org.w3c.dom.Document;
28 import org.w3c.dom.Element;
29 import org.w3c.dom.NodeList;
30 import org.xml.sax.SAXException;
31
32 import org.astrogrid.xmldb.client.QueryService;
33 import org.astrogrid.xmldb.client.XMLDBFactory;
34
35 import org.xmldb.api.base.ResourceSet;
36 import org.xmldb.api.modules.XMLResource;
37 import org.xmldb.api.base.Resource;
38 import org.xmldb.api.base.Collection;
39 import org.xmldb.api.base.XMLDBException;
40
41 /***
42 * The Standard Fits Querier plugin uses an XML 'index' document to search on.
43 * This index is generated once by running the IndexGenerator in this package
44 * across all the files. A configuration setting points to this index file, which
45 * is loaded into memory at the first query.
46 *
47 * However some indexes are too big to load, in which case the eXist XML database
48 * might be used. (This also gives better query options). In this case, leave
49 * the index references blank, and this class will send the query to the
50 * org.astrogrid.xmldb.eXist.server.QueryDBService; see elsewhere (unhelpful) for
51 * how to configure that.
52 *
53 *
54 * @author M Hill
55 */
56
57 public class FitsQuerierPlugin extends DefaultPlugin
58 {
59 public final static String FITS_DEFAULT_COLLECTION = "dcfitsfiles";
60
61 private XMLDBFactory xdb = new XMLDBFactory();
62
63
64 /*** Plugin implementation - carries out query.
65 */
66 public void askQuery(Principal user, Query query, Querier querier) throws IOException {
67
68 String[] filenames = null;
69
70 XqlMaker maker = new XqlMaker();
71 String xql = maker.getXql(query);
72
73 querier.setStatus(new QuerierQuerying(querier.getStatus(), xql));
74
75 filenames = useeXist(xql);
76
77 if ((!aborted) && (filenames != null)) {
78 querier.getStatus().addDetail(filenames+" files matched");
79 UrlListResults results = new UrlListResults(querier, filenames);
80 results.send(query.getResultsDef(), querier.getUser());
81 }
82 }
83
84 /*** Plugin implementation - returns number of matches
85 */
86 public long getCount(Principal user, Query query, Querier querier) throws IOException {
87
88 String[] filenames = null;
89
90 XqlMaker maker = new XqlMaker();
91 String xql = maker.getXql(query);
92
93 querier.setStatus(new QuerierQuerying(querier.getStatus(), xql));
94
95 filenames = useeXist(xql);
96
97 return filenames.length;
98 }
99
100 private String[] useeXist(String xql) throws IOException {
101 Document resultDoc = null;
102 String []files = new String[0];
103 Collection coll = null;
104 try {
105 coll = xdb.openCollection(FITS_DEFAULT_COLLECTION);
106 //log.info("Got Collection");
107 QueryService xqs = xdb.getQueryService(coll);
108
109 long beginQ = System.currentTimeMillis();
110 ResourceSet rs = xqs.query(xql);
111 //log.info("Total Query Time = " + (System.currentTimeMillis() - beginQ));
112 //log.info("Number of results found in query = " + rs.getSize());
113 if(rs.getSize() > 0) {
114 Resource xmlr = rs.getMembersAsResource();
115 resultDoc = DomHelper.newDocument(xmlr.getContent().toString());
116 }//if
117 }catch(XMLDBException xdbe) {
118 xdbe.printStackTrace();
119 throw new IOException("XMLDB exception, query most likely wrong or xml db is down XMLDB Exception");
120 }catch(SAXException se) {
121 throw new IOException("FitsQuerierPlugin index not valid xml");
122 }
123 if(resultDoc != null) {
124 NodeList fileNames = resultDoc.getElementsByTagName("Filename");
125 files = new String[fileNames.getLength()];
126 for(int i = 0;i < fileNames.getLength();i++) {
127 if(fileNames.item(i).hasChildNodes()) {
128 files[i] = fileNames.item(i).getFirstChild().getNodeValue();
129 }//if
130 }//for
131 }//if
132 return files;
133 }
134
135
136 /***
137 * locates all the fits files in this dataset that overlap the given
138 * circular region
139 */
140 public String[] coneSearch(double ra, double dec, double sr) throws IOException
141 {
142 /*
143 Ellipse2D cone = new Ellipse2D.Double(ra-sr, dec-sr, sr*2,sr*2);
144 Area matchingArea = new Area(cone);
145
146 Hashtable intersectingFits = new Hashtable();
147
148 //first locate all the coverage nodes in the index
149 NodeList coverages = index.getElementsByTagName("Coverage");
150
151 for (int i=0;i<coverages.getLength();i++)
152 {
153 //extract coverage region
154 Area coverage = new Area(getCoverageFromIndex( (Element) coverages.item(i)));
155
156 //does it intersect with circle?
157 if (intersects(matchingArea, coverage))
158 {
159 //find parent tag describing whole file
160 Element parent = (Element) coverages.item(i).getParentNode();
161
162 String filename = DomHelper.getValue(parent, "Filename");
163 //add if not already there - ie ignore duplicates, which might
164 //happen if a FITS has several images
165 if (intersectingFits.get(filename) == null)
166 {
167 intersectingFits.put(filename, filename);
168 }
169 }
170
171 if (aborted) break; //stop if we've been aborted
172 }
173
174 return (String[]) intersectingFits.values().toArray(new String[] {});
175 */
176 throw new IOException("ConeSearches currently not supported by FitsQuerierPlugin.");
177 }
178
179 /***
180 * Looks through the coverage in the index and returns a suitable 'shape' to
181 * represent that region. At the moment it just returns a 'general path' with
182 * the given points in it
183 */
184 public GeneralPath getCoverageFromIndex(Element dom)
185 {
186 return null;
187 /*
188 GeneralPath region = new GeneralPath();
189
190 NodeList points = dom.getElementsByTagName("Point");
191
192 for (int l=0;l<points.getLength();l++)
193 {
194 float ra = Float.parseFloat(DomHelper.getValue((Element) points.item(l), "RA"));
195 float dec = Float.parseFloat(DomHelper.getValue((Element) points.item(l), "Dec"));
196
197 if (l==0) {
198 region.moveTo(ra, dec);
199 } else {
200 region.lineTo(ra, dec);
201 }
202 }
203
204 return region;
205 */
206 }
207
208 /***
209 * returns true if area 1 intersects with area 2
210 * At the moment checks if the rectangular *boundaries* of area 1 intersect
211 * with area 2.
212 * @todo do properly
213 */
214 public boolean intersects(Area a1, Area a2)
215 {
216 return a2.intersects(a1.getBounds2D());
217 }
218
219 /***
220 * Loads the index - one off operation
221 */
222 protected synchronized void loadIndex() throws IOException {
223 return;
224 }
225
226 /*** Returns the formats that this plugin can provide. Asks the results class; override in subclasse if nec */
227 public String[] getFormats() {
228 return UrlListResults.listFormats();
229 }
230
231 }
232
233 /*
234 $Log: FitsQuerierPlugin.java,v $
235 Revision 1.3 2005/03/21 18:45:55 mch
236 Naughty big lump of changes
237
238 Revision 1.2 2005/03/11 14:50:59 KevinBenson
239 added catch for parserconfigurationexception
240
241 Revision 1.1 2005/03/10 16:42:55 mch
242 Split fits, sql and xdb
243
244 Revision 1.3 2005/03/10 13:59:00 KevinBenson
245 corrections to fits and testing to fits
246
247 Revision 1.2 2005/03/08 15:03:24 KevinBenson
248 new stuff for Fits querier to work with an internal xml database
249
250 Revision 1.1.1.1 2005/02/17 18:37:35 mch
251 Initial checkin
252
253 Revision 1.1.1.1 2005/02/16 17:11:24 mch
254 Initial checkin
255
256 Revision 1.7.2.3 2004/12/08 18:36:40 mch
257 Added Vizier, rationalised SqlWriters etc, separated out TableResults from QueryResults
258
259 Revision 1.7.2.2 2004/11/24 20:59:37 mch
260 doc fixes and added slinger browser
261
262 Revision 1.7.2.1 2004/11/22 00:57:16 mch
263 New interfaces for SIAP etc and new slinger package
264
265 Revision 1.7 2004/11/12 13:49:12 mch
266 Fix where keyword maker might not have had keywords made
267
268 Revision 1.6 2004/11/11 23:23:29 mch
269 Prepared framework for SSAP and SIAP
270
271 Revision 1.5 2004/11/09 17:42:22 mch
272 Fixes to tests after fixes for demos, incl adding closable to targetIndicators
273
274 Revision 1.4 2004/11/03 00:17:56 mch
275 PAL_MCH Candidate 2 merge
276
277 Revision 1.3.6.1 2004/10/27 00:43:39 mch
278 Started adding getCount, some resource fixes, some jsps
279
280 Revision 1.3 2004/10/18 13:11:30 mch
281 Lumpy Merge
282
283 Revision 1.2.2.1 2004/10/15 19:59:05 mch
284 Lots of changes during trip to CDS to improve int test pass rate
285
286 Revision 1.2 2004/10/06 21:12:17 mch
287 Big Lump of changes to pass Query OM around instead of Query subclasses, and TargetIndicator mixed into Slinger
288
289 Revision 1.1 2004/09/28 15:02:13 mch
290 Merged PAL and server packages
291
292 Revision 1.7 2004/09/08 17:44:18 mch
293 Fix for URL not being a servlet
294
295 Revision 1.6 2004/09/07 00:54:20 mch
296 Tidied up Querier/Plugin/Results, and removed deprecated SPI-visitor-SQL-translator
297
298 Revision 1.5 2004/08/09 13:04:31 KevinBenson
299 small change to get the servlet from the index
300
301 Revision 1.4 2004/07/26 13:53:44 KevinBenson
302 Changes to Fits to do an xquery on an xml file dealing with fits data.
303 Small xsl style sheet to make the xql which will get the filename element
304
305 Revision 1.3.30.1 2004/07/26 08:53:40 KevinBenson
306 Still need to make a few more corrections, but wanted to check this in now.
307 It is the fits querier that now uses exist for doing adql->xquery
308
309 Revision 1.3 2004/03/15 19:16:12 mch
310 Lots of fixes to status updates
311
312 Revision 1.2 2004/03/12 20:04:57 mch
313 It05 Refactor (Client)
314
315 Revision 1.1 2004/03/12 04:45:26 mch
316 It05 MCH Refactor
317
318 Revision 1.14 2004/03/08 00:31:28 mch
319 Split out webservice implementations for versioning
320
321 Revision 1.13 2004/01/14 17:57:32 nw
322 improved documentation
323
324 Revision 1.12 2004/01/13 00:33:14 nw
325 Merged in branch providing
326 * sql pass-through
327 * replace Certification by User
328 * Rename _query as Query
329
330 Revision 1.11.6.2 2004/01/08 09:43:41 nw
331 replaced adql front end with a generalized front end that accepts
332 a range of query languages (pass-thru sql at the moment)
333
334 Revision 1.11.6.1 2004/01/07 11:51:07 nw
335 found out how to get wsdl to generate nice java class names.
336 Replaced _query with Query throughout sources.
337
338 Revision 1.11 2003/12/09 12:31:23 mch
339 New Fits Result set
340
341 Revision 1.10 2003/12/03 19:37:03 mch
342 Introduced DirectDelegate, fixed DummyQuerier
343
344 Revision 1.9 2003/12/03 15:25:13 mch
345 Fix to ignoring duplicates
346
347 Revision 1.8 2003/12/02 17:58:05 mch
348 Removed duplicate filenames
349
350 Revision 1.7 2003/12/01 20:57:39 mch
351 Abstracting coarse-grained plugin
352
353 Revision 1.6 2003/11/28 19:57:15 mch
354 Cone Search now works
355
356 Revision 1.5 2003/11/28 19:16:53 mch
357 Extended matching
358
359 Revision 1.4 2003/11/28 18:22:18 mch
360 IndexGenerator now working
361
362 Revision 1.3 2003/11/28 16:10:30 nw
363 finished plugin-rewrite.
364 added tests to cover plugin system.
365 cleaned up querier & queriermanager. tested
366
367 Revision 1.2 2003/11/27 00:52:58 nw
368 refactored to introduce plugin-back end and translator maps.
369 interfaces in place. still broken code in places.
370
371 Revision 1.1 2003/11/25 18:50:06 mch
372 Abstracted Querier from DatabaseQuerier
373
374 */
375
376
377
378