1
2
3
4
5
6
7 package org.astrogrid.dataservice.queriers;
8
9 import java.io.IOException;
10 import java.lang.reflect.Constructor;
11 import java.lang.reflect.InvocationTargetException;
12 import java.security.Principal;
13 import org.apache.commons.logging.Log;
14 import org.apache.commons.logging.LogFactory;
15 import org.astrogrid.cfg.ConfigException;
16 import org.astrogrid.cfg.ConfigFactory;
17 import org.astrogrid.dataservice.DatacenterException;
18 import org.astrogrid.dataservice.queriers.status.QuerierProcessingResults;
19 import org.astrogrid.dataservice.queriers.status.QuerierStatus;
20 import org.astrogrid.query.returns.ReturnSpec;
21 import org.astrogrid.query.returns.ReturnTable;
22 import org.astrogrid.slinger.SRI;
23 import org.astrogrid.slinger.targets.TargetIdentifier;
24 import org.astrogrid.slinger.vospace.HomespaceName;
25 import org.astrogrid.slinger.vospace.IVOSRN;
26 import org.astrogrid.tableserver.out.FilteredTableWriter;
27 import org.astrogrid.tableserver.out.HtmlTableWriter;
28 import org.astrogrid.tableserver.out.TableWriter;
29 import org.astrogrid.tableserver.out.VoTableWriter;
30 import org.astrogrid.tableserver.out.XsvTableWriter;
31
32 /*** A container interface that holds the results of a query that is in some
33 * way a table. Implementations might be SqlResults.
34 *
35 * @author M Hill
36 */
37
38 public abstract class TableResults implements QueryResults
39 {
40
41 Log log = LogFactory.getLog(TableResults.class);
42
43 public final static String TABLE_FILTERS_KEY = "datacenter.table.filter";
44
45 protected Querier querier = null;
46
47 /*** Construct with a link to the Querier that spawned these results, so we
48 * can include info from it if need be */
49 public TableResults(Querier parentQuerier) {
50 this.querier = parentQuerier;
51 }
52
53 /*** Subclasses implement suitable ways of writing their results to the given TableWriter */
54 public abstract void writeTable(TableWriter tableWriter, QuerierStatus statusToUpdate) throws IOException;
55
56
57 /*** returns the formats that this result implementation can produce (ie VOTABLE, HTML, CSV, etc) */
58 public static String[] listFormats() {
59 return new String[] { ReturnTable.VOTABLE, ReturnTable.CSV, ReturnTable.HTML };
60 }
61
62 /*** Returns the number of results - or -1 if unknown */
63 public abstract int getCount() throws IOException;
64
65 /*** This is a helper method for plugins; it is meant to be called
66 * from the askQuery method. It transforms the results and sends them
67 * as required, updating the querier status appropriately.
68 */
69 public void send(ReturnSpec returns, Principal user) throws IOException {
70 if (returns instanceof ReturnTable) {
71 sendTable( (ReturnTable) returns, user);
72 }
73 else {
74 throw new UnsupportedOperationException("Unknown return type "+returns.getClass().getName());
75 }
76 }
77
78 /*** Subclasses override to make spocial table writers. requested format is given
79 * as a mime type*/
80 public TableWriter makeTableWriter(TargetIdentifier target, String requestedFormat, Principal user) throws IOException {
81
82 if (requestedFormat.equals(ReturnTable.VOTABLE)) {
83 return new VoTableWriter(target, "Query Results", user);
84 }
85 else if (requestedFormat.equals(ReturnTable.CSV)) {
86 return new XsvTableWriter(target, "Query Results", ",", user);
87 }
88 else if (requestedFormat.equals(ReturnTable.TSV)) {
89 return new XsvTableWriter(target, "Query Results", "\t", user);
90 }
91 else if (requestedFormat.equals(ReturnTable.HTML)) {
92 return new HtmlTableWriter(target, "Query Results", querier.getQuery().toString(), user);
93 }
94
95
96
97
98
99
100 else if (requestedFormat.equals(ReturnTable.DEFAULT)) {
101 return new VoTableWriter(target, "Query Results", user);
102 }
103 else {
104 throw new IllegalArgumentException("Unknown results format "+requestedFormat+" given");
105 }
106 }
107
108 /*** Sends a table */
109 public void sendTable(ReturnTable returns, Principal user) throws IOException {
110
111 QuerierProcessingResults status = new QuerierProcessingResults(querier.getStatus());
112 querier.setStatus(status);
113
114 log.info(querier+", sending results to "+returns);
115
116 TargetIdentifier target = returns.getTarget();
117 String format = returns.getFormat();
118
119 if (target == null) {
120 throw new DatacenterException("No Target given for results");
121 }
122
123 status.setMessage("Sending results to "+target.toString()+" as "+format);
124
125 TableWriter tableWriter = makeTableWriter(target, format, user);
126
127
128 Class filterClass = ConfigFactory.getCommonConfig().getClass(TABLE_FILTERS_KEY, null);
129 if (filterClass != null) {
130
131 tableWriter = makeTableWriter(filterClass, tableWriter);
132 }
133
134
135 writeTable(tableWriter, status);
136
137 if (querier.isAborted()) {
138 return;
139 }
140
141 String s = "Results sent as table ("+format+") to ";
142
143 if (returns.getTarget() instanceof SRI) {
144 s =s+"<a href='ViewFile?"+((SRI) target).toURI()+"'>"+target+"</a>";
145 }
146 else {
147 s =s+target;
148 }
149
150 if (target instanceof IVOSRN) {
151 s = s + " -> "+((IVOSRN) target).resolve();
152 }
153 try {
154 if (target instanceof HomespaceName) {
155 s = s + " -> "+( (HomespaceName) target).resolveIvosrn();
156 s = s + " -> "+((HomespaceName) target).toLocation(user);
157 }
158 }
159 catch (Exception e) {
160 log.error(e+" resolving "+target+" for adding to status ",e);
161 }
162
163 status.addDetail(s);
164 status.setMessage("");
165
166 log.info(querier+" results sent");
167 }
168
169
170 public TableWriter makeTableWriter(Class filter, TableWriter writer) {
171 if (!filter.isInstance(FilteredTableWriter.class)) {
172 throw new ConfigException("tablewriter filter class given by "+TABLE_FILTERS_KEY+" is not a FilteredTableWriter");
173 }
174 try {
175 Constructor constr = filter.getConstructor(new Class[] { TableWriter.class });
176 return (TableWriter) constr.newInstance(new Object[] { writer } );
177 }
178 catch (NoSuchMethodException nsme) {
179 throw new ConfigException("Class "+filter+" given by "+TABLE_FILTERS_KEY+" must extend FilteredTableWriter and have a constructor that takes only a TableWriter");
180 }
181 catch (InvocationTargetException e) {
182 throw new ConfigException("Class "+filter+" given by "+TABLE_FILTERS_KEY+" fails to construct",e);
183 }
184 catch (IllegalAccessException e) {
185 throw new ConfigException("Class "+filter+" given by "+TABLE_FILTERS_KEY+" fails to construct",e);
186 }
187 catch (InstantiationException e) {
188 throw new ConfigException("Class "+filter+" given by "+TABLE_FILTERS_KEY+" fails to construct",e);
189 }
190 }
191
192 }
193
194
195
196