1 /*
2 * The Apache Software License, Version 1.1
3 *
4 * Copyright (c) 1999 The Apache Software Foundation. All rights
5 * reserved.
6 *
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions
9 * are met:
10 *
11 * 1. Redistributions of source code must retain the above copyright
12 * notice, this list of conditions and the following disclaimer.
13 *
14 * 2. Redistributions in binary form must reproduce the above copyright
15 * notice, this list of conditions and the following disclaimer in
16 * the documentation and/or other materials provided with the
17 * distribution.
18 *
19 * 3. The end-user documentation included with the redistribution, if
20 * any, must include the following acknowlegement:
21 * "This product includes software developed by the
22 * Apache Software Foundation (http://www.apache.org/)."
23 * Alternately, this acknowlegement may appear in the software itself,
24 * if and wherever such third-party acknowlegements normally appear.
25 *
26 * 4. The names "The Jakarta Project", "Tomcat", and "Apache Software
27 * Foundation" must not be used to endorse or promote products derived
28 * from this software without prior written permission. For written
29 * permission, please contact apache@apache.org.
30 *
31 * 5. Products derived from this software may not be called "Apache"
32 * nor may "Apache" appear in their names without prior written
33 * permission of the Apache Group.
34 *
35 * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
36 * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
37 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
38 * DISCLAIMED. IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR
39 * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
40 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
41 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
42 * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
43 * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
44 * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
45 * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
46 * SUCH DAMAGE.
47 * ====================================================================
48 *
49 * This software consists of voluntary contributions made by many
50 * individuals on behalf of the Apache Software Foundation. For more
51 * information on the Apache Software Foundation, please see
52 * <http://www.apache.org/>.
53 *
54 */
55
56 package org.apache.commons.jelly.tags.sql;
57
58 import java.sql.*;
59 import java.util.*;
60 import javax.servlet.jsp.jstl.sql.Result;
61
62 /***
63 * <p>This class creates a cached version of a <tt>ResultSet</tt>.
64 * It's represented as a <tt>Result</tt> implementation, capable of
65 * returing an array of <tt>Row</tt> objects containing a <tt>Column</tt>
66 * instance for each column in the row.</p>
67 *
68 * <p>Note -- this is a private copy for the RI to avoid making the
69 * corresponding class in javax.servlet.* public.</p>
70 *
71 * @author Hans Bergsten
72 * @author Justyna Horwat
73 */
74
75 public class ResultImpl implements Result {
76 private List rowMap;
77 private List rowByIndex;
78 private String[] columnNames;
79 private boolean isLimited;
80
81 /***
82 * This constructor reads the ResultSet and saves a cached
83 * copy.
84 *
85 * @param rs an open <tt>ResultSet</tt>, positioned before the first
86 * row
87 * @param startRow, beginning row to be cached
88 * @param maxRows, query maximum rows limit
89 * @exception if a database error occurs
90 */
91 public ResultImpl(ResultSet rs, int startRow, int maxRows)
92 throws SQLException {
93
94 rowMap = new ArrayList();
95 rowByIndex = new ArrayList();
96
97 ResultSetMetaData rsmd = rs.getMetaData();
98 int noOfColumns = rsmd.getColumnCount();
99
100 // Create the column name array
101 columnNames = new String[noOfColumns];
102 for (int i = 1; i <= noOfColumns; i++) {
103 columnNames[i-1] = rsmd.getColumnName(i);
104 }
105
106 // Throw away all rows upto startRow
107 for (int i = 0; i < startRow; i++) {
108 rs.next();
109 }
110
111 // Process the remaining rows upto maxRows
112 int processedRows = 0;
113 while (rs.next()) {
114 if ((maxRows != -1) && (processedRows == maxRows)) {
115 isLimited = true;
116 break;
117 }
118 Object[] columns = new Object[noOfColumns];
119 SortedMap columnMap =
120 new TreeMap(String.CASE_INSENSITIVE_ORDER);
121
122 // JDBC uses 1 as the lowest index!
123 for (int i = 1; i <= noOfColumns; i++) {
124 Object value = rs.getObject(i);
125 if (rs.wasNull()) {
126 value = null;
127 }
128 columns[i-1] = value;
129 columnMap.put(columnNames[i-1], value);
130 }
131 rowMap.add(columnMap);
132 rowByIndex.add(columns);
133 processedRows++;
134 }
135 }
136
137 /***
138 * This constructor is given a List of Maps where each Map represents a Row of data.
139 * This constructor is typically used to create a Mock Object representing a result set.
140 *
141 * @param listOfMaps is a list of Maps where a Map represents a Row keyed by the column name
142 */
143 public ResultImpl(List listOfMaps) {
144
145 rowMap = new ArrayList();
146 rowByIndex = new ArrayList();
147 isLimited = false;
148
149 // lets build up a Set of all the unique column names
150 HashSet keySet = new HashSet();
151 for (Iterator iter = listOfMaps.iterator(); iter.hasNext(); ) {
152 Map row = (Map) iter.next();
153 keySet.addAll( row.keySet() );
154 }
155
156 // Create the column name array
157 int noOfColumns = keySet.size();
158 columnNames = new String[noOfColumns];
159 int i = 0;
160 for (Iterator iter = keySet.iterator(); iter.hasNext(); i++ ) {
161 columnNames[i] = (String) iter.next();
162 }
163
164 // Now add each row to the result set
165 for (Iterator iter = listOfMaps.iterator(); iter.hasNext(); ) {
166 Map row = (Map) iter.next();
167
168 Object[] columns = new Object[noOfColumns];
169 SortedMap columnMap =
170 new TreeMap(String.CASE_INSENSITIVE_ORDER);
171
172 for (i = 0; i < noOfColumns; i++) {
173 String columnName = columnNames[i];
174 Object value = row.get(columnName);
175 columns[i] = value;
176 columnMap.put(columnName, value);
177 }
178 rowMap.add(columnMap);
179 rowByIndex.add(columns);
180 }
181 }
182
183 /***
184 * Returns an array of SortedMap objects. The SortedMap
185 * object key is the ColumnName and the value is the ColumnValue.
186 * SortedMap was created using the CASE_INSENSITIVE_ORDER
187 * Comparator so the key is the case insensitive representation
188 * of the ColumnName.
189 *
190 * @return an array of Map, or null if there are no rows
191 */
192 public SortedMap[] getRows() {
193 if (rowMap == null) {
194 return null;
195 }
196
197 //should just be able to return SortedMap[] object
198 return (SortedMap []) rowMap.toArray(new SortedMap[0]);
199 }
200
201
202 /***
203 * Returns an array of Object[] objects. The first index
204 * designates the Row, the second the Column. The array
205 * stores the value at the specified row and column.
206 *
207 * @return an array of Object[], or null if there are no rows
208 */
209 public Object[][] getRowsByIndex() {
210 if (rowByIndex == null) {
211 return null;
212 }
213
214 //should just be able to return Object[][] object
215 return (Object [][])rowByIndex.toArray(new Object[0][0]);
216 }
217
218 /***
219 * Returns an array of String objects. The array represents
220 * the names of the columns arranged in the same order as in
221 * the getRowsByIndex() method.
222 *
223 * @return an array of String[]
224 */
225 public String[] getColumnNames() {
226 return columnNames;
227 }
228
229 /***
230 * Returns the number of rows in the cached ResultSet
231 *
232 * @return the number of cached rows, or -1 if the Result could
233 * not be initialized due to SQLExceptions
234 */
235 public int getRowCount() {
236 if (rowMap == null) {
237 return -1;
238 }
239 return rowMap.size();
240 }
241
242 /***
243 * Returns true of the query was limited by a maximum row setting
244 *
245 * @return true if the query was limited by a MaxRows attribute
246 */
247 public boolean isLimitedByMaxRows() {
248 return isLimited;
249 }
250
251 }
This page was automatically generated by Maven