Index: BasicRowProcessor.java
===================================================================
--- BasicRowProcessor.java (revision 536476)
+++ BasicRowProcessor.java (working copy)
@@ -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.
+ *
+ *
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.
+ *
+ *
Note: This implementation does not allow null
+ * for key, whereas {@link HashMap} does, because of the code:
+ *
+ * key.toString().toLowerCase()
+ *
*/
private static class CaseInsensitiveHashMap extends HashMap {
/**
+ * The internal mapping from lowercase keys to the real keys.
+ *
+ *
+ * Any query operation using the key
+ * ({@link #get(Object)}, {@link #containsKey(Object)})
+ * is done in three steps:
+ *
+ * - convert the parameter key to lower case
+ * - get the actual key that corresponds to the lower case key
+ * - query the map with the actual key
+ *
+ *
+ */
+ 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);
}
}