Coverage Report - org.apache.commons.dbutils.BasicRowProcessor
 
Classes in this File Line Coverage Branch Coverage Complexity
BasicRowProcessor
0%
0/22
0%
0/4
1.25
BasicRowProcessor$1
N/A
N/A
1.25
BasicRowProcessor$CaseInsensitiveHashMap
0%
0/20
0%
0/2
1.25
 
 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;
 18  
 
 19  
 import java.sql.ResultSet;
 20  
 import java.sql.ResultSetMetaData;
 21  
 import java.sql.SQLException;
 22  
 import java.util.HashMap;
 23  
 import java.util.Iterator;
 24  
 import java.util.List;
 25  
 import java.util.Map;
 26  
 
 27  
 /**
 28  
  * Basic implementation of the <code>RowProcessor</code> interface.
 29  
  * 
 30  
  * <p>
 31  
  * This class is thread-safe.
 32  
  * </p>
 33  
  * 
 34  
  * @see RowProcessor
 35  
  */
 36  
 public class BasicRowProcessor implements RowProcessor {
 37  
 
 38  
     /**
 39  
      * The default BeanProcessor instance to use if not supplied in the
 40  
      * constructor.
 41  
      */
 42  0
     private static final BeanProcessor defaultConvert = new BeanProcessor();
 43  
 
 44  
     /**
 45  
      * The Singleton instance of this class.
 46  
      */
 47  0
     private static final BasicRowProcessor instance = new BasicRowProcessor();
 48  
 
 49  
     /**
 50  
      * Returns the Singleton instance of this class.
 51  
      *
 52  
      * @return The single instance of this class.
 53  
      * @deprecated Create instances with the constructors instead.  This will 
 54  
      * be removed after DbUtils 1.1.
 55  
      */
 56  
     public static BasicRowProcessor instance() {
 57  0
         return instance;
 58  
     }
 59  
 
 60  
     /**
 61  
      * Use this to process beans.
 62  
      */
 63  
     private final BeanProcessor convert;
 64  
 
 65  
     /**
 66  
      * BasicRowProcessor constructor.  Bean processing defaults to a 
 67  
      * BeanProcessor instance.
 68  
      */
 69  
     public BasicRowProcessor() {
 70  0
         this(defaultConvert);
 71  0
     }
 72  
     
 73  
     /**
 74  
      * BasicRowProcessor constructor.
 75  
      * @param convert The BeanProcessor to use when converting columns to 
 76  
      * bean properties.
 77  
      * @since DbUtils 1.1
 78  
      */
 79  
     public BasicRowProcessor(BeanProcessor convert) {
 80  0
         super();
 81  0
         this.convert = convert;
 82  0
     }
 83  
 
 84  
     /**
 85  
      * Convert a <code>ResultSet</code> row into an <code>Object[]</code>.
 86  
      * This implementation copies column values into the array in the same 
 87  
      * order they're returned from the <code>ResultSet</code>.  Array elements
 88  
      * will be set to <code>null</code> if the column was SQL NULL.
 89  
      *
 90  
      * @see org.apache.commons.dbutils.RowProcessor#toArray(java.sql.ResultSet)
 91  
      */
 92  
     public Object[] toArray(ResultSet rs) throws SQLException {
 93  0
         ResultSetMetaData meta = rs.getMetaData();
 94  0
         int cols = meta.getColumnCount();
 95  0
         Object[] result = new Object[cols];
 96  
 
 97  0
         for (int i = 0; i < cols; i++) {
 98  0
             result[i] = rs.getObject(i + 1);
 99  
         }
 100  
 
 101  0
         return result;
 102  
     }
 103  
 
 104  
     /**
 105  
      * Convert a <code>ResultSet</code> row into a JavaBean.  This 
 106  
      * implementation delegates to a BeanProcessor instance.
 107  
      * @see org.apache.commons.dbutils.RowProcessor#toBean(java.sql.ResultSet, java.lang.Class)
 108  
      * @see org.apache.commons.dbutils.BeanProcessor#toBean(java.sql.ResultSet, java.lang.Class) 
 109  
      */
 110  
     public Object toBean(ResultSet rs, Class type) throws SQLException {
 111  0
         return this.convert.toBean(rs, type);
 112  
     }
 113  
 
 114  
     /**
 115  
      * Convert a <code>ResultSet</code> into a <code>List</code> of JavaBeans.  
 116  
      * This implementation delegates to a BeanProcessor instance. 
 117  
      * @see org.apache.commons.dbutils.RowProcessor#toBeanList(java.sql.ResultSet, java.lang.Class)
 118  
      * @see org.apache.commons.dbutils.BeanProcessor#toBeanList(java.sql.ResultSet, java.lang.Class)
 119  
      */
 120  
     public List toBeanList(ResultSet rs, Class type) throws SQLException {
 121  0
         return this.convert.toBeanList(rs, type);
 122  
     }
 123  
 
 124  
     /**
 125  
      * Convert a <code>ResultSet</code> row into a <code>Map</code>.  This 
 126  
      * implementation returns a <code>Map</code> with case insensitive column
 127  
      * names as keys.  Calls to <code>map.get("COL")</code> and 
 128  
      * <code>map.get("col")</code> return the same value.
 129  
      * @see org.apache.commons.dbutils.RowProcessor#toMap(java.sql.ResultSet)
 130  
      */
 131  
     public Map toMap(ResultSet rs) throws SQLException {
 132  0
         Map result = new CaseInsensitiveHashMap();
 133  0
         ResultSetMetaData rsmd = rs.getMetaData();
 134  0
         int cols = rsmd.getColumnCount();
 135  
 
 136  0
         for (int i = 1; i <= cols; i++) {
 137  0
             result.put(rsmd.getColumnName(i), rs.getObject(i));
 138  
         }
 139  
 
 140  0
         return result;
 141  
     }
 142  
     
 143  
     /**
 144  
      * A Map that converts all keys to lowercase Strings for case insensitive
 145  
      * lookups.  This is needed for the toMap() implementation because 
 146  
      * databases don't consistenly handle the casing of column names. 
 147  
      * 
 148  
      * <p>The keys are stored as they are given [BUG #DBUTILS-34], so we maintain
 149  
      * an internal mapping from lowercase keys to the real keys in order to 
 150  
      * achieve the case insensitive lookup.
 151  
      * 
 152  
      * <p>Note: This implementation does not allow <tt>null</tt>
 153  
      * for key, whereas {@link HashMap} does, because of the code:
 154  
      * <pre>
 155  
      * key.toString().toLowerCase()
 156  
      * </pre>
 157  
      */
 158  0
     private static class CaseInsensitiveHashMap extends HashMap {
 159  
 
 160  
         /**
 161  
          * The internal mapping from lowercase keys to the real keys.
 162  
          * 
 163  
          * <p>
 164  
          * Any query operation using the key 
 165  
          * ({@link #get(Object)}, {@link #containsKey(Object)})
 166  
          * is done in three steps:
 167  
          * <ul>
 168  
          * <li>convert the parameter key to lower case</li>
 169  
          * <li>get the actual key that corresponds to the lower case key</li>
 170  
          * <li>query the map with the actual key</li>
 171  
          * </ul>
 172  
          * </p>
 173  
          */
 174  0
         private final Map lowerCaseMap = new HashMap();
 175  
 
 176  
         /**
 177  
          * Required for serialization support.
 178  
          * 
 179  
          * @see java.io.Serializable
 180  
          */ 
 181  
         private static final long serialVersionUID = 1841673097701957808L;
 182  
 
 183  
         /**
 184  
          * @see java.util.Map#containsKey(java.lang.Object)
 185  
          */
 186  
         public boolean containsKey(Object key) {
 187  0
             Object realKey = lowerCaseMap.get(key.toString().toLowerCase());
 188  0
             return super.containsKey(realKey);
 189  
             // Possible optimisation here:
 190  
             // Since the lowerCaseMap contains a mapping for all the keys,
 191  
             // we could just do this:
 192  
             // return lowerCaseMap.containsKey(key.toString().toLowerCase());
 193  
         }
 194  
 
 195  
         /**
 196  
          * @see java.util.Map#get(java.lang.Object)
 197  
          */
 198  
         public Object get(Object key) {
 199  0
             Object realKey = lowerCaseMap.get(key.toString().toLowerCase());
 200  0
             return super.get(realKey);
 201  
         }
 202  
 
 203  
         /**
 204  
          * @see java.util.Map#put(java.lang.Object, java.lang.Object)
 205  
          */
 206  
         public Object put(Object key, Object value) {
 207  
             /*
 208  
              * In order to keep the map and lowerCaseMap synchronized,
 209  
              * we have to remove the old mapping before putting the 
 210  
              * new one. Indeed, oldKey and key are not necessaliry equals.
 211  
              * (That's why we call super.remove(oldKey) and not just
 212  
              * super.put(key, value))
 213  
              */
 214  0
             Object oldKey = lowerCaseMap.put(key.toString().toLowerCase(), key);
 215  0
             Object oldValue = super.remove(oldKey);
 216  0
             super.put(key, value);
 217  0
             return oldValue;
 218  
         }
 219  
 
 220  
         /**
 221  
          * @see java.util.Map#putAll(java.util.Map)
 222  
          */
 223  
         public void putAll(Map m) {
 224  0
             Iterator iter = m.entrySet().iterator();
 225  0
             while (iter.hasNext()) {
 226  0
                 Map.Entry entry = (Map.Entry) iter.next();
 227  0
                 Object key = entry.getKey();
 228  0
                 Object value = entry.getValue();
 229  0
                 this.put(key, value);
 230  0
             }
 231  0
         }
 232  
 
 233  
         /**
 234  
          * @see java.util.Map#remove(java.lang.Object)
 235  
          */
 236  
         public Object remove(Object key) {
 237  0
             Object realKey = lowerCaseMap.remove(key.toString().toLowerCase());
 238  0
             return super.remove(realKey);
 239  
         }
 240  
     }
 241  
     
 242  
 }