Coverage Report - org.apache.commons.dbutils.wrappers.SqlNullCheckedResultSet
 
Classes in this File Line Coverage Branch Coverage Complexity
SqlNullCheckedResultSet
99%
104/105
83%
5/6
1.089
 
 1  
 /*
 2  
  * Licensed to the Apache Software Foundation (ASF) under one or more
 3  
  * contributor license agreements.  See the NOTICE file distributed with
 4  
  * this work for additional information regarding copyright ownership.
 5  
  * The ASF licenses this file to You under the Apache License, Version 2.0
 6  
  * (the "License"); you may not use this file except in compliance with
 7  
  * the License.  You may obtain a copy of the License at
 8  
  *
 9  
  *      http://www.apache.org/licenses/LICENSE-2.0
 10  
  *
 11  
  * Unless required by applicable law or agreed to in writing, software
 12  
  * distributed under the License is distributed on an "AS IS" BASIS,
 13  
  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 14  
  * See the License for the specific language governing permissions and
 15  
  * limitations under the License.
 16  
  */
 17  
 package org.apache.commons.dbutils.wrappers;
 18  
 
 19  
 import java.io.InputStream;
 20  
 import java.io.Reader;
 21  
 import java.lang.reflect.InvocationHandler;
 22  
 import java.lang.reflect.Method;
 23  
 import java.math.BigDecimal;
 24  
 import java.net.URL;
 25  
 import java.sql.Blob;
 26  
 import java.sql.Clob;
 27  
 import java.sql.Date;
 28  
 import java.sql.Ref;
 29  
 import java.sql.ResultSet;
 30  
 import java.sql.Time;
 31  
 import java.sql.Timestamp;
 32  
 import java.util.HashMap;
 33  
 import java.util.Map;
 34  
 
 35  
 import org.apache.commons.dbutils.ProxyFactory;
 36  
 
 37  
 /**
 38  
  * Decorates a <code>ResultSet</code> with checks for a SQL NULL value on each
 39  
  * <code>getXXX</code> method. If a column value obtained by a
 40  
  * <code>getXXX</code> method is not SQL NULL, the column value is returned. If
 41  
  * the column value is SQL null, an alternate value is returned. The alternate
 42  
  * value defaults to the Java <code>null</code> value, which can be overridden
 43  
  * for instances of the class.
 44  
  *
 45  
  * <p>
 46  
  * Usage example:
 47  
  * <blockquote>
 48  
  * <pre>
 49  
  * Connection conn = // somehow get a connection
 50  
  * Statement stmt = conn.createStatement();
 51  
  * ResultSet rs = stmt.executeQuery("SELECT col1, col2 FROM table1");
 52  
  *
 53  
  * // Wrap the result set for SQL NULL checking
 54  
  * SqlNullCheckedResultSet wrapper = new SqlNullCheckedResultSet(rs);
 55  
  * wrapper.setNullString("---N/A---"); // Set null string
 56  
  * wrapper.setNullInt(-999); // Set null integer
 57  
  * rs = ProxyFactory.instance().createResultSet(wrapper);
 58  
  *
 59  
  * while (rs.next()) {
 60  
  *     // If col1 is SQL NULL, value returned will be "---N/A---"
 61  
  *     String col1 = rs.getString("col1");
 62  
  *     // If col2 is SQL NULL, value returned will be -999
 63  
  *     int col2 = rs.getInt("col2");
 64  
  * }
 65  
  * rs.close();
 66  
  * </pre>
 67  
  * </blockquote>
 68  
  * </p>
 69  
  * <p>Unlike some other classes in DbUtils, this class is NOT thread-safe.</p>
 70  
  */
 71  
 public class SqlNullCheckedResultSet implements InvocationHandler {
 72  
 
 73  
     /**
 74  
      * Maps normal method names (ie. "getBigDecimal") to the corresponding null
 75  
      * Method object (ie. getNullBigDecimal).
 76  
      */
 77  1
     private static final Map<String, Method> nullMethods = new HashMap<String, Method>();
 78  
 
 79  
     /**
 80  
      * The {@code getNull} string prefix.
 81  
      * @since 1.4
 82  
      */
 83  
     private static final String GET_NULL_PREFIX = "getNull";
 84  
 
 85  
     static {
 86  1
         Method[] methods = SqlNullCheckedResultSet.class.getMethods();
 87  54
         for (int i = 0; i < methods.length; i++) {
 88  53
             String methodName = methods[i].getName();
 89  
 
 90  53
             if (methodName.startsWith(GET_NULL_PREFIX)) {
 91  21
                 String normalName = "get" + methodName.substring(GET_NULL_PREFIX.length());
 92  21
                 nullMethods.put(normalName, methods[i]);
 93  
             }
 94  
         }
 95  
     }
 96  
 
 97  
     /**
 98  
      * The factory to create proxies with.
 99  
      */
 100  1
     private static final ProxyFactory factory = ProxyFactory.instance();
 101  
 
 102  
     /**
 103  
      * Wraps the <code>ResultSet</code> in an instance of this class.  This is
 104  
      * equivalent to:
 105  
      * <pre>
 106  
      * ProxyFactory.instance().createResultSet(new SqlNullCheckedResultSet(rs));
 107  
      * </pre>
 108  
      *
 109  
      * @param rs The <code>ResultSet</code> to wrap.
 110  
      * @return wrapped ResultSet
 111  
      */
 112  
     public static ResultSet wrap(ResultSet rs) {
 113  0
         return factory.createResultSet(new SqlNullCheckedResultSet(rs));
 114  
     }
 115  
 
 116  44
     private InputStream nullAsciiStream = null;
 117  44
     private BigDecimal nullBigDecimal = null;
 118  44
     private InputStream nullBinaryStream = null;
 119  44
     private Blob nullBlob = null;
 120  44
     private boolean nullBoolean = false;
 121  44
     private byte nullByte = 0;
 122  44
     private byte[] nullBytes = null;
 123  44
     private Reader nullCharacterStream = null;
 124  44
     private Clob nullClob = null;
 125  44
     private Date nullDate = null;
 126  44
     private double nullDouble = 0.0;
 127  44
     private float nullFloat = 0.0f;
 128  44
     private int nullInt = 0;
 129  44
     private long nullLong = 0;
 130  44
     private Object nullObject = null;
 131  44
     private Ref nullRef = null;
 132  44
     private short nullShort = 0;
 133  44
     private String nullString = null;
 134  44
     private Time nullTime = null;
 135  44
     private Timestamp nullTimestamp = null;
 136  44
     private URL nullURL = null;
 137  
 
 138  
     /**
 139  
      * The wrapped result.
 140  
      */
 141  
     private final ResultSet rs;
 142  
 
 143  
     /**
 144  
      * Constructs a new instance of
 145  
      * <code>SqlNullCheckedResultSet</code>
 146  
      * to wrap the specified <code>ResultSet</code>.
 147  
      * @param rs ResultSet to wrap
 148  
      */
 149  
     public SqlNullCheckedResultSet(ResultSet rs) {
 150  44
         super();
 151  44
         this.rs = rs;
 152  44
     }
 153  
 
 154  
     /**
 155  
      * Returns the value when a SQL null is encountered as the result of
 156  
      * invoking a <code>getAsciiStream</code> method.
 157  
      *
 158  
      * @return the value
 159  
      */
 160  
     public InputStream getNullAsciiStream() {
 161  11
         return this.nullAsciiStream;
 162  
     }
 163  
 
 164  
     /**
 165  
      * Returns the value when a SQL null is encountered as the result of
 166  
      * invoking a <code>getBigDecimal</code> method.
 167  
      *
 168  
      * @return the value
 169  
      */
 170  
     public BigDecimal getNullBigDecimal() {
 171  11
         return this.nullBigDecimal;
 172  
     }
 173  
 
 174  
     /**
 175  
      * Returns the value when a SQL null is encountered as the result of
 176  
      * invoking a <code>getBinaryStream</code> method.
 177  
      *
 178  
      * @return the value
 179  
      */
 180  
     public InputStream getNullBinaryStream() {
 181  11
         return this.nullBinaryStream;
 182  
     }
 183  
 
 184  
     /**
 185  
      * Returns the value when a SQL null is encountered as the result of
 186  
      * invoking a <code>getBlob</code> method.
 187  
      *
 188  
      * @return the value
 189  
      */
 190  
     public Blob getNullBlob() {
 191  11
         return this.nullBlob;
 192  
     }
 193  
 
 194  
     /**
 195  
      * Returns the value when a SQL null is encountered as the result of
 196  
      * invoking a <code>getBoolean</code> method.
 197  
      *
 198  
      * @return the value
 199  
      */
 200  
     public boolean getNullBoolean() {
 201  7
         return this.nullBoolean;
 202  
     }
 203  
 
 204  
     /**
 205  
      * Returns the value when a SQL null is encountered as the result of
 206  
      * invoking a <code>getByte</code> method.
 207  
      *
 208  
      * @return the value
 209  
      */
 210  
     public byte getNullByte() {
 211  7
         return this.nullByte;
 212  
     }
 213  
 
 214  
     /**
 215  
      * Returns the value when a SQL null is encountered as the result of
 216  
      * invoking a <code>getBytes</code> method.
 217  
      *
 218  
      * @return the value
 219  
      */
 220  
     public byte[] getNullBytes() {
 221  11
         if (this.nullBytes == null) {
 222  3
             return null;
 223  
         }
 224  8
         byte[] copy = new byte[this.nullBytes.length];
 225  8
         System.arraycopy(this.nullBytes, 0, copy, 0, this.nullBytes.length);
 226  8
         return copy;
 227  
     }
 228  
 
 229  
     /**
 230  
      * Returns the value when a SQL null is encountered as the result of
 231  
      * invoking a <code>getCharacterStream</code> method.
 232  
      *
 233  
      * @return the value
 234  
      */
 235  
     public Reader getNullCharacterStream() {
 236  11
         return this.nullCharacterStream;
 237  
     }
 238  
 
 239  
     /**
 240  
      * Returns the value when a SQL null is encountered as the result of
 241  
      * invoking a <code>getClob</code> method.
 242  
      *
 243  
      * @return the value
 244  
      */
 245  
     public Clob getNullClob() {
 246  11
         return this.nullClob;
 247  
     }
 248  
 
 249  
     /**
 250  
      * Returns the value when a SQL null is encountered as the result of
 251  
      * invoking a <code>getDate</code> method.
 252  
      *
 253  
      * @return the value
 254  
      */
 255  
     public Date getNullDate() {
 256  21
         return this.nullDate;
 257  
     }
 258  
 
 259  
     /**
 260  
      * Returns the value when a SQL null is encountered as the result of
 261  
      * invoking a <code>getDouble</code> method.
 262  
      *
 263  
      * @return the value
 264  
      */
 265  
     public double getNullDouble() {
 266  7
         return this.nullDouble;
 267  
     }
 268  
 
 269  
     /**
 270  
      * Returns the value when a SQL null is encountered as the result of
 271  
      * invoking a <code>getFloat</code> method.
 272  
      *
 273  
      * @return the value
 274  
      */
 275  
     public float getNullFloat() {
 276  7
         return this.nullFloat;
 277  
     }
 278  
 
 279  
     /**
 280  
      * Returns the value when a SQL null is encountered as the result of
 281  
      * invoking a <code>getInt</code> method.
 282  
      *
 283  
      * @return the value
 284  
      */
 285  
     public int getNullInt() {
 286  9
         return this.nullInt;
 287  
     }
 288  
 
 289  
     /**
 290  
      * Returns the value when a SQL null is encountered as the result of
 291  
      * invoking a <code>getLong</code> method.
 292  
      *
 293  
      * @return the value
 294  
      */
 295  
     public long getNullLong() {
 296  7
         return this.nullLong;
 297  
     }
 298  
 
 299  
     /**
 300  
      * Returns the value when a SQL null is encountered as the result of
 301  
      * invoking a <code>getObject</code> method.
 302  
      *
 303  
      * @return the value
 304  
      */
 305  
     public Object getNullObject() {
 306  21
         return this.nullObject;
 307  
     }
 308  
 
 309  
     /**
 310  
      * Returns the value when a SQL null is encountered as the result of
 311  
      * invoking a <code>getRef</code> method.
 312  
      *
 313  
      * @return the value
 314  
      */
 315  
     public Ref getNullRef() {
 316  11
         return this.nullRef;
 317  
     }
 318  
 
 319  
     /**
 320  
      * Returns the value when a SQL null is encountered as the result of
 321  
      * invoking a <code>getShort</code> method.
 322  
      *
 323  
      * @return the value
 324  
      */
 325  
     public short getNullShort() {
 326  7
         return this.nullShort;
 327  
     }
 328  
 
 329  
     /**
 330  
      * Returns the value when a SQL null is encountered as the result of
 331  
      * invoking a <code>getString</code> method.
 332  
      *
 333  
      * @return the value
 334  
      */
 335  
     public String getNullString() {
 336  8
         return this.nullString;
 337  
     }
 338  
 
 339  
     /**
 340  
      * Returns the value when a SQL null is encountered as the result of
 341  
      * invoking a <code>getTime</code> method.
 342  
      *
 343  
      * @return the value
 344  
      */
 345  
     public Time getNullTime() {
 346  21
         return this.nullTime;
 347  
     }
 348  
 
 349  
     /**
 350  
      * Returns the value when a SQL null is encountered as the result of
 351  
      * invoking a <code>getTimestamp</code> method.
 352  
      *
 353  
      * @return the value
 354  
      */
 355  
     public Timestamp getNullTimestamp() {
 356  21
         return this.nullTimestamp;
 357  
     }
 358  
 
 359  
     /**
 360  
      * Returns the value when a SQL null is encountered as the result of
 361  
      * invoking a <code>getURL</code> method.
 362  
      *
 363  
      * @return the value
 364  
      */
 365  
     public URL getNullURL() {
 366  4
         return this.nullURL;
 367  
     }
 368  
 
 369  
     /**
 370  
      * Intercepts calls to <code>get*</code> methods and calls the appropriate
 371  
      * <code>getNull*</code> method if the <code>ResultSet</code> returned
 372  
      * <code>null</code>.
 373  
      *
 374  
      *  @see java.lang.reflect.InvocationHandler#invoke(java.lang.Object, java.lang.reflect.Method, java.lang.Object[])
 375  
      * @param proxy Not used; all method calls go to the internal result set
 376  
      * @param method The method to invoke on the result set
 377  
      * @param args The arguments to pass to the result set
 378  
      * @return null checked result
 379  
      * @throws Throwable error
 380  
      */
 381  
     @Override
 382  
     public Object invoke(Object proxy, Method method, Object[] args)
 383  
         throws Throwable {
 384  
 
 385  268
         Object result = method.invoke(this.rs, args);
 386  
 
 387  268
         Method nullMethod = nullMethods.get(method.getName());
 388  
 
 389  
         // Check nullMethod != null first so that we don't call wasNull()
 390  
         // before a true getter method was invoked on the ResultSet.
 391  268
         return (nullMethod != null && this.rs.wasNull())
 392  
             ? nullMethod.invoke(this, (Object[]) null)
 393  
             : result;
 394  
     }
 395  
 
 396  
     /**
 397  
      * Sets the value to return when a SQL null is encountered as the result of
 398  
      * invoking a <code>getAsciiStream</code> method.
 399  
      *
 400  
      * @param nullAsciiStream the value
 401  
      */
 402  
     public void setNullAsciiStream(InputStream nullAsciiStream) {
 403  2
         this.nullAsciiStream = nullAsciiStream;
 404  2
     }
 405  
 
 406  
     /**
 407  
      * Sets the value to return when a SQL null is encountered as the result of
 408  
      * invoking a <code>getBigDecimal</code> method.
 409  
      *
 410  
      * @param nullBigDecimal the value
 411  
      */
 412  
     public void setNullBigDecimal(BigDecimal nullBigDecimal) {
 413  2
         this.nullBigDecimal = nullBigDecimal;
 414  2
     }
 415  
 
 416  
     /**
 417  
      * Sets the value to return when a SQL null is encountered as the result of
 418  
      * invoking a <code>getBinaryStream</code> method.
 419  
      *
 420  
      * @param nullBinaryStream the value
 421  
      */
 422  
     public void setNullBinaryStream(InputStream nullBinaryStream) {
 423  2
         this.nullBinaryStream = nullBinaryStream;
 424  2
     }
 425  
 
 426  
     /**
 427  
      * Sets the value to return when a SQL null is encountered as the result of
 428  
      * invoking a <code>getBlob</code> method.
 429  
      *
 430  
      * @param nullBlob the value
 431  
      */
 432  
     public void setNullBlob(Blob nullBlob) {
 433  2
         this.nullBlob = nullBlob;
 434  2
     }
 435  
 
 436  
     /**
 437  
      * Sets the value to return when a SQL null is encountered as the result of
 438  
      * invoking a <code>getBoolean</code> method.
 439  
      *
 440  
      * @param nullBoolean the value
 441  
      */
 442  
     public void setNullBoolean(boolean nullBoolean) {
 443  2
         this.nullBoolean = nullBoolean;
 444  2
     }
 445  
 
 446  
     /**
 447  
      * Sets the value to return when a SQL null is encountered as the result of
 448  
      * invoking a <code>getByte</code> method.
 449  
      *
 450  
      * @param nullByte the value
 451  
      */
 452  
     public void setNullByte(byte nullByte) {
 453  2
         this.nullByte = nullByte;
 454  2
     }
 455  
 
 456  
     /**
 457  
      * Sets the value to return when a SQL null is encountered as the result of
 458  
      * invoking a <code>getBytes</code> method.
 459  
      *
 460  
      * @param nullBytes the value
 461  
      */
 462  
     public void setNullBytes(byte[] nullBytes) {
 463  2
         byte[] copy = new byte[nullBytes.length];
 464  2
         System.arraycopy(nullBytes, 0, copy, 0, nullBytes.length);
 465  2
         this.nullBytes = copy;
 466  2
     }
 467  
 
 468  
     /**
 469  
      * Sets the value to return when a SQL null is encountered as the result of
 470  
      * invoking a <code>getCharacterStream</code> method.
 471  
      *
 472  
      * @param nullCharacterStream the value
 473  
      */
 474  
     public void setNullCharacterStream(Reader nullCharacterStream) {
 475  2
         this.nullCharacterStream = nullCharacterStream;
 476  2
     }
 477  
 
 478  
     /**
 479  
      * Sets the value to return when a SQL null is encountered as the result of
 480  
      * invoking a <code>getClob</code> method.
 481  
      *
 482  
      * @param nullClob the value
 483  
      */
 484  
     public void setNullClob(Clob nullClob) {
 485  2
         this.nullClob = nullClob;
 486  2
     }
 487  
 
 488  
     /**
 489  
      * Sets the value to return when a SQL null is encountered as the result of
 490  
      * invoking a <code>getDate</code> method.
 491  
      *
 492  
      * @param nullDate the value
 493  
      */
 494  
     public void setNullDate(Date nullDate) {
 495  2
         this.nullDate = nullDate;
 496  2
     }
 497  
 
 498  
     /**
 499  
      * Sets the value to return when a SQL null is encountered as the result of
 500  
      * invoking a <code>getDouble</code> method.
 501  
      *
 502  
      * @param nullDouble the value
 503  
      */
 504  
     public void setNullDouble(double nullDouble) {
 505  2
         this.nullDouble = nullDouble;
 506  2
     }
 507  
 
 508  
     /**
 509  
      * Sets the value to return when a SQL null is encountered as the result of
 510  
      * invoking a <code>getFloat</code> method.
 511  
      *
 512  
      * @param nullFloat the value
 513  
      */
 514  
     public void setNullFloat(float nullFloat) {
 515  2
         this.nullFloat = nullFloat;
 516  2
     }
 517  
 
 518  
     /**
 519  
      * Sets the value to return when a SQL null is encountered as the result of
 520  
      * invoking a <code>getInt</code> method.
 521  
      *
 522  
      * @param nullInt the value
 523  
      */
 524  
     public void setNullInt(int nullInt) {
 525  2
         this.nullInt = nullInt;
 526  2
     }
 527  
 
 528  
     /**
 529  
      * Sets the value to return when a SQL null is encountered as the result of
 530  
      * invoking a <code>getLong</code> method.
 531  
      *
 532  
      * @param nullLong the value
 533  
      */
 534  
     public void setNullLong(long nullLong) {
 535  2
         this.nullLong = nullLong;
 536  2
     }
 537  
 
 538  
     /**
 539  
      * Sets the value to return when a SQL null is encountered as the result of
 540  
      * invoking a <code>getObject</code> method.
 541  
      *
 542  
      * @param nullObject the value
 543  
      */
 544  
     public void setNullObject(Object nullObject) {
 545  2
         this.nullObject = nullObject;
 546  2
     }
 547  
 
 548  
     /**
 549  
      * Sets the value to return when a SQL null is encountered as the result of
 550  
      * invoking a <code>getRef</code> method.
 551  
      *
 552  
      * @param nullRef the value
 553  
      */
 554  
     public void setNullRef(Ref nullRef) {
 555  2
         this.nullRef = nullRef;
 556  2
     }
 557  
 
 558  
     /**
 559  
      * Sets the value to return when a SQL null is encountered as the result of
 560  
      * invoking a <code>getShort</code> method.
 561  
      *
 562  
      * @param nullShort the value
 563  
      */
 564  
     public void setNullShort(short nullShort) {
 565  2
         this.nullShort = nullShort;
 566  2
     }
 567  
 
 568  
     /**
 569  
      * Sets the value to return when a SQL null is encountered as the result of
 570  
      * invoking a <code>getString</code> method.
 571  
      *
 572  
      * @param nullString the value
 573  
      */
 574  
     public void setNullString(String nullString) {
 575  3
         this.nullString = nullString;
 576  3
     }
 577  
 
 578  
     /**
 579  
      * Sets the value to return when a SQL null is encountered as the result of
 580  
      * invoking a <code>getTime</code> method.
 581  
      *
 582  
      * @param nullTime the value
 583  
      */
 584  
     public void setNullTime(Time nullTime) {
 585  2
         this.nullTime = nullTime;
 586  2
     }
 587  
 
 588  
     /**
 589  
      * Sets the value to return when a SQL null is encountered as the result of
 590  
      * invoking a <code>getTimestamp</code> method.
 591  
      *
 592  
      * @param nullTimestamp the value
 593  
      */
 594  
     public void setNullTimestamp(Timestamp nullTimestamp) {
 595  2
         this.nullTimestamp = nullTimestamp;
 596  2
     }
 597  
 
 598  
     /**
 599  
      * Sets the value to return when a SQL null is encountered as the result of
 600  
      * invoking a <code>getURL</code> method.
 601  
      *
 602  
      * @param nullURL the value
 603  
      */
 604  
     public void setNullURL(URL nullURL) {
 605  1
         this.nullURL = nullURL;
 606  1
     }
 607  
 
 608  
 }