/** * Create a Map instance to be used as column map. * <p>By default, a linked case-insensitive Map will be created. * @param columnCount the column count, to be used as initial * capacity for the Map * @return the new Map instance * @see org.springframework.util.LinkedCaseInsensitiveMap */ protected Map<String, Object> createColumnMap(int columnCount) { return new LinkedCaseInsensitiveMap<>(columnCount); }
@Nullable /* for testing */ static LinkedCaseInsensitiveMap<String> splitIntoCaseInsensitiveMap(String[] pairs) { if (ObjectUtils.isEmpty(pairs)) { return null; } LinkedCaseInsensitiveMap<String> result = new LinkedCaseInsensitiveMap<>(); for (String element : pairs) { String[] splittedElement = StringUtils.split(element, "="); if (splittedElement == null) { continue; } result.put(splittedElement[0].trim(), splittedElement[1].trim()); } return result; }
@Override public boolean containsKey(Object key) { return (key instanceof String && this.caseInsensitiveKeys.containsKey(convertKey((String) key))); }
@Override protected boolean removeEldestEntry(Map.Entry<String, V> eldest) { boolean doRemove = LinkedCaseInsensitiveMap.this.removeEldestEntry(eldest); if (doRemove) { caseInsensitiveKeys.remove(convertKey(eldest.getKey())); } return doRemove; } };
@Test public void getOrDefault() { assertNull(map.put("key", "value1")); assertEquals("value1", map.put("KEY", "value2")); assertEquals("value2", map.put("Key", "value3")); assertEquals("value3", map.getOrDefault("key", "N")); assertEquals("value3", map.getOrDefault("KEY", "N")); assertEquals("value3", map.getOrDefault("Key", "N")); assertEquals("N", map.getOrDefault("keeeey", "N")); assertEquals("N", map.getOrDefault(new Object(), "N")); }
@Test public void putWithOverlappingKeys() { assertNull(map.put("key", "value1")); assertEquals("value1", map.put("KEY", "value2")); assertEquals("value2", map.put("Key", "value3")); assertEquals(1, map.size()); assertEquals("value3", map.get("key")); assertEquals("value3", map.get("KEY")); assertEquals("value3", map.get("Key")); assertTrue(map.containsKey("key")); assertTrue(map.containsKey("KEY")); assertTrue(map.containsKey("Key")); assertTrue(map.keySet().contains("key")); assertTrue(map.keySet().contains("KEY")); assertTrue(map.keySet().contains("Key")); }
@Test public void mapClone() { assertNull(map.put("key", "value1")); LinkedCaseInsensitiveMap<String> copy = map.clone(); assertEquals(map.getLocale(), copy.getLocale()); assertEquals("value1", map.get("key")); assertEquals("value1", map.get("KEY")); assertEquals("value1", map.get("Key")); assertEquals("value1", copy.get("key")); assertEquals("value1", copy.get("KEY")); assertEquals("value1", copy.get("Key")); copy.put("Key", "value2"); assertEquals(1, map.size()); assertEquals(1, copy.size()); assertEquals("value1", map.get("key")); assertEquals("value1", map.get("KEY")); assertEquals("value1", map.get("Key")); assertEquals("value2", copy.get("key")); assertEquals("value2", copy.get("KEY")); assertEquals("value2", copy.get("Key")); }
@Test public void computeIfAbsentWithExistingValue() { assertNull(map.putIfAbsent("key", "value1")); assertEquals("value1", map.putIfAbsent("KEY", "value2")); assertEquals("value1", map.put("Key", "value3")); assertEquals("value3", map.computeIfAbsent("key", key -> "value1")); assertEquals("value3", map.computeIfAbsent("KEY", key -> "value2")); assertEquals("value3", map.computeIfAbsent("Key", key -> "value3")); }
@Override @Nullable public V put(String key, @Nullable V value) { String oldKey = this.caseInsensitiveKeys.put(convertKey(key), key); V oldKeyValue = null; if (oldKey != null && !oldKey.equals(key)) { oldKeyValue = this.targetMap.remove(oldKey); } V oldValue = this.targetMap.put(key, value); return (oldKeyValue != null ? oldKeyValue : oldValue); }
@Override public void putAll(Map<? extends String, ? extends V> map) { if (map.isEmpty()) { return; } for (Map.Entry<? extends String, ? extends V> entry : map.entrySet()) { put(entry.getKey(), entry.getValue()); } }
/** * Convert the given key to a case-insensitive key. * <p>The default implementation converts the key * to lower-case according to this Map's Locale. * @param key the user-specified key * @return the key to use for storing * @see String#toLowerCase(Locale) */ protected String convertKey(String key) { return key.toLowerCase(getLocale()); }
@Override public boolean containsKey(Object key) { return LinkedCaseInsensitiveMap.this.containsKey(key); } @Override
@Override public String[] getParameterValues(String name) { return params.get(name); } }
@Test public void putAndGet() { assertNull(map.put("key", "value1")); assertEquals("value1", map.put("key", "value2")); assertEquals("value2", map.put("key", "value3")); assertEquals(1, map.size()); assertEquals("value3", map.get("key")); assertEquals("value3", map.get("KEY")); assertEquals("value3", map.get("Key")); assertTrue(map.containsKey("key")); assertTrue(map.containsKey("KEY")); assertTrue(map.containsKey("Key")); assertTrue(map.keySet().contains("key")); assertTrue(map.keySet().contains("KEY")); assertTrue(map.keySet().contains("Key")); }
@Override protected boolean removeEldestEntry(Map.Entry<String, V> eldest) { boolean doRemove = LinkedCaseInsensitiveMap.this.removeEldestEntry(eldest); if (doRemove) { caseInsensitiveKeys.remove(convertKey(eldest.getKey())); } return doRemove; } };
@Test public void getOrDefaultWithNullValue() { assertNull(map.put("key", null)); assertNull(map.put("KEY", null)); assertNull(map.put("Key", null)); assertNull(map.getOrDefault("key", "N")); assertNull(map.getOrDefault("KEY", "N")); assertNull(map.getOrDefault("Key", "N")); assertEquals("N", map.getOrDefault("keeeey", "N")); assertEquals("N", map.getOrDefault(new Object(), "N")); }
@Override public void putAll(Map<? extends String, ? extends V> map) { if (map.isEmpty()) { return; } for (Map.Entry<? extends String, ? extends V> entry : map.entrySet()) { put(entry.getKey(), entry.getValue()); } }
/** * Convert the given key to a case-insensitive key. * <p>The default implementation converts the key * to lower-case according to this Map's Locale. * @param key the user-specified key * @return the key to use for storing * @see String#toLowerCase(Locale) */ protected String convertKey(String key) { return key.toLowerCase(getLocale()); }
@Override public boolean containsKey(Object key) { return LinkedCaseInsensitiveMap.this.containsKey(key); } @Override
@Override public String[] getParameterValues(String name) { return params.get(name); } }