KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > xquark > extractor > metadata > ExtractorMappingInfo


1 /*
2  * This file belongs to the XQuark distribution.
3  * Copyright (C) 2003 XQuark Group.
4  *
5  * This program is free software; you can redistribute it and/or
6  * modify it under the terms of the GNU Lesser General Public
7  * License as published by the Free Software Foundation; either
8  * version 2.1 of the License, or (at your option) any later version.
9  *
10  * This program is distributed in the hope that it will be useful,
11  * but WITHOUT ANY WARRANTY; without even the implied warranty of
12  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13  * Lesser General Public License for more details.
14  *
15  * You should have received a copy of the GNU Lesser General Public
16  * License along with this program; if not, write to the Free Software
17  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307.
18  * You can also get it at http://www.gnu.org/licenses/lgpl.html
19  *
20  * For more information on this software, see http://www.xquark.org.
21  */

22
23 package org.xquark.extractor.metadata;
24
25 import java.io.*;
26 import java.io.InputStream JavaDoc;
27 import java.io.Reader JavaDoc;
28 import java.math.BigDecimal JavaDoc;
29 import java.sql.ResultSet JavaDoc;
30 import java.sql.SQLException JavaDoc;
31 import java.sql.Timestamp JavaDoc;
32 import java.text.ParseException JavaDoc;
33
34 import org.xquark.extractor.common.MetaDataException;
35 import org.xquark.jdbc.typing.*;
36 import org.xquark.schema.SchemaException;
37 import org.xquark.schema.SimpleType;
38 import org.xquark.schema.datatypes.*;
39 import org.xquark.schema.datatypes.URI.MalformedURIException;
40 import org.xquark.schema.validation.ValidationContextProvider;
41 import org.xquark.xquery.parser.XQueryException;
42 import org.xquark.xquery.typing.QAtomicSerializer;
43
44 /**
45  * Processes XML/SQL mapping issues (type checking, JDBC interface, mapping...)
46  * for extractor.
47  *
48  * NOTE: At the present time there is no particular reason with the metadata
49  * and the reconstruction should use the same class except for future use of flags
50  * or if the junction between the reconstruction an metadata could be done.
51  */

