Author: dfabulich
Date: Wed Feb 11 08:08:01 2009
New Revision: 743269

URL: http://svn.apache.org/viewvc?rev=743269&view=rev
Log:
[DBUTILS-34] BasicRowProcessor loses any information on database field case
Submitted by: Julien Aymé

Modified:
    
commons/sandbox/dbutils/bugfixing/src/java/org/apache/commons/dbutils/BasicRowProcessor.java

Modified: 
commons/sandbox/dbutils/bugfixing/src/java/org/apache/commons/dbutils/BasicRowProcessor.java
URL: 
http://svn.apache.org/viewvc/commons/sandbox/dbutils/bugfixing/src/java/org/apache/commons/dbutils/BasicRowProcessor.java?rev=743269&r1=743268&r2=743269&view=diff
==============================================================================
--- 
commons/sandbox/dbutils/bugfixing/src/java/org/apache/commons/dbutils/BasicRowProcessor.java
 (original)
+++ 
commons/sandbox/dbutils/bugfixing/src/java/org/apache/commons/dbutils/BasicRowProcessor.java
 Wed Feb 11 08:08:01 2009
@@ -144,10 +144,36 @@
      * A Map that converts all keys to lowercase Strings for case insensitive
      * lookups.  This is needed for the toMap() implementation because 
      * databases don't consistenly handle the casing of column names. 
+     * 
+     * <p>The keys are stored as they are given [BUG #DBUTILS-34], so we 
maintain
+     * an internal mapping from lowercase keys to the real keys in order to 
+     * achieve the case insensitive lookup.
+     * 
+     * <p>Note: This implementation does not allow <tt>null</tt>
+     * for key, whereas {...@link HashMap} does, because of the code:
+     * <pre>
+     * key.toString().toLowerCase()
+     * </pre>
      */
     private static class CaseInsensitiveHashMap extends HashMap {
 
         /**
+         * The internal mapping from lowercase keys to the real keys.
+         * 
+         * <p>
+         * Any query operation using the key 
+         * ({...@link #get(Object)}, {...@link #containsKey(Object)})
+         * is done in three steps:
+         * <ul>
+         * <li>convert the parameter key to lower case</li>
+         * <li>get the actual key that corresponds to the lower case key</li>
+         * <li>query the map with the actual key</li>
+         * </ul>
+         * </p>
+         */
+        private Map lowerCaseMap = new HashMap();
+
+        /**
          * Required for serialization support.
          * 
          * @see java.io.Serializable
@@ -158,21 +184,37 @@
          * @see java.util.Map#containsKey(java.lang.Object)
          */
         public boolean containsKey(Object key) {
-            return super.containsKey(key.toString().toLowerCase());
+            Object realKey = lowerCaseMap.get(key.toString().toLowerCase());
+            return super.containsKey(realKey);
+            // Possible optimisation here:
+            // Since the lowerCaseMap contains a mapping for all the keys,
+            // we could just do this:
+            // return lowerCaseMap.containsKey(key.toString().toLowerCase());
         }
 
         /**
          * @see java.util.Map#get(java.lang.Object)
          */
         public Object get(Object key) {
-            return super.get(key.toString().toLowerCase());
+            Object realKey = lowerCaseMap.get(key.toString().toLowerCase());
+            return super.get(realKey);
         }
 
         /**
          * @see java.util.Map#put(java.lang.Object, java.lang.Object)
          */
         public Object put(Object key, Object value) {
-            return super.put(key.toString().toLowerCase(), value);
+            /*
+             * In order to keep the map and lowerCaseMap synchronized,
+             * we have to remove the old mapping before putting the 
+             * new one. Indeed, oldKey and key are not necessaliry equals.
+             * (That's why we call super.remove(oldKey) and not just
+             * super.put(key, value))
+             */
+            Object oldKey = lowerCaseMap.put(key.toString().toLowerCase(), 
key);
+            Object oldValue = super.remove(oldKey);
+            super.put(key, value);
+            return oldValue;
         }
 
         /**
@@ -191,7 +233,8 @@
          * @see java.util.Map#remove(java.lang.Object)
          */
         public Object remove(Object key) {
-            return super.remove(key.toString().toLowerCase());
+            Object realKey = lowerCaseMap.remove(key.toString().toLowerCase());
+            return super.remove(realKey);
         }
     }
     


Reply via email to