001: /*
002: * Licensed to the Apache Software Foundation (ASF) under one or more
003: * contributor license agreements. See the NOTICE file distributed with
004: * this work for additional information regarding copyright ownership.
005: * The ASF licenses this file to You under the Apache License, Version 2.0
006: * (the "License"); you may not use this file except in compliance with
007: * the License. You may obtain a copy of the License at
008: *
009: * http://www.apache.org/licenses/LICENSE-2.0
010: *
011: * Unless required by applicable law or agreed to in writing, software
012: * distributed under the License is distributed on an "AS IS" BASIS,
013: * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
014: * See the License for the specific language governing permissions and
015: * limitations under the License.
016: *
017: * $Header:$
018: */
019: package org.apache.beehive.netui.util.iterator;
020:
021: import java.sql.ResultSet;
022: import java.sql.ResultSetMetaData;
023: import java.sql.SQLException;
024: import java.util.Iterator;
025: import java.util.NoSuchElementException;
026: import java.util.SortedMap;
027: import java.util.TreeMap;
028:
029: import org.apache.beehive.netui.util.Bundle;
030: import org.apache.beehive.netui.util.logging.Logger;
031:
032: /**
033: * <p>
034: * {@link Iterator} implementation for {@link ResultSet}.
035: * </p>
036: */
037: public class ResultSetIterator implements Iterator {
038:
039: private static final Logger LOGGER = Logger
040: .getInstance(ResultSetIterator.class);
041:
042: private boolean _primed = false;
043: private String[] _columnNames = null;
044: private ResultSet _rs = null;
045:
046: /**
047: * Create a ResultSetIterator for the <code>resultSet</code>.
048: *
049: * @param resultSet the ResultSet to iterate over
050: * @throws IllegalStateException when a {@link SQLException} occurs manipulating the ResultSet
051: */
052: public ResultSetIterator(ResultSet resultSet) {
053: if (resultSet == null)
054: return;
055:
056: _rs = resultSet;
057:
058: try {
059: // handle RSMD here to build a template map that can contain the data for each row
060: ResultSetMetaData rsmd = _rs.getMetaData();
061: assert rsmd != null;
062:
063: int cols = rsmd.getColumnCount();
064: _columnNames = new String[cols];
065: for (int i = 1; i <= cols; i++) {
066: _columnNames[i - 1] = rsmd.getColumnName(i);
067: LOGGER.trace("column[" + i + "]: "
068: + _columnNames[i - 1]);
069: }
070: } catch (SQLException sql) {
071: String msg = "An exception occurred reading ResultSetMetaData from a ResultSet. Cause: "
072: + sql;
073: LOGGER.error(msg, sql);
074: throw new IllegalStateException(msg, sql);
075: }
076: }
077:
078: /**
079: * Check for a subsequent item in the ResultSet.
080: *
081: * @return <code>true</code> if there is another element; <code>false</code> otherwise
082: * @throws IllegalStateException when a {@link SQLException} occurs advancing the ResultSet
083: */
084: public boolean hasNext() {
085: if (_rs == null)
086: return false;
087:
088: if (_primed)
089: return true;
090:
091: try {
092: _primed = _rs.next();
093: return _primed;
094: } catch (SQLException sql) {
095: String msg = "An exception occurred reading from the Iterator. Cause: "
096: + sql;
097: LOGGER.error(msg, sql);
098: throw new IllegalStateException(msg, sql);
099: }
100: }
101:
102: /**
103: * Advance to the next row in the ResultSet.
104: *
105: * @return a {@link java.util.Map} containing the data in the next row. The keys in the map
106: * correspond to the ResultSet's column names and are case insensitive when checking a key.
107: * @throws NoSuchElementException if the ResultSet is null or the end of the ResultSet has been reached
108: */
109: public Object next() {
110: if (_rs == null)
111: throw new NoSuchElementException(
112: Bundle
113: .getErrorString("IteratorFactory_Iterator_noSuchElement"));
114:
115: try {
116: if (!_primed) {
117: _primed = _rs.next();
118: if (!_primed) {
119: throw new NoSuchElementException(
120: Bundle
121: .getErrorString("IteratorFactory_Iterator_noSuchElement"));
122: }
123: }
124:
125: _primed = false;
126: return convertRow(_rs, _columnNames);
127: } catch (SQLException sql) {
128: String msg = "An exception occurred reading from the Iterator. Cause: "
129: + sql;
130: LOGGER.error(msg, sql);
131: throw new IllegalStateException(msg, sql);
132: }
133: }
134:
135: /**
136: * The remove operation is unsupported on the ResultSetIterator.
137: *
138: * @throws UnsupportedOperationException always
139: */
140: public void remove() {
141: throw new UnsupportedOperationException(Bundle.getErrorString(
142: "IteratorFactory_Iterator_removeUnsupported",
143: new Object[] { this .getClass().getName() }));
144: }
145:
146: private static final Object convertRow(final ResultSet resultSet,
147: final String[] columnNames) throws SQLException {
148: SortedMap map = new TreeMap(String.CASE_INSENSITIVE_ORDER);
149: for (int i = 0; i < columnNames.length; i++) {
150: Object value = resultSet.getObject(i + 1);
151: if (resultSet.wasNull())
152: value = null;
153: map.put(columnNames[i], value);
154: }
155: return map;
156: }
157: }
|