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 018package org.apache.commons.beanutils; 019 020import java.sql.SQLException; 021import java.util.Iterator; 022import java.util.NoSuchElementException; 023 024/** 025 * <p>Implements {@link Iterator} returned by the 026 * <code>iterator()</code> method of {@link ResultSetDynaClass}. Each 027 * object returned by this iterator will be a {@link DynaBean} that 028 * represents a single row from the result set being wrapped.</p> 029 * 030 */ 031public class ResultSetIterator implements DynaBean, Iterator<DynaBean> { 032 033 /** 034 * <p>Flag indicating whether the result set is currently positioned at a 035 * row for which we have not yet returned an element in the iteration.</p> 036 */ 037 protected boolean current; 038 039 /** 040 * <p>The {@link ResultSetDynaClass} we are associated with.</p> 041 */ 042 protected ResultSetDynaClass dynaClass; 043 044 /** 045 * <p>Flag indicating whether the result set has indicated that there are 046 * no further rows.</p> 047 */ 048 protected boolean eof; 049 050 /** 051 * <p>Construct an <code>Iterator</code> for the result set being wrapped 052 * by the specified {@link ResultSetDynaClass}.</p> 053 * 054 * @param dynaClass The {@link ResultSetDynaClass} wrapping the 055 * result set we will iterate over 056 */ 057 ResultSetIterator(final ResultSetDynaClass dynaClass) { 058 this.dynaClass = dynaClass; 059 } 060 061 /** 062 * <p>Advance the result set to the next row, if there is not a current 063 * row (and if we are not already at eof).</p> 064 * 065 * @throws SQLException if the result set throws an exception 066 */ 067 protected void advance() throws SQLException { 068 if (!current && !eof) { 069 if (dynaClass.getResultSet().next()) { 070 current = true; 071 eof = false; 072 } else { 073 current = false; 074 eof = true; 075 } 076 } 077 } 078 079 /** 080 * Does the specified mapped property contain a value for the specified 081 * key value? 082 * 083 * @param name Name of the property to check 084 * @param key Name of the key to check 085 * @return <code>true</code> if the mapped property contains a value for 086 * the specified key, otherwise <code>false</code> 087 * 088 * @throws IllegalArgumentException if there is no property 089 * of the specified name 090 */ 091 @Override 092 public boolean contains(final String name, final String key) { 093 throw new UnsupportedOperationException 094 ("FIXME - mapped properties not currently supported"); 095 } 096 097 /** 098 * Return the value of a simple property with the specified name. 099 * 100 * @param name Name of the property whose value is to be retrieved 101 * @return The property's value 102 * @throws IllegalArgumentException if there is no property 103 * of the specified name 104 */ 105 @Override 106 public Object get(final String name) { 107 if (dynaClass.getDynaProperty(name) == null) { 108 throw new IllegalArgumentException(name); 109 } 110 try { 111 return dynaClass.getObjectFromResultSet(name); 112 } catch (final SQLException e) { 113 throw new RuntimeException 114 ("get(" + name + "): SQLException: " + e); 115 } 116 } 117 118 /** 119 * Return the value of an indexed property with the specified name. 120 * 121 * @param name Name of the property whose value is to be retrieved 122 * @param index Index of the value to be retrieved 123 * @return The indexed property's value 124 * @throws IllegalArgumentException if there is no property 125 * of the specified name 126 * @throws IllegalArgumentException if the specified property 127 * exists, but is not indexed 128 * @throws IndexOutOfBoundsException if the specified index 129 * is outside the range of the underlying property 130 * @throws NullPointerException if no array or List has been 131 * initialized for this property 132 */ 133 @Override 134 public Object get(final String name, final int index) { 135 throw new UnsupportedOperationException 136 ("FIXME - indexed properties not currently supported"); 137 } 138 139 /** 140 * Return the value of a mapped property with the specified name, 141 * or <code>null</code> if there is no value for the specified key. 142 * 143 * @param name Name of the property whose value is to be retrieved 144 * @param key Key of the value to be retrieved 145 * @return The mapped property's value 146 * @throws IllegalArgumentException if there is no property 147 * of the specified name 148 * @throws IllegalArgumentException if the specified property 149 * exists, but is not mapped 150 */ 151 @Override 152 public Object get(final String name, final String key) { 153 throw new UnsupportedOperationException 154 ("FIXME - mapped properties not currently supported"); 155 } 156 157 /** 158 * Return the <code>DynaClass</code> instance that describes the set of 159 * properties available for this DynaBean. 160 * 161 * @return The associated DynaClass 162 */ 163 @Override 164 public DynaClass getDynaClass() { 165 return this.dynaClass; 166 } 167 168 /** 169 * <p>Return <code>true</code> if the iteration has more elements.</p> 170 * 171 * @return <code>true</code> if the result set has another 172 * row, otherwise <code>false</code> 173 */ 174 @Override 175 public boolean hasNext() { 176 try { 177 advance(); 178 return !eof; 179 } catch (final SQLException e) { 180 throw new RuntimeException("hasNext(): SQLException: " + e); 181 } 182 } 183 184 /** 185 * <p>Return the next element in the iteration.</p> 186 * 187 * @return advance to the new row and return this 188 */ 189 @Override 190 public DynaBean next() { 191 try { 192 advance(); 193 if (eof) { 194 throw new NoSuchElementException(); 195 } 196 current = false; 197 return this; 198 } catch (final SQLException e) { 199 throw new RuntimeException("next(): SQLException: " + e); 200 } 201 202 } 203 204 /** 205 * <p>Remove the current element from the iteration. This method is 206 * not supported.</p> 207 */ 208 @Override 209 public void remove() { 210 throw new UnsupportedOperationException("remove()"); 211 } 212 213 /** 214 * Remove any existing value for the specified key on the 215 * specified mapped property. 216 * 217 * @param name Name of the property for which a value is to 218 * be removed 219 * @param key Key of the value to be removed 220 * @throws IllegalArgumentException if there is no property 221 * of the specified name 222 */ 223 @Override 224 public void remove(final String name, final String key) { 225 throw new UnsupportedOperationException 226 ("FIXME - mapped operations not currently supported"); 227 } 228 229 /** 230 * Set the value of an indexed property with the specified name. 231 * 232 * @param name Name of the property whose value is to be set 233 * @param index Index of the property to be set 234 * @param value Value to which this property is to be set 235 * @throws ConversionException if the specified value cannot be 236 * converted to the type required for this property 237 * @throws IllegalArgumentException if there is no property 238 * of the specified name 239 * @throws IllegalArgumentException if the specified property 240 * exists, but is not indexed 241 * @throws IndexOutOfBoundsException if the specified index 242 * is outside the range of the underlying property 243 */ 244 @Override 245 public void set(final String name, final int index, final Object value) { 246 throw new UnsupportedOperationException 247 ("FIXME - indexed properties not currently supported"); 248 } 249 250 /** 251 * Set the value of a simple property with the specified name. 252 * 253 * @param name Name of the property whose value is to be set 254 * @param value Value to which this property is to be set 255 * @throws ConversionException if the specified value cannot be 256 * converted to the type required for this property 257 * @throws IllegalArgumentException if there is no property 258 * of the specified name 259 * @throws NullPointerException if an attempt is made to set a 260 * primitive property to null 261 */ 262 @Override 263 public void set(final String name, final Object value) { 264 if (dynaClass.getDynaProperty(name) == null) { 265 throw new IllegalArgumentException(name); 266 } 267 try { 268 dynaClass.getResultSet().updateObject(name, value); 269 } catch (final SQLException e) { 270 throw new RuntimeException 271 ("set(" + name + "): SQLException: " + e); 272 } 273 } 274 275 /** 276 * Set the value of a mapped property with the specified name. 277 * 278 * @param name Name of the property whose value is to be set 279 * @param key Key of the property to be set 280 * @param value Value to which this property is to be set 281 * @throws ConversionException if the specified value cannot be 282 * converted to the type required for this property 283 * @throws IllegalArgumentException if there is no property 284 * of the specified name 285 * @throws IllegalArgumentException if the specified property 286 * exists, but is not mapped 287 */ 288 @Override 289 public void set(final String name, final String key, final Object value) { 290 throw new UnsupportedOperationException 291 ("FIXME - mapped properties not currently supported"); 292 } 293 294}