View Javadoc

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