View Javadoc

1   /*
2    * $Id: VoTableWriter.java,v 1.4 2005/03/30 21:51:25 mch Exp $
3    *
4    * (C) Copyright Astrogrid...
5    */
6   
7   package org.astrogrid.tableserver.out;
8   import java.io.BufferedWriter;
9   import java.io.IOException;
10  import java.io.PrintWriter;
11  import java.io.Writer;
12  import java.security.Principal;
13  import java.util.Date;
14  import org.apache.commons.logging.Log;
15  import org.astrogrid.slinger.mime.MimeTypes;
16  import org.astrogrid.slinger.targets.TargetIdentifier;
17  import org.astrogrid.tableserver.metadata.ColumnInfo;
18  
19  /***
20   * For writing out tables in votable.  As far as I'm aware dates are not handled
21   * by VOTables (by Jan 2005).  Since I'm stroppely ignoring VOTable development as
22   * irrelevent (ie I'm not going to try and push for standard date support, they can
23   * get around to it whenever), dates here are written as the 'C standard' number of seconds since
24   * 1970 (negative numbers before 1970), with type 'float' so we can provide milliseconds
25   * etc. NB we need to handle dates from several thousand BC.
26   *
27   * @author M Hill
28   */
29  
30  public class VoTableWriter implements TableWriter {
31     
32     
33     protected static final Log log = org.apache.commons.logging.LogFactory.getLog(VoTableWriter.class);
34     
35     protected PrintWriter printOut = null;
36     
37     protected ColumnInfo[] cols = null;
38     
39     public final static String TYPE_LONG      = "long";
40     public final static String TYPE_BOOLEAN   = "boolean";
41     public final static String TYPE_BIT       = "bit";
42     public final static String TYPE_UBYTE     = "unsignedByte";
43     public final static String TYPE_CHAR      = "char";
44     public final static String TYPE_UNICHAR   = "unicodeChar";
45     public final static String TYPE_DOUBLE    = "double";
46     public final static String TYPE_FLOAT     = "float";
47     public final static String TYPE_DOUBLECOMPLEX = "doubleComplex";
48     public final static String TYPE_FLOATCOMPLEX  = "floatComplex";
49     public final static String TYPE_INT       = "int";
50     public final static String TYPE_SHORT     = "short";
51     
52     public final static String[] TYPES = new String[] {
53        TYPE_LONG, TYPE_BOOLEAN, TYPE_BIT, TYPE_UBYTE, TYPE_CHAR, TYPE_UNICHAR, TYPE_DOUBLE, TYPE_FLOAT, TYPE_DOUBLECOMPLEX, TYPE_FLOATCOMPLEX, TYPE_INT, TYPE_SHORT
54     };
55     
56     /***
57      * Construct this wrapping the given stream.  Writes out the first few tags
58      */
59     public VoTableWriter(TargetIdentifier target, String title, Principal user) throws IOException {
60        
61        target.setMimeType(MimeTypes.VOTABLE, user);
62        
63        printOut = new PrintWriter(new BufferedWriter(target.resolveWriter(user)));
64        
65  //         printOut.println("<!DOCTYPE VOTABLE SYSTEM 'http://us-vo.org/xml/VOTable.dtd'>");
66           printOut.println("<VOTABLE version='1.0'>");
67           
68           /* don't know where to find this info - in the netadata I expect
69            <DEFINITIONS>
70            <COOSYS ID="myJ2000" system="eq_FK5" equinox="2000." epoch="2000."/>
71            </DEFINITIONS>
72            */
73           
74           printOut.println("<RESOURCE>");
75           /* don't know where to find this info - in the netadata I expect
76            <PARAM ID="RA" datatype="E" value="200.0"/>
77            <PARAM ID="DE" datatype="E" value="40.0"/>
78            <PARAM ID="SR" datatype="E" value="30.0"/>
79            <PARAM ID="PositionalError" datatype="E" value="0.1"/>
80            <PARAM ID="Credit" datatype="A" arraysize="*" value="Charles Messier, Richard Gelderman"/>
81            */
82        
83        
84     }
85     
86     
87     /*** Produces text/html */
88     public String getMimeType() {
89        return MimeTypes.VOTABLE;
90     }
91     
92     /***Returns the VOTable type for the given java class type */
93     public static String getVoTableType(Class javatype) {
94        if (javatype == String.class) {        return TYPE_CHAR;    }
95        else if (javatype == Integer.class) {  return TYPE_INT;     }
96        else if (javatype == Long.class)    {  return TYPE_INT;    }
97        else if (javatype == Float.class)   {  return TYPE_FLOAT;   }
98        else if (javatype == Double.class) {   return TYPE_FLOAT;  }
99        else if (javatype == Boolean.class) {  return TYPE_BOOLEAN;    }
100       else if (javatype == Date.class)    {  return TYPE_FLOAT;    }
101       else {
102          log.error("Don't know what VOtable type the java class "+javatype+" maps to, returning string");
103          return TYPE_CHAR;
104       }
105    }
106    
107    
108    /*** Start body - writes out header and preps col array */
109    public void startTable(ColumnInfo[] cols) throws IOException {
110       
111       printOut.println("<TABLE>");
112          
113       for (int i = 0; i < cols.length; i++) {
114          if (cols[i] == null) {
115             throw new IllegalArgumentException("No information for column "+i);
116          }
117       
118          printOut.print("<FIELD name='"+cols[i].getName()+"' ");
119          if (cols[i].getId() != null) printOut.print("ID='"+cols[i].getId()+"' ");
120          if (cols[i].getUcd("1") != null) printOut.print(" ucd='"+cols[i].getUcd("1")+"' ");
121          
122          //type
123          if (cols[i].getPublicType() != null) {
124             //do some checking on data types
125             String type = null;
126             for (int t = 0; t < TYPES.length; t++)
127             {
128                if (cols[i].getPublicType().equals(TYPES[t])) {
129                   type = TYPES[t]; //found a match
130                }
131             }
132             if (type == null) {
133                //nothign found, try converting from common types
134                if (cols[i].getPublicType().toLowerCase().equals("real")) {
135                   type = TYPE_FLOAT;
136                }
137                else if (cols[i].getPublicType().toLowerCase().equals("smallint")) {
138                   type = TYPE_INT;
139                }
140                else if (cols[i].getPublicType().toLowerCase().equals("varchar")) {
141                   type = TYPE_CHAR;
142                }
143             }
144          
145             if (type==null) {
146                type = getVoTableType(cols[i].getJavaType());
147             }
148             
149             if (type != null) {
150                printOut.print(" datatype='"+type+"'");
151             }
152          }
153 
154          //units
155          if (cols[i].getJavaType() == Date.class) {
156             printOut.print(" units='s' ");
157          }
158          else {
159             if (cols[i].getUnits() != null) printOut.print(" units='"+cols[i].getUnits()+"' ");
160          }
161          printOut.println("/>");
162       }
163 
164       printOut.flush(); //so something comes back to the browser quickly
165       
166       //start body table
167       printOut.println("<DATA>");
168       printOut.println("<TABLEDATA>");
169       
170    }
171    
172    /*** Writes the given array of values out */
173    public void writeRow(Object[] colValues) throws IOException {
174       
175       printOut.print("<TR>");
176       for (int i=0;i<colValues.length;i++) {
177          if (colValues[i] instanceof Date) {
178             printOut.print("<TD>"+ (float) (((Date) colValues[i]).getTime()/1000) +"</TD>");
179          }
180          else {
181             printOut.print("<TD>"+colValues[i]+"</TD>");
182          }
183       }
184       printOut.println("</TR>");
185       
186    }
187 
188    public void endTable() {
189             //close row body
190          printOut.println("</TABLEDATA>");
191          printOut.println("</DATA>");
192 
193       //close document
194       printOut.println("</TABLE>");
195    }
196    
197    /*** Closes writer - writes out the closing tags and closes wrapped stream
198     */
199    public void close() {
200       
201       printOut.println("</RESOURCE>");
202       
203       printOut.println("</VOTABLE>");
204       
205       printOut.close();
206    }
207    
208    /*** Abort writes out a line to show the table is incomplete */
209    public void abort() {
210       printOut.println("<tr><td> ------------------ Writing Aborted -----------------</td></tr> ");
211       close();
212    }
213    
214    /*** Convenience method to get direct access to the output stream, so that we can pipe votables direct */
215    public Writer getOut() {
216       return printOut;
217    }
218    
219 }
220 
221 /*
222  $Log: VoTableWriter.java,v $
223  Revision 1.4  2005/03/30 21:51:25  mch
224  Fix to return Votable fits list for url list
225 
226  Revision 1.3  2005/03/30 18:54:03  mch
227  fixes to results format
228 
229  Revision 1.2  2005/03/30 15:52:15  mch
230  debug etc for bad sql types
231 
232  Revision 1.1  2005/03/21 18:45:55  mch
233  Naughty big lump of changes
234 
235  Revision 1.4  2005/03/10 15:13:48  mch
236  Seperating out fits, table and xdb servers
237 
238  Revision 1.3  2005/03/10 13:49:52  mch
239  Updating metadata
240 
241  Revision 1.2  2005/03/01 15:58:33  mch
242  Changed to use starlinks tamfits library
243 
244  Revision 1.1.1.1  2005/02/17 18:37:34  mch
245  Initial checkin
246 
247  Revision 1.1.1.1  2005/02/16 17:11:24  mch
248  Initial checkin
249 
250  Revision 1.1.2.10  2005/01/24 12:14:28  mch
251  Fixes to VizieR proxy and resource stuff
252 
253  Revision 1.1.2.9  2005/01/13 18:57:31  mch
254  Fixes to metadata mostly
255 
256  Revision 1.1.2.8  2004/12/13 21:53:14  mch
257  Made the java types the intermediate types, added types to Xsv and html output
258 
259  Revision 1.1.2.7  2004/12/08 18:36:40  mch
260  Added Vizier, rationalised SqlWriters etc, separated out TableResults from QueryResults
261 
262  Revision 1.1.2.6  2004/12/07 21:21:09  mch
263  Fixes after a days integration testing
264 
265  Revision 1.1.2.5  2004/12/07 00:49:42  mch
266  minor changes to put rows on one line (compact)
267 
268  Revision 1.1.2.4  2004/12/06 02:50:30  mch
269  a few bug fixes
270 
271  Revision 1.1.2.3  2004/12/05 19:33:16  mch
272  changed skynode to 'raw' soap (from axis) and bug fixes
273 
274  Revision 1.1.2.2  2004/11/30 02:32:18  mch
275  fix to 0-base of writerows
276 
277  Revision 1.1.2.1  2004/11/30 01:26:42  mch
278  added tablewriters
279 
280 
281 
282  */
283 
284 
285