View Javadoc

1   /*
2    * $Header: /cvsroot/valuelist/valuelist/src/java/net/mlw/vlh/adapter/jdbc/dynabean/fix/ResultSetDynaClass.java,v 1.3 2005/08/19 16:06:29 smarek Exp $
3    * $Revision: 1.3 $
4    * $Date: 2005/08/19 16:06:29 $
5    *
6    * ====================================================================
7    * 
8    * The Apache Software License, Version 1.1
9    *
10   * Copyright (c) 2001-2003 The Apache Software Foundation.  All rights
11   * reserved.
12   *
13   * Redistribution and use in source and binary forms, with or without
14   * modification, are permitted provided that the following conditions
15   * are met:
16   *
17   * 1. Redistributions of source code must retain the above copyright
18   *    notice, this list of conditions and the following disclaimer. 
19   *
20   * 2. Redistributions in binary form must reproduce the above copyright
21   *    notice, this list of conditions and the following disclaimer in
22   *    the documentation and/or other materials provided with the
23   *    distribution.
24   *
25   * 3. The end-user documentation included with the redistribution,
26   *    if any, must include the following acknowledgement:  
27   *       "This product includes software developed by the 
28   *        Apache Software Foundation (http://www.apache.org/)."
29   *    Alternately, this acknowledgement may appear in the software itself,
30   *    if and wherever such third-party acknowledgements normally appear.
31   *
32   * 4. The names "Apache", "The Jakarta Project", "Commons", and "Apache Software
33   *    Foundation" must not be used to endorse or promote products derived
34   *    from this software without prior written permission. For written 
35   *    permission, please contact apache@apache.org.
36   *
37   * 5. Products derived from this software may not be called "Apache",
38   *    "Apache" nor may "Apache" appear in their names without prior 
39   *    written permission of the Apache Software Foundation.
40   *
41   * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
42   * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
43   * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
44   * DISCLAIMED.  IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR
45   * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
46   * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
47   * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
48   * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
49   * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
50   * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
51   * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
52   * SUCH DAMAGE.
53   * ====================================================================
54   *
55   * This software consists of voluntary contributions made by many
56   * individuals on behalf of the Apache Software Foundation.  For more
57   * information on the Apache Software Foundation, please see
58   * <http://www.apache.org/>.
59   *
60   */
61  
62  
63  package net.mlw.vlh.adapter.jdbc.dynabean.fix;
64  
65  
66  import java.sql.ResultSet;
67  import java.sql.SQLException;
68  import java.util.HashMap;
69  import java.util.Iterator;
70  import java.util.Map;
71  
72  import org.apache.commons.beanutils.DynaBean;
73  import org.apache.commons.beanutils.DynaClass;
74  import org.apache.commons.beanutils.DynaProperty;
75  
76  
77  /***
78   * <p>Implementation of <code>DynaClass</code> for DynaBeans that wrap the
79   * <code>java.sql.Row</code> objects of a <code>java.sql.ResultSet</code>.
80   * The normal usage pattern is something like:</p>
81   * <pre>
82   *   ResultSet rs = ...;
83   *   ResultSetDynaClass rsdc = new ResultSetDynaClass(rs);
84   *   Iterator rows = rsdc.iterator();
85   *   while (rows.hasNext())  {
86   *     DynaBean row = (DynaBean) rows.next();
87   *     ... process this row ...
88   *   }
89   *   rs.close();
90   * </pre>
91   *
92   * <p>Each column in the result set will be represented as a DynaBean
93   * property of the corresponding name (optionally forced to lower case
94   * for portability).</p>
95   *
96   * <p><strong>WARNING</strong> - Any {@link DynaBean} instance returned by
97   * this class, or from the <code>Iterator</code> returned by the
98   * <code>iterator()</code> method, is directly linked to the row that the
99   * underlying result set is currently positioned at.  This has the following
100  * implications:</p>
101  * <ul>
102  * <li>Once you retrieve a different {@link DynaBean} instance, you should
103  *     no longer use any previous instance.</li>
104  * <li>Changing the position of the underlying result set will change the
105  *     data that the {@link DynaBean} references.</li>
106  * <li>Once the underlying result set is closed, the {@link DynaBean}
107  *     instance may no longer be used.</li>
108  * </ul>
109  *
110  * <p>Any database data that you wish to utilize outside the context of the
111  * current row of an open result set must be copied.  For example, you could
112  * use the following code to create standalone copies of the information in
113  * a result set:</p>
114  * <pre>
115  *   ArrayList results = new ArrayList(); // To hold copied list
116  *   ResultSetDynaClass rsdc = ...;
117  *   DynaProperty properties[] = rsdc.getDynaProperties();
118  *   BasicDynaClass bdc =
119  *     new BasicDynaClass("foo", BasicDynaBean.class,
120  *                        rsdc.getDynaProperties());
121  *   Iterator rows = rsdc.iterator();
122  *   while (rows.hasNext()) {
123  *     DynaBean oldRow = (DynaBean) rows.next();
124  *     DynaBean newRow = bdc.newInstance();
125  *     PropertyUtils.copyProperties(newRow, oldRow);
126  *     results.add(newRow);
127  *   }
128  * </pre>
129  *
130  * @author Craig R. McClanahan
131  * @version $Revision: 1.3 $ $Date: 2005/08/19 16:06:29 $
132  */
133 
134 public class ResultSetDynaClass extends JDBCDynaClass implements DynaClass {
135 
136 
137     // ----------------------------------------------------------- Constructors
138 
139 
140     /***
141      * <p>Construct a new ResultSetDynaClass for the specified
142      * <code>ResultSet</code>.  The property names corresponding
143      * to column names in the result set will be lower cased.</p>
144      *
145      * @param resultSet The result set to be wrapped
146      *
147      * @exception NullPointerException if <code>resultSet</code>
148      *  is <code>null</code>
149      * @exception SQLException if the metadata for this result set
150      *  cannot be introspected
151      */
152     public ResultSetDynaClass(ResultSet resultSet) throws SQLException {
153 
154         this(resultSet, true, false);
155 
156     }
157 
158 
159     /***
160      * <p>Construct a new ResultSetDynaClass for the specified
161      * <code>ResultSet</code>.  The property names corresponding
162      * to the column names in the result set will be lower cased or not,
163      * depending on the specified <code>lowerCase</code> value.</p>
164      *
165      * <p><strong>WARNING</strong> - If you specify <code>false</code>
166      * for <code>lowerCase</code>, the returned property names will
167      * exactly match the column names returned by your JDBC driver.
168      * Because different drivers might return column names in different
169      * cases, the property names seen by your application will vary
170      * depending on which JDBC driver you are using.</p>
171      *
172      * @param resultSet The result set to be wrapped
173      * @param lowerCase Should property names be lower cased?
174      * @param useName   Should property names b ethe column name of the
175      *                  label name?
176      * @exception NullPointerException if <code>resultSet</code>
177      *  is <code>null</code>
178      * @exception SQLException if the metadata for this result set
179      *  cannot be introspected
180      */
181     public ResultSetDynaClass(ResultSet resultSet, boolean lowerCase, boolean useName)
182         throws SQLException {
183 
184         if (resultSet == null) {
185             throw new NullPointerException();
186         }
187         this.resultSet = resultSet;
188         this.lowerCase = lowerCase;
189         this.useName = useName;
190         introspect(resultSet);
191 
192     }
193 
194 
195     // ----------------------------------------------------- Instance Variables
196 
197 
198     /***
199      * Flag defining whether column names should be lower cased when
200      * converted to property names.
201      */
202     protected boolean lowerCase = true;
203 
204 
205     /***
206      * The set of dynamic properties that are part of this DynaClass.
207      */
208     protected DynaProperty properties[] = null;
209 
210 
211     /***
212      * The set of dynamic properties that are part of this DynaClass,
213      * keyed by the property name.  Individual descriptor instances will
214      * be the same instances as those in the <code>properties</code> list.
215      */
216     protected Map propertiesMap = new HashMap();
217 
218 
219     /***
220      * <p>The <code>ResultSet</code> we are wrapping.</p>
221      */
222     protected ResultSet resultSet = null;
223 
224 
225     // --------------------------------------------------------- Public Methods
226 
227 
228     /***
229      * <p>Return an <code>Iterator</code> of {@link DynaBean} instances for
230      * each row of the wrapped <code>ResultSet</code>, in "forward" order.
231      * Unless the underlying result set supports scrolling, this method
232      * should be called only once.</p>
233      */
234     public Iterator iterator() {
235 
236         return (new ResultSetIterator(this));
237 
238     }
239 
240 
241     // -------------------------------------------------------- Package Methods
242 
243 
244     /***
245      * <p>Return the result set we are wrapping.</p>
246      */
247     ResultSet getResultSet() {
248 
249         return (this.resultSet);
250 
251     }
252 
253 
254     // ------------------------------------------------------ Protected Methods
255     
256     /***
257      * <p>Loads the class of the given name which by default uses the class loader used 
258      * to load this library.
259      * Dervations of this class could implement alternative class loading policies such as
260      * using custom ClassLoader or using the Threads's context class loader etc.
261      * </p>
262      */        
263     protected Class loadClass(String className) throws SQLException {
264 
265         try {
266             return getClass().getClassLoader().loadClass(className);
267         } 
268         catch (Exception e) {
269             throw new SQLException("Cannot load column class '" +
270                                    className + "': " + e);
271         }
272     }
273 }