All Downloads are FREE. Search and download functionalities are using the official Maven repository.

com.mockrunner.util.common.CaseAwareMap Maven / Gradle / Ivy

package com.mockrunner.util.common;

import java.util.Collection;
import java.util.HashMap;
import java.util.Iterator;
import java.util.Map;
import java.util.Set;

/**
 * Implementation of a Map that recognizes the case of the
 * keys, if the keys are strings. If isCaseSensitive is
 * true it behaves exactly like a HashMap.
 * If isCaseSensitive is false (which is the
 * default), it considers same strings with different case as equal.
 * I.e. if you do
 * 
*
* put("test", "1"); *
* put("TEST", "2"); *
*
* the second put overwrites the value of the first one, * because the keys are considered to be equal. With *
*
* get("TesT"); *
*
* you'll get the result "2". * If you iterate through the keys (using either keySet or * entrySet), you'll get the first added version of the key, * in the above case, you'll get "test". * It is allowed to use non-strings as keys. In this case the Map * behaves like a usual HashMap.
* Note: This class is similar to a TreeMap(String.CASE_INSENSITIVE_ORDER) * except that non-strings do not throw a ClassCastException * and that keys are not sorted. */ public class CaseAwareMap implements Map { private boolean isCaseSensitive; private Map caseInsensitiveMap; private Map actualMap; public CaseAwareMap() { this(false); } public CaseAwareMap(boolean isCaseSensitive) { this.isCaseSensitive = isCaseSensitive; caseInsensitiveMap = new HashMap(); actualMap = new HashMap(); } /** * Returns if keys are case sensitive. Defaults to false. * @return are keys case sensitive */ public boolean isCaseSensitive() { return isCaseSensitive; } /** * Sets if keys are case sensitive. * If set to true this implementation behaves like * a HashMap. Please note, that all entries are cleared * when switching case sensitivity. It's not possible to switch * and keep the entries. * @param isCaseSensitive are keys case sensitive */ public void setCaseSensitive(boolean isCaseSensitive) { clear(); this.isCaseSensitive = isCaseSensitive; } public void clear() { caseInsensitiveMap.clear(); actualMap.clear(); } public boolean containsKey(Object key) { Object compareKey = getCompareKey(key); return getCompareMap().containsKey(compareKey); } public boolean containsValue(Object value) { return actualMap.containsValue(value); } public Set entrySet() { return actualMap.entrySet(); } public Object get(Object key) { Object compareKey = getCompareKey(key); return getCompareMap().get(compareKey); } public boolean isEmpty() { return size() <= 0; } public Set keySet() { return actualMap.keySet(); } public Object put(Object key, Object value) { return doConsistentModify(key, new ConsistentPut(value)); } public void putAll(Map map) { Iterator keys = map.keySet().iterator(); while(keys.hasNext()) { Object nextKey = keys.next(); Object nextValue = map.get(nextKey); put(nextKey, nextValue); } } public Object remove(Object key) { return doConsistentModify(key, new ConsistentRemove()); } public int size() { return actualMap.size(); } public Collection values() { return actualMap.values(); } private boolean areKeysEquals(Object actualKey, Object compareKey) { if(null == actualKey && null == compareKey) return true; if(null == actualKey) return false; if(null == compareKey) return false; Object actualCompareKey = getCompareKey(actualKey); return compareKey.equals(actualCompareKey); } private boolean isStringKey(Object key) { return (null != key) && (key instanceof String); } private Object getCompareKey(Object key) { if(isCaseSensitive || !isStringKey(key)) { return key; } return ((String)key).toUpperCase(); } private Map getCompareMap() { if(isCaseSensitive) { return actualMap; } return caseInsensitiveMap; } private Object doConsistentModify(Object key, ConsistentModify modifier) { Object compareKey = getCompareKey(key); if(!caseInsensitiveMap.containsKey(compareKey)) { return modifier.modify(key, compareKey); } Iterator iterator = actualMap.keySet().iterator(); while(iterator.hasNext()) { Object actualKey = iterator.next(); if(areKeysEquals(actualKey, compareKey)) { return modifier.modify(actualKey, compareKey); } } return null; } private interface ConsistentModify { public Object modify(Object key1, Object key2); } private class ConsistentRemove implements ConsistentModify { public Object modify(Object key1, Object key2) { actualMap.remove(key1); return caseInsensitiveMap.remove(key2); } } private class ConsistentPut implements ConsistentModify { private Object value; public ConsistentPut(Object value) { this.value = value; } public Object modify(Object key1, Object key2) { actualMap.put(key1, value); return caseInsensitiveMap.put(key2, value); } } }




© 2015 - 2024 Weber Informatics LLC | Privacy Policy