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 * https://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 IllegalArgumentException("get(" + name + "): SQLException: " + e, e); 114 } 115 } 116 117 /** 118 * Return the value of an indexed property with the specified name. 119 * 120 * @param name Name of the property whose value is to be retrieved 121 * @param index Index of the value to be retrieved 122 * @return The indexed property's value 123 * @throws IllegalArgumentException if there is no property 124 * of the specified name 125 * @throws IllegalArgumentException if the specified property 126 * exists, but is not indexed 127 * @throws IndexOutOfBoundsException if the specified index 128 * is outside the range of the underlying property 129 * @throws NullPointerException if no array or List has been 130 * initialized for this property 131 */ 132 @Override 133 public Object get(final String name, final int index) { 134 throw new UnsupportedOperationException 135 ("FIXME - indexed properties not currently supported"); 136 } 137 138 /** 139 * Return the value of a mapped property with the specified name, 140 * or <code>null</code> if there is no value for the specified key. 141 * 142 * @param name Name of the property whose value is to be retrieved 143 * @param key Key of the value to be retrieved 144 * @return The mapped property's value 145 * @throws IllegalArgumentException if there is no property 146 * of the specified name 147 * @throws IllegalArgumentException if the specified property 148 * exists, but is not mapped 149 */ 150 @Override 151 public Object get(final String name, final String key) { 152 throw new UnsupportedOperationException 153 ("FIXME - mapped properties not currently supported"); 154 } 155 156 /** 157 * Return the <code>DynaClass</code> instance that describes the set of 158 * properties available for this DynaBean. 159 * 160 * @return The associated DynaClass 161 */ 162 @Override 163 public DynaClass getDynaClass() { 164 return this.dynaClass; 165 } 166 167 /** 168 * <p>Return <code>true</code> if the iteration has more elements.</p> 169 * 170 * @return <code>true</code> if the result set has another 171 * row, otherwise <code>false</code> 172 */ 173 @Override 174 public boolean hasNext() { 175 try { 176 advance(); 177 return !eof; 178 } catch (final SQLException e) { 179 throw new IllegalStateException("hasNext(): SQLException: " + e, e); 180 } 181 } 182 183 /** 184 * <p>Return the next element in the iteration.</p> 185 * 186 * @return advance to the new row and return this 187 */ 188 @Override 189 public DynaBean next() { 190 try { 191 advance(); 192 if (eof) { 193 throw new NoSuchElementException(); 194 } 195 current = false; 196 return this; 197 } catch (final SQLException e) { 198 throw new IllegalStateException("next(): SQLException: " + e, e); 199 } 200 201 } 202 203 /** 204 * <p>Remove the current element from the iteration. This method is 205 * not supported.</p> 206 */ 207 @Override 208 public void remove() { 209 throw new UnsupportedOperationException("remove()"); 210 } 211 212 /** 213 * Remove any existing value for the specified key on the 214 * specified mapped property. 215 * 216 * @param name Name of the property for which a value is to 217 * be removed 218 * @param key Key of the value to be removed 219 * @throws IllegalArgumentException if there is no property 220 * of the specified name 221 */ 222 @Override 223 public void remove(final String name, final String key) { 224 throw new UnsupportedOperationException 225 ("FIXME - mapped operations not currently supported"); 226 } 227 228 /** 229 * Set the value of an indexed property with the specified name. 230 * 231 * @param name Name of the property whose value is to be set 232 * @param index Index of the property to be set 233 * @param value Value to which this property is to be set 234 * @throws ConversionException if the specified value cannot be 235 * converted to the type required for this property 236 * @throws IllegalArgumentException if there is no property 237 * of the specified name 238 * @throws IllegalArgumentException if the specified property 239 * exists, but is not indexed 240 * @throws IndexOutOfBoundsException if the specified index 241 * is outside the range of the underlying property 242 */ 243 @Override 244 public void set(final String name, final int index, final Object value) { 245 throw new UnsupportedOperationException 246 ("FIXME - indexed properties not currently supported"); 247 } 248 249 /** 250 * Set the value of a simple property with the specified name. 251 * 252 * @param name Name of the property whose value is to be set 253 * @param value Value to which this property is to be set 254 * @throws ConversionException if the specified value cannot be 255 * converted to the type required for this property 256 * @throws IllegalArgumentException if there is no property 257 * of the specified name 258 * @throws NullPointerException if an attempt is made to set a 259 * primitive property to null 260 */ 261 @Override 262 public void set(final String name, final Object value) { 263 if (dynaClass.getDynaProperty(name) == null) { 264 throw new IllegalArgumentException(name); 265 } 266 try { 267 dynaClass.getResultSet().updateObject(name, value); 268 } catch (final SQLException e) { 269 throw new IllegalArgumentException("set(" + name + "): SQLException: " + e, e); 270 } 271 } 272 273 /** 274 * Set the value of a mapped property with the specified name. 275 * 276 * @param name Name of the property whose value is to be set 277 * @param key Key of the property to be set 278 * @param value Value to which this property is to be set 279 * @throws ConversionException if the specified value cannot be 280 * converted to the type required for this property 281 * @throws IllegalArgumentException if there is no property 282 * of the specified name 283 * @throws IllegalArgumentException if the specified property 284 * exists, but is not mapped 285 */ 286 @Override 287 public void set(final String name, final String key, final Object value) { 288 throw new UnsupportedOperationException("FIXME - mapped properties not currently supported"); 289 } 290 291}