View Javadoc

1   /*
2    * Copyright 2002,2004 The Apache Software Foundation.
3    *
4    * Licensed under the Apache License, Version 2.0 (the "License");
5    * you may not use this file except in compliance with the License.
6    * You may obtain a copy of the License at
7    *
8    *      http://www.apache.org/licenses/LICENSE-2.0
9    *
10   * Unless required by applicable law or agreed to in writing, software
11   * distributed under the License is distributed on an "AS IS" BASIS,
12   * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13   * See the License for the specific language governing permissions and
14   * limitations under the License.
15   */
16  
17  package javax.servlet.jsp.jstl.sql;
18  
19  import java.sql.*;
20  import java.util.*;
21  
22  /***
23   * <p>This class creates a cached version of a <tt>ResultSet</tt>.
24   * It's represented as a <tt>Result</tt> implementation, capable of
25   * returing an array of <tt>Row</tt> objects containing a <tt>Column</tt>
26   * instance for each column in the row.   It is not part of the JSTL
27   * API; it serves merely as a back-end to ResultSupport's static methods.
28   * Thus, we scope its access to the package.
29   *
30   * @author Hans Bergsten
31   * @author Justyna Horwat
32   */
33  
34  class ResultImpl implements Result {
35      private List rowMap;
36      private List rowByIndex;
37      private String[] columnNames;
38      private boolean isLimited;
39  
40      /***
41       * This constructor reads the ResultSet and saves a cached
42       * copy.
43       *
44       * @param rs an open <tt>ResultSet</tt>, positioned before the first
45       * row
46       * @param startRow, beginning row to be cached
47       * @param maxRows, query maximum rows limit
48       * @exception if a database error occurs
49       */
50      public ResultImpl(ResultSet rs, int startRow, int maxRows)
51          throws SQLException
52      {
53          rowMap = new ArrayList();
54          rowByIndex = new ArrayList();
55  
56          ResultSetMetaData rsmd = rs.getMetaData();
57          int noOfColumns = rsmd.getColumnCount();
58  
59          // Create the column name array
60          columnNames = new String[noOfColumns];
61          for (int i = 1; i <= noOfColumns; i++) {
62              columnNames[i-1] = rsmd.getColumnName(i);
63          }
64  
65          // Throw away all rows upto startRow
66          for (int i = 0; i < startRow; i++) {
67              rs.next();
68          }
69  
70          // Process the remaining rows upto maxRows
71          int processedRows = 0;
72          while (rs.next()) {
73              if ((maxRows != -1) && (processedRows == maxRows)) {
74                  isLimited = true;
75                  break;
76              }
77              Object[] columns = new Object[noOfColumns];
78              SortedMap columnMap =
79                  new TreeMap(String.CASE_INSENSITIVE_ORDER);
80  
81              // JDBC uses 1 as the lowest index!
82              for (int i = 1; i <= noOfColumns; i++) {
83                  Object value =  rs.getObject(i);
84                  if (rs.wasNull()) {
85                      value = null;
86                  }
87                  columns[i-1] = value;
88                  columnMap.put(columnNames[i-1], value);
89              }
90              rowMap.add(columnMap);
91              rowByIndex.add(columns);
92              processedRows++;
93          }
94      }
95  
96      /***
97       * Returns an array of SortedMap objects. The SortedMap
98       * object key is the ColumnName and the value is the ColumnValue.
99       * SortedMap was created using the CASE_INSENSITIVE_ORDER
100      * Comparator so the key is the case insensitive representation
101      * of the ColumnName.
102      *
103      * @return an array of Map, or null if there are no rows
104      */
105     public SortedMap[] getRows() {
106         if (rowMap == null) {
107             return null;
108         }
109 
110         //should just be able to return SortedMap[] object
111         return (SortedMap []) rowMap.toArray(new SortedMap[0]);
112     }
113 
114 
115     /***
116      * Returns an array of Object[] objects. The first index
117      * designates the Row, the second the Column. The array
118      * stores the value at the specified row and column.
119      *
120      * @return an array of Object[], or null if there are no rows
121      */
122     public Object[][] getRowsByIndex() {
123         if (rowByIndex == null) {
124             return null;
125         }
126 
127         //should just be able to return Object[][] object
128         return (Object [][])rowByIndex.toArray(new Object[0][0]);
129     }
130 
131     /***
132      * Returns an array of String objects. The array represents
133      * the names of the columns arranged in the same order as in
134      * the getRowsByIndex() method.
135      *
136      * @return an array of String[]
137      */
138     public String[] getColumnNames() {
139         return columnNames;
140     }
141 
142     /***
143      * Returns the number of rows in the cached ResultSet
144      *
145      * @return the number of cached rows, or -1 if the Result could
146      *    not be initialized due to SQLExceptions
147      */
148     public int getRowCount() {
149         if (rowMap == null) {
150             return -1;
151         }
152         return rowMap.size();
153     }
154 
155     /***
156      * Returns true of the query was limited by a maximum row setting
157      *
158      * @return true if the query was limited by a MaxRows attribute
159      */
160     public boolean isLimitedByMaxRows() {
161         return isLimited;
162     }
163 
164 }