comparison src/main/java/nl/cwi/monetdb/util/XMLExporter.java @ 0:a5a898f6886c

Copy of MonetDB java directory changeset e6e32756ad31.
author Sjoerd Mullender <sjoerd@acm.org>
date Wed, 21 Sep 2016 09:34:48 +0200 (2016-09-21)
parents
children 57978db4ee57 17fbaf2635bb
comparison
equal deleted inserted replaced
-1:000000000000 0:a5a898f6886c
1 /*
2 * This Source Code Form is subject to the terms of the Mozilla Public
3 * License, v. 2.0. If a copy of the MPL was not distributed with this
4 * file, You can obtain one at http://mozilla.org/MPL/2.0/.
5 *
6 * Copyright 1997 - July 2008 CWI, August 2008 - 2016 MonetDB B.V.
7 */
8
9 package nl.cwi.monetdb.util;
10
11 import java.io.*;
12 import java.sql.*;
13 import java.util.*;
14 import java.text.*;
15
16 public class XMLExporter extends Exporter {
17 private boolean useNil;
18
19 public final static int TYPE_NIL = 1;
20 public final static int VALUE_OMIT = 0;
21 public final static int VALUE_XSI = 1;
22
23 public XMLExporter(PrintWriter out) {
24 super(out);
25 }
26
27 public void dumpSchema(
28 DatabaseMetaData dbmd,
29 String type,
30 String catalog,
31 String schema,
32 String name)
33 throws SQLException
34 {
35 if (type.indexOf("VIEW") != -1) {
36 String[] types = new String[1];
37 types[0] = type;
38 ResultSet tbl = dbmd.getTables(catalog, schema, name, types);
39 if (!tbl.next()) throw new SQLException("Whoops no data for " + name);
40
41 // This will probably only work for MonetDB
42 out.print("<!-- unable to represent: CREATE " + type + " " +
43 (!useSchema ? dq(schema) + "." : "") + dq(name));
44 out.print(" AS ");
45 out.print(tbl.getString("REMARKS").trim());
46 out.print(" -->");
47 return;
48 }
49
50 out.println("<xsd:schema>");
51
52 ResultSet cols = dbmd.getColumns(catalog, schema, name, null);
53 String ident;
54 Set<String> types = new HashSet<String>();
55 // walk through the ResultSet and create the types
56 // for a bit of a clue on the types, see this url:
57 // http://books.xmlschemata.org/relaxng/relax-CHP-19.html
58 while (cols.next()) {
59 switch (cols.getInt("DATA_TYPE")) {
60 case java.sql.Types.CHAR:
61 ident = "CHAR_" + cols.getString("COLUMN_SIZE");
62 if (types.contains(ident)) break;
63 types.add(ident);
64
65 out.print(" <xsd:simpleType name=");
66 out.print(dq(ident));
67 out.println(">");
68 out.println(" <xsd:restriction base=\"xsd:string\">");
69 out.print(" <xsd:length value=");
70 out.print(dq(cols.getString("COLUMN_SIZE")));
71 out.println(" />");
72 out.println(" </xsd:restriction>");
73 out.println(" </xsd:simpleType>");
74 break;
75 case java.sql.Types.VARCHAR:
76 case java.sql.Types.LONGVARCHAR:
77 ident = "VARCHAR_" + cols.getString("COLUMN_SIZE");
78 if (types.contains(ident)) break;
79 types.add(ident);
80
81 out.print(" <xsd:simpleType name=");
82 out.print(dq(ident));
83 out.println(">");
84 out.println(" <xsd:restriction base=\"xsd:string\">");
85 out.print(" <xsd:maxLength value=");
86 out.print(dq(cols.getString("COLUMN_SIZE")));
87 out.println(" />");
88 out.println(" </xsd:restriction>");
89 out.println(" </xsd:simpleType>");
90 break;
91 case java.sql.Types.CLOB:
92 ident = "CLOB";
93 if (types.contains(ident)) break;
94 types.add(ident);
95
96 out.print(" <xsd:simpleType name=");
97 out.print(dq(ident));
98 out.println(">");
99 out.println(" <xsd:restriction base=\"xsd:string\" />");
100 out.println(" </xsd:simpleType>");
101 break;
102 case java.sql.Types.DECIMAL:
103 case java.sql.Types.NUMERIC:
104 ident = "DECIMAL_" + cols.getString("COLUMN_SIZE") +
105 "_" + cols.getString("DECIMAL_DIGITS");
106 if (types.contains(ident)) break;
107 types.add(ident);
108
109 out.print(" <xsd:simpleType name=");
110 out.print(dq(ident));
111 out.println(">");
112 out.println(" <xsd:restriction base=\"xsd:decimal\">");
113 out.print(" <xsd:totalDigits value=");
114 out.print(dq(cols.getString("COLUMN_SIZE")));
115 out.println(" />");
116 out.print(" <xsd:fractionDigits value=");
117 out.print(dq(cols.getString("DECIMAL_DIGITS")));
118 out.println(" />");
119 out.println(" </xsd:restriction>");
120 out.println(" </xsd:simpleType>");
121 break;
122 case java.sql.Types.TINYINT:
123 ident = "TINYINT";
124 if (types.contains(ident)) break;
125 types.add(ident);
126
127 out.print(" <xsd:simpleType name=");
128 out.print(dq(ident));
129 out.println(">");
130 out.println(" <xsd:restriction base=\"xsd:byte\" />");
131 out.println(" </xsd:simpleType>");
132 break;
133 case java.sql.Types.SMALLINT:
134 ident = "SMALLINT";
135 if (types.contains(ident)) break;
136 types.add(ident);
137
138 out.print(" <xsd:simpleType name=");
139 out.print(dq(ident));
140 out.println(">");
141 out.println(" <xsd:restriction base=\"xsd:short\" />");
142 out.println(" </xsd:simpleType>");
143 break;
144 case java.sql.Types.INTEGER:
145 ident = "INTEGER";
146 if (types.contains(ident)) break;
147 types.add(ident);
148
149 out.print(" <xsd:simpleType name=");
150 out.print(dq(ident));
151 out.println(">");
152 out.println(" <xsd:restriction base=\"xsd:integer\" />");
153 out.println(" </xsd:simpleType>");
154 break;
155 case java.sql.Types.BIGINT:
156 ident = "BIGINT";
157 if (types.contains(ident)) break;
158 types.add(ident);
159
160 out.print(" <xsd:simpleType name=");
161 out.print(dq(ident));
162 out.println(">");
163 out.println(" <xsd:restriction base=\"xsd:long\" />");
164 out.println(" </xsd:simpleType>");
165 break;
166 case java.sql.Types.BIT:
167 case java.sql.Types.BOOLEAN:
168 ident = "BOOLEAN";
169 if (types.contains(ident)) break;
170 types.add(ident);
171
172 out.print(" <xsd:simpleType name=");
173 out.print(dq(ident));
174 out.println(">");
175 out.println(" <xsd:restriction base=\"xsd:boolean\" />");
176 out.println(" </xsd:simpleType>");
177 break;
178 case java.sql.Types.DATE:
179 ident = "DATE";
180 if (types.contains(ident)) break;
181 types.add(ident);
182
183 out.print(" <xsd:simpleType name=");
184 out.print(dq(ident));
185 out.println(">");
186 out.println(" <xsd:restriction base=\"xsd:date\" />");
187 out.println(" </xsd:simpleType>");
188 break;
189 case java.sql.Types.TIME:
190 if ("timetz".equals(cols.getString("TYPE_NAME"))) {
191 ident = "TIME_WTZ";
192 } else {
193 ident = "TIME";
194 }
195 if (types.contains(ident)) break;
196 types.add(ident);
197
198 out.print(" <xsd:simpleType name=");
199 out.print(dq(ident));
200 out.println(">");
201 out.println(" <xsd:restriction base=\"xsd:time\" />");
202 out.println(" </xsd:simpleType>");
203 break;
204 case java.sql.Types.TIMESTAMP:
205 if ("timestamptz".equals(cols.getString("TYPE_NAME"))) {
206 ident = "TIMESTAMP_WTZ";
207 } else {
208 ident = "TIMESTAMP";
209 }
210 if (types.contains(ident)) break;
211 types.add(ident);
212
213 out.print(" <xsd:simpleType name=");
214 out.print(dq(ident));
215 out.println(">");
216 out.println(" <xsd:restriction base=\"xsd:dateTime\" />");
217 out.println(" </xsd:simpleType>");
218 break;
219 }
220 }
221
222 // rewind the ResultSet
223 cols.beforeFirst();
224
225 // create the RowType
226 out.print(" <xsd:complexType name=");
227 out.print(dq("RowType." + catalog.replaceAll("\\.", "_x002e_") +
228 "." + schema.replaceAll("\\.", "_x002e_") +
229 "." + name.replaceAll("\\.", "_x002e_")));
230 out.println(">");
231 out.println(" <xsd:sequence>");
232 while (cols.next()) {
233 out.print(" <xsd:element name=");
234 out.print(dq(cols.getString("COLUMN_NAME")));
235 out.print(" type=");
236 switch (cols.getInt("DATA_TYPE")) {
237 case java.sql.Types.CHAR:
238 ident = "CHAR_" + cols.getString("COLUMN_SIZE");
239 break;
240 case java.sql.Types.VARCHAR:
241 case java.sql.Types.LONGVARCHAR:
242 ident = "VARCHAR_" + cols.getString("COLUMN_SIZE");
243 break;
244 case java.sql.Types.CLOB:
245 ident = "CLOB";
246 break;
247 case java.sql.Types.DECIMAL:
248 case java.sql.Types.NUMERIC:
249 ident = "DECIMAL_" + cols.getString("COLUMN_SIZE") +
250 "_" + cols.getString("DECIMAL_DIGITS");
251 break;
252 case java.sql.Types.TINYINT:
253 ident = "TINYINT";
254 break;
255 case java.sql.Types.SMALLINT:
256 ident = "SMALLINT";
257 break;
258 case java.sql.Types.INTEGER:
259 ident = "INTEGER";
260 break;
261 case java.sql.Types.BIGINT:
262 ident = "BIGINT";
263 break;
264 case java.sql.Types.BIT:
265 case java.sql.Types.BOOLEAN:
266 ident = "BOOLEAN";
267 break;
268 case java.sql.Types.DATE:
269 ident = "DATE";
270 break;
271 case java.sql.Types.TIME:
272 if ("timetz".equals(cols.getString("TYPE_NAME"))) {
273 ident = "TIME_WTZ";
274 } else {
275 ident = "TIME";
276 }
277 break;
278 case java.sql.Types.TIMESTAMP:
279 if ("timestamptz".equals(cols.getString("TYPE_NAME"))) {
280 ident = "TIMESTAMP_WTZ";
281 } else {
282 ident = "TIMESTAMP";
283 }
284 break;
285 default:
286 ident = "(unknown)";
287 break;
288 }
289 out.print(dq(ident));
290 out.println(" />");
291 }
292 out.println(" </xsd:sequence>");
293 out.println(" </xsd:complexType>");
294
295 out.print(" <xsd:complexType name=");
296 out.print(dq("TableType." + catalog.replaceAll("\\.", "_x002e_") +
297 "." + schema.replaceAll("\\.", "_x002e_") +
298 "." + name.replaceAll("\\.", "_x002e_")));
299 out.println(">");
300 out.println(" <xsd:sequence>");
301 out.print(" <xsd:element name=\"row\" type=");
302 out.print(dq("RowType." + catalog.replaceAll("\\.", "_x002e_") +
303 "." + schema.replaceAll("\\.", "_x002e_") +
304 "." + name.replaceAll("\\.", "_x002e_")));
305 out.println(" minOccurs=\"0\" maxOccurs=\"unbounded\" />");
306 out.println(" </xsd:sequence>");
307 out.println(" </xsd:complexType>");
308
309 out.println("</xsd:schema>");
310 }
311
312 private final static SimpleDateFormat xsd_ts =
313 new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss");
314 private final static SimpleDateFormat xsd_tstz =
315 new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ssZ");
316
317 /**
318 * Generates an XML representation of the given ResultSet.
319 *
320 * @param rs the ResultSet
321 */
322 public void dumpResultSet(ResultSet rs) throws SQLException {
323 // write simple XML serialisation
324 ResultSetMetaData rsmd = rs.getMetaData();
325 if (!useSchema) out.println("<" + rsmd.getSchemaName(1) + ">");
326 out.println("<" + rsmd.getTableName(1) + ">");
327 String data;
328 while (rs.next()) {
329 out.println(" <row>");
330 for (int i = 1; i <= rsmd.getColumnCount(); i++) {
331 switch (rsmd.getColumnType(i)) {
332 case java.sql.Types.TIMESTAMP:
333 Timestamp ts = rs.getTimestamp(i);
334 if ("timestamptz".equals(rsmd.getColumnTypeName(i))) {
335 data = xsd_tstz.format(ts).toString();
336 } else {
337 data = xsd_ts.format(ts).toString();
338 }
339 break;
340 default:
341 data = rs.getString(i);
342 break;
343 }
344 if (data == null) {
345 if (useNil) {
346 // "nil" method: write <tag xsi:nil="true" />
347 out.print(" ");
348 out.print("<" + rsmd.getColumnLabel(i));
349 out.println(" xsi:nil=\"true\" />");
350 } else {
351 // This is the "absent" method (of completely
352 // hiding the tag if null
353 }
354 } else {
355 out.print(" ");
356 out.print("<" + rsmd.getColumnLabel(i));
357 if (data.length() == 0) {
358 out.println(" />");
359 } else {
360 out.print(">" + data.replaceAll("&", "&amp;").replaceAll("<", "&lt;").replaceAll(">", "&gt;"));
361 out.println("</" + rsmd.getColumnLabel(i) + ">");
362 }
363 }
364 }
365 out.println(" </row>");
366 }
367 out.println("</" + rsmd.getTableName(1) + ">");
368 if (!useSchema) out.println("</" + rsmd.getSchemaName(1) + ">");
369 }
370
371 public void setProperty(int type, int value) throws Exception {
372 switch (type) {
373 case TYPE_NIL:
374 switch (value) {
375 case VALUE_OMIT:
376 useNil = false;
377 break;
378 case VALUE_XSI:
379 useNil = true;
380 break;
381 default:
382 throw new Exception("Illegal value " + value + " for TYPE_NIL");
383 }
384 break;
385 default:
386 throw new Exception("Illegal type " + type);
387 }
388 }
389
390 public int getProperty(int type) throws Exception {
391 switch (type) {
392 case TYPE_NIL:
393 return useNil ? VALUE_XSI : VALUE_OMIT;
394 default:
395 throw new Exception("Illegal type " + type);
396 }
397 }
398 }