52 public class ExtractorMappingInfo extends MappingInfo
53 {
54     private static int BUF_SIZE = 256;
55     
56     private boolean isBuiltInXMLType = true;
57     private ColumnMetaData columnMetaData = null;
58     
59     /** Whether this column must be retrieved using JDBC getString */
60     private boolean useGetString = false;
61
62     
63     /**
64      * Used at the present time, by GenAlgebraVisitor for temporary table.
65      * @param cmeta
66      * @throws MetaDataException
67      */

68     public ExtractorMappingInfo(DbType cmeta, TypeMap typeMap)
69     throws MetaDataException
70     {
71         setXMLType(generateSimpleType(cmeta));
72         setDBType(cmeta);
73         useGetString = typeMap.useGetString(dbType.getJDBCType());
74     }
75
76     /**
77      * Used at the present time, by metadata for constructing an XML type basing
78      * on SQL type and set some flags (not used yet)
79      * @param cmeta
80      * @throws MetaDataException
81      */

82     public ExtractorMappingInfo(ColumnMetaData cmeta, TypeMap typeMap)
83     throws MetaDataException
84     {
85         this(cmeta.getType(), typeMap);
86         setColumnMetaData(cmeta);
87     }
88     
89     /**
90      * This constructor is to be used only at reconstruction time when no simple
91      * type string generation and MappingInfo flags are needed. At reconstruction
92      * time, no reliable DBType is available. This should be corrected if flags
93      * like @link MappingInfo#useStreams were needed.
94      * (see @link org.xquark.extractor.algebra.GenAlgebraVisitor)
95      * @param XMLType
96      */

97     public ExtractorMappingInfo(SimpleType XMLType, TypeMap typeMap)
98     {
99         super(XMLType);
100         useGetString = typeMap.useGetString(
101                 ABSTRACT_SCHEMA_JDBC_MAPPING[sType.getPrimitive().getType()]);
102     }
103     
104     /**
105      * Performed on demand, if data is fetched from database.
106      */

107     public void checkForExtraction() throws XQueryException {
108         if (columnMetaData != null && !columnMetaData.getSqlType().isExtraction())
109             throw new XQueryException("Extraction is not supported for the " + columnMetaData.getTypeName() + " data type.");
110     }
111
112     private String JavaDoc generateSimpleType(DbType dbType)
113     throws MetaDataException
114     {
115         StringBuffer JavaDoc buffer = new StringBuffer JavaDoc();
116         isBuiltInXMLType = true;
117         switch (dbType.getJDBCType()) {
118             case java.sql.Types.ARRAY :
119                 throw new MetaDataException("The JDBC ARRAY type is not currently supported for extraction.");
120             case java.sql.Types.BIGINT :
121                 buffer.append("long");
122                 break;
123             case java.sql.Types.BINARY :
124                 isBuiltInXMLType = false;
125                 buffer.append("<simpleType><restriction base=\"base64Binary\"><length value=\"");
126                 buffer.append(dbType.getLength());
127                 buffer.append("\"/></restriction></simpleType>");
128                 break;
129             case java.sql.Types.BIT : case DbType.BOOLEAN :
130                 buffer.append("boolean");
131                 break;
132             case java.sql.Types.CHAR :
133                 isBuiltInXMLType = false;
134                 buffer.append("<simpleType><restriction base=\"string\"><length value=\"");
135                 buffer.append(dbType.getLength());
136                 buffer.append("\"/></restriction></simpleType>");
137                 break;
138             case java.sql.Types.DATE :
139                 buffer.append("date");
140                 break;
141             case java.sql.Types.DECIMAL : case java.sql.Types.NUMERIC :
142                 isBuiltInXMLType = false;
143                 buffer.append("<simpleType><restriction base=\"decimal\"><totalDigits value=\"");
144                 buffer.append(dbType.getLength());
145                 buffer.append("\"/><fractionDigits value=\"");
146                 buffer.append(dbType.getScale());
147                 buffer.append("\"/></restriction></simpleType>");
148                 break;
149             case java.sql.Types.DISTINCT :
150                 throw new MetaDataException("The JDBC CLOB type is not currently supported for extraction.");
151             case java.sql.Types.DOUBLE : case java.sql.Types.FLOAT :
152                 buffer.append("double");
153                 break;
154             case DbType.ORACLE_ROWID:
155                 buffer.append("string");
156                 break;
157             case java.sql.Types.INTEGER :
158                 buffer.append("integer");
159                 break;
160             case java.sql.Types.JAVA_OBJECT :
161                 throw new MetaDataException("The JDBC JAVA_OBJECT type is not currently supported for extraction.");
162             case java.sql.Types.NULL :
163                 throw new MetaDataException("The JDBC NULL type is not currently supported for extraction.");
164             case java.sql.Types.OTHER :
165                 throw new MetaDataException("The JDBC OTHER type is not currently supported for extraction.");
166             case java.sql.Types.REAL :
167                 buffer.append("float");
168                 break;
169             case java.sql.Types.REF :
170                 throw new MetaDataException("The JDBC REF type is not currently supported for extraction.");
171             case java.sql.Types.SMALLINT :
172                 buffer.append("short");
173                 break;
174             case java.sql.Types.STRUCT :
175                 throw new MetaDataException("The JDBC STRUCT type is not currently supported for extraction.");
176             case java.sql.Types.TIME :
177                 buffer.append("time");
178                 break;
179             case java.sql.Types.TIMESTAMP :
180                 buffer.append("dateTime");
181                 break;
182             case java.sql.Types.TINYINT :
183                 buffer.append("byte");
184                 break;
185             case java.sql.Types.BLOB :
186             case java.sql.Types.LONGVARBINARY : case java.sql.Types.VARBINARY :
187                 isBuiltInXMLType = false;
188                 buffer.append("<simpleType><restriction base=\"base64Binary\"><maxLength value=\"");
189                 buffer.append(dbType.getLength());
190                 buffer.append("\"/></restriction></simpleType>");
191                 break;
192             case java.sql.Types.CLOB :
193             case java.sql.Types.LONGVARCHAR : case java.sql.Types.VARCHAR :
194                 isBuiltInXMLType = false;
195                 buffer.append("<simpleType><restriction base=\"string\"><maxLength value=\"");
196                 buffer.append(dbType.getLength());
197                 buffer.append("\"/></restriction></simpleType>");
198                 break;
199         }
200         return buffer.toString();
201     }
202     
203     public boolean isBuiltInXMLType() {
204         return isBuiltInXMLType;
205     }
206
207     public String JavaDoc getParameter(ResultSet JavaDoc rs, int i, QAtomicSerializer qSerializer, ValidationContextProvider nsContext) throws XQueryException {
208         String JavaDoc value = null;
209         try {
210             if (useGetString) {
211                 try {
212                     // Try a getString + convert/toXMLString if JDBC cannot provide a java type compatible with schema
213
value = rs.getString(i);
214                     if (value == null)
215                         return null;
216                     switch(javaType) {
217                         // perf shortcut for numbers
218
case JAVA_FLOAT : case JAVA_DOUBLE :
219                         case JAVA_LONG : case JAVA_BIG_DECIMAL :
220                             return qSerializer.removeNotSignificantDigits(value);
221
222                         case JAVA_STRING :
223                             return qSerializer.serialize(sType, value);
224                         case SCHEMA_QNAME :
225                             return qSerializer.serialize(new QName(value));
226                         case SCHEMA_URI :
227                             return qSerializer.serialize(new URI(value));
228                         case SCHEMA_DATETIME :
229                             return qSerializer.serialize(sType, (DateTime)sType.convert(value, true, nsContext));
230                         case SCHEMA_DURATION :
231                             return qSerializer.serialize(sType, new Duration(value));
232                         case JAVA_BOOLEAN :
233                             return qSerializer.serialize(sType, (Boolean JavaDoc)sType.convert(value, true, nsContext));
234                         case SCHEMA_BYTE_ARRAY :
235                             return qSerializer.serialize(sType, (ByteArray)sType.convert(value, true, nsContext));
236                         default:
237                             return null;
238                     }
239                 }
240                 catch (SchemaException e1) {
241                     throw new XQueryException("Schema exception raised when converting \""
242                             + value + "\" database value to XML. Please check underlying exception.", e1);
243                 }
244                 catch (SQLException JavaDoc e1) {
245                     throw new XQueryException("JDBC exception raised when retrieving data from resultset using backup getString() method. Please check underlying exception.", e1);
246                 }
247             }
248             else {
249                 switch(javaType) {
250                     case JAVA_STRING :
251                         if (useStreams){
252                             Reader JavaDoc reader = rs.getCharacterStream(i);
253                             char[] cb = new char[BUF_SIZE];
254                             CharArrayWriter caw = new CharArrayWriter();
255                             int len = -1;
256                             try {
257                                 while ((len = reader.read(cb)) > 0)
258                                     caw.write(cb, 0, len);
259                             } catch (IOException e1) {
260                                 throw new XQueryException(
261                                         "IOexception raised when retrieving data from resultset using backup getCharacterStream() method. Please check underlying exception.",
262                                         e1);
263                             }
264                             if (caw.size() == 0 && rs.wasNull())
265                                 value = null;
266                             else
267                                 value = caw.toString();
268                         }
269                         else
270                             value = rs.getString(i);
271                         if (value == null)
272                             return null;
273                         return qSerializer.serialize(sType, value);
274                     case SCHEMA_QNAME :
275                         value = rs.getString(i);
276                         if (value == null)
277                             return null;
278                         return qSerializer.serialize(new QName(value));
279                     case SCHEMA_URI :
280                         value = rs.getString(i);
281                         if (value == null)
282                             return null;
283                         return qSerializer.serialize(new URI(value));
284                     case SCHEMA_DATETIME :
285                         Timestamp JavaDoc ts = rs.getTimestamp(i);
286                         if (ts == null)
287                             return null;
288                         return qSerializer.serialize(sType, new DateTime(ts.getTime()));
289                     case SCHEMA_DURATION :
290                         value = rs.getString(i);
291                         if (value == null)
292                             return null;
293                         return qSerializer.serialize(sType, new Duration(value));
294                     case JAVA_LONG :
295                         long l = rs.getLong(i);
296                         if (rs.wasNull())
297                             return null;
298                         return qSerializer.serialize(new Long JavaDoc(l));
299                     case JAVA_BIG_DECIMAL :
300                         BigDecimal JavaDoc bd = rs.getBigDecimal(i);
301                         if (bd == null)
302                             return null;
303                         return qSerializer.serialize(bd);
304                     case JAVA_FLOAT :
305                         float f = rs.getFloat(i);
306                         if (rs.wasNull())
307                             return null;
308                         return qSerializer.serialize(new Float JavaDoc(f));
309                     case JAVA_DOUBLE :
310                         double d = rs.getDouble(i);
311                         if (rs.wasNull())
312                             return null;
313                         return qSerializer.serialize(new Double JavaDoc(d));
314                     case JAVA_BOOLEAN :
315                         boolean b = rs.getBoolean(i);
316                         if (rs.wasNull())
317                             return null;
318                         return qSerializer.serialize(sType, new Boolean JavaDoc(b));
319                     case SCHEMA_BYTE_ARRAY :
320                         byte[] ba = null;
321                         if (useStreams){
322                             InputStream JavaDoc is = rs.getBinaryStream(i);
323                             ba = new byte[BUF_SIZE];
324                             ByteArrayOutputStream baos = new ByteArrayOutputStream();
325                             int len = -1;
326                             try {
327                                 while ((len = is.read(ba)) > 0)
328                                     baos.write(ba, 0, len);
329                             } catch (IOException e1) {
330                                 throw new XQueryException(
331                                         "IOexception raised when retrieving data from resultset using backup getCharacterStream() method. Please check underlying exception.",
332                                         e1);
333                             }
334                             if (baos.size() == 0 && rs.wasNull())
335                                 ba = null;
336                             else
337                                 ba = baos.toByteArray();
338                         }
339                         else
340                             ba = rs.getBytes(i);
341                         if (ba == null)
342                             return null;
343                         return qSerializer.serialize(sType, ba);
344                     default:
345                         return null;
346                 }
347             }
348         }
349         catch (SQLException JavaDoc e) {
350             try {
351                 // Try a getString + convert/toXMLString if JDBC cannot provide a java type compatible with schema
352
// For instance MySQL does not support getTimeStamp on a literal since no TO_DATE exist
353
// TODO: try to detect there is no column to avoid catching exception
354
value = rs.getString(i);
355                 return sType.toXMLString(sType.convert(value, true, nsContext), nsContext);
356             }
357             catch (SQLException JavaDoc e1) {
358                 throw new XQueryException("JDBC exception raised when retrieving data from resultset using backup getString() method. Please check underlying exception.", e1);
359             }
360             catch (SchemaException e1) {
361                 throw new XQueryException("Schema exception raised when converting \""
362                         + value + "\" database value to XML. Please check underlying exception.", e1);
363             }
364         }
365         catch (MalformedURIException e) {
366             throw new XQueryException("Data retrieved from resultset is not an URI. Please check underlying exception.", e);
367         }
368         catch (ParseException JavaDoc e) {
369             throw new XQueryException("Data retrieved from resultset is not a Duration. Please check underlying exception.", e);
370         }
371     }
372     
373     public ColumnMetaData getColumnMetaData() {
374         return columnMetaData;
375     }
376
377     public void setColumnMetaData(ColumnMetaData columnMetaData) {
378         this.columnMetaData = columnMetaData;
379     }
380 }
381
Popular Tags