View Javadoc

1   /***
2    * Redistribution and use of this software and associated documentation
3    * ("Software"), with or without modification, are permitted provided
4    * that the following conditions are met:
5    *
6    * 1. Redistributions of source code must retain copyright
7    *    statements and notices.  Redistributions must also contain a
8    *    copy of this document.
9    *
10   * 2. Redistributions in binary form must reproduce the
11   *    above copyright notice, this list of conditions and the
12   *    following disclaimer in the documentation and/or other
13   *    materials provided with the distribution.
14   *
15   * 3. The name "Exolab" must not be used to endorse or promote
16   *    products derived from this Software without prior written
17   *    permission of Exoffice Technologies.  For written permission,
18   *    please contact info@exolab.org.
19   *
20   * 4. Products derived from this Software may not be called "Exolab"
21   *    nor may "Exolab" appear in their names without prior written
22   *    permission of Exoffice Technologies. Exolab is a registered
23   *    trademark of Exoffice Technologies.
24   *
25   * 5. Due credit should be given to the Exolab Project
26   *    (http://www.exolab.org/).
27   *
28   * THIS SOFTWARE IS PROVIDED BY EXOFFICE TECHNOLOGIES AND CONTRIBUTORS
29   * ``AS IS'' AND ANY EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT
30   * NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
31   * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL
32   * EXOFFICE TECHNOLOGIES OR ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
33   * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
34   * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
35   * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
36   * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
37   * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
38   * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
39   * OF THE POSSIBILITY OF SUCH DAMAGE.
40   *
41   * Copyright 2001-2003 (C) Exoffice Technologies Inc. All Rights Reserved.
42   *
43   * $Id: TypeSet.java,v 1.1 2004/11/26 01:51:16 tanderson Exp $
44   */
45  
46  package org.exolab.jms.tools.db;
47  
48  import java.sql.Connection;
49  import java.sql.ResultSet;
50  import java.sql.SQLException;
51  import java.util.ArrayList;
52  import java.util.HashMap;
53  import java.util.Iterator;
54  
55  import org.apache.commons.logging.Log;
56  import org.apache.commons.logging.LogFactory;
57  
58  import org.exolab.jms.persistence.PersistenceException;
59  import org.exolab.jms.persistence.SQLHelper;
60  
61  
62  /***
63   * A helper class for managing the set of types supported by an RDBMS
64   *
65   * @version     $Revision: 1.1 $ $Date: 2004/11/26 01:51:16 $
66   * @author      <a href="mailto:tima@intalio.com">Tim Anderson</a>
67   */
68  class TypeSet {
69  
70      /***
71       * A map of type identifiers to an ArrayList of corresponding RDBMS types
72       */
73      private HashMap _types = new HashMap();
74  
75      /***
76       * The logger
77       */
78      private static final Log _log = LogFactory.getLog(TypeSet.class);
79  
80  
81      /***
82       * Construct a new instance
83       *
84       * @param connection the database connection to obtain meta-data from
85       * @throws PersistenceException if meta-data cannot be accessed
86       */
87      public TypeSet(Connection connection) throws PersistenceException {
88          ResultSet set = null;
89          try {
90              set = connection.getMetaData().getTypeInfo();
91              while (set.next()) {
92                  int type = set.getInt("DATA_TYPE");
93                  String name = set.getString("TYPE_NAME");
94                  long precision = set.getLong("PRECISION");
95                  String createParams = set.getString("CREATE_PARAMS");
96  
97                  Descriptor descriptor = Descriptor.getDescriptor(type);
98                  if (descriptor != null) {
99                      addType(type, name, precision, createParams);
100                 } else {
101                     _log.debug(
102                         "TypeSet: skipping unknown type, type id=" + type
103                         + ", name=" + name + ", precision=" + precision
104                         + ", create params=" + createParams);
105                 }
106             }
107         } catch (SQLException exception) {
108             throw new PersistenceException(
109                 "Failed to get type meta-data", exception);
110         } finally {
111             SQLHelper.close(set);
112         }
113     }
114 
115     /***
116      * Return the closest type matching the requested type id and precision
117      *
118      * @param type the type identifier
119      * @param precision the requested precision
120      * @return the closest matching type, or null if none exists
121      */
122     public Type getType(int type, long precision) {
123         Type result = null;
124         ArrayList types = (ArrayList) _types.get(new Integer(type));
125         if (types != null) {
126             Iterator iter = types.iterator();
127             while (iter.hasNext()) {
128                 Type option = (Type) iter.next();
129                 if (precision == -1 && (option.getPrecision() != -1 &&
130                     option.getParameters())) {
131                     // no precision was requested, but the type requires
132                     // parameters
133                     result = new Type(type, option.getName(),
134                         option.getPrecision(),
135                         option.getParameters());
136                     break;
137                 } else if (precision <= option.getPrecision()) {
138                     // use the requested precision
139                     result = new Type(type, option.getName(), precision,
140                         option.getParameters());
141                     break;
142                 } else {
143                     _log.debug("TypeSet: requested type=" + type
144                         + " exceeds precision for supported " + option);
145                 }
146             }
147         } else {
148             _log.debug("TypeSet: no types matching type id=" + type
149                 + ", type=" + Descriptor.getDescriptor(type).getName());
150         }
151         return result;
152     }
153 
154     /***
155      * Return the near type matching the supplied type id and precision.
156      * This should only be invoked if the requested precision exceeds that
157      * supported by the database.
158      *
159      * @param type the type identifier
160      * @return the type, or null, if none exists
161      */
162     public Type getNearestType(int type, long precision) {
163         Type result = null;
164         ArrayList types = (ArrayList) _types.get(new Integer(type));
165         if (types != null) {
166             Iterator iter = types.iterator();
167             Type nearest = null;
168             while (iter.hasNext()) {
169                 Type option = (Type) iter.next();
170                 if (precision <= option.getPrecision()) {
171                     // use the requested precision
172                     result = new Type(type, option.getName(), precision,
173                         option.getParameters());
174                     break;
175                 } else {
176                     nearest = option;
177                 }
178             }
179             if (result == null && nearest != null) {
180                 // use the closest precision
181                 result = new Type(type, nearest.getName(),
182                     nearest.getPrecision(),
183                     nearest.getParameters());
184                 _log.warn(
185                     "TypeSet: requested type=" + type + ", precision="
186                     + precision + " exceeds precision supported by database. "
187                     + "Falling back to " + nearest);
188             }
189         } else {
190             _log.debug("TypeSet: no types matching type id=" + type
191                 + ", type=" + Descriptor.getDescriptor(type).getName());
192         }
193         return result;
194     }
195 
196     /***
197      * Returns true if the type is supported
198      *
199      * @param type the type identifier
200      * @return <code>true</code> if the type is supported
201      */
202     public boolean exists(int type) {
203         return _types.containsKey(new Integer(type));
204     }
205 
206 
207     private void addType(int type, String name, long precision,
208                          String createParams) {
209         Descriptor descriptor = Descriptor.getDescriptor(type);
210         boolean parameters = false;
211         if (createParams != null && createParams.trim().length() != 0) {
212             parameters = true;
213         }
214 
215         Integer key = new Integer(type);
216         ArrayList types = (ArrayList) _types.get(key);
217         if (types == null) {
218             types = new ArrayList();
219             _types.put(key, types);
220         }
221 
222         _log.debug("TypeSet: type id=" + type
223             + ", type=" + descriptor.getName()
224             + ", name=" + name
225             + ", precision=" + precision
226             + ", createParams=" + createParams);
227         types.add(new Type(type, name, precision, parameters));
228     }
229 
230 } //-- TypeSet