1 /*
2 * Copyright 2002-2012 the original author or authors.
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17 package com.foxinmy.weixin4j.util;
18
19 import java.util.HashMap;
20 import java.util.LinkedHashMap;
21 import java.util.Locale;
22 import java.util.Map;
23
24 /**
25 * {@link LinkedHashMap} variant that stores String keys in a case-insensitive
26 * manner, for example for key-based access in a results table.
27 *
28 * <p>
29 * Preserves the original order as well as the original casing of keys, while
30 * allowing for contains, get and remove calls with any case of key.
31 *
32 * <p>
33 * Does <i>not</i> support {@code null} keys.
34 *
35 * @author Juergen Hoeller
36 * @since 3.0
37 */
38 @SuppressWarnings("serial")
39 public class LinkedCaseInsensitiveMap<V> extends LinkedHashMap<String, V> {
40
41 private final Map<String, String> caseInsensitiveKeys;
42
43 private final Locale locale;
44
45 /**
46 * Create a new LinkedCaseInsensitiveMap for the default Locale.
47 *
48 * @see java.lang.String#toLowerCase()
49 */
50 public LinkedCaseInsensitiveMap() {
51 this(null);
52 }
53
54 /**
55 * Create a new LinkedCaseInsensitiveMap that stores lower-case keys
56 * according to the given Locale.
57 *
58 * @param locale
59 * the Locale to use for lower-case conversion
60 * @see java.lang.String#toLowerCase(java.util.Locale)
61 */
62 public LinkedCaseInsensitiveMap(Locale locale) {
63 super();
64 this.caseInsensitiveKeys = new HashMap<String, String>();
65 this.locale = (locale != null ? locale : Locale.getDefault());
66 }
67
68 /**
69 * Create a new LinkedCaseInsensitiveMap that wraps a {@link LinkedHashMap}
70 * with the given initial capacity and stores lower-case keys according to
71 * the default Locale.
72 *
73 * @param initialCapacity
74 * the initial capacity
75 * @see java.lang.String#toLowerCase()
76 */
77 public LinkedCaseInsensitiveMap(int initialCapacity) {
78 this(initialCapacity, null);
79 }
80
81 /**
82 * Create a new LinkedCaseInsensitiveMap that wraps a {@link LinkedHashMap}
83 * with the given initial capacity and stores lower-case keys according to
84 * the given Locale.
85 *
86 * @param initialCapacity
87 * the initial capacity
88 * @param locale
89 * the Locale to use for lower-case conversion
90 * @see java.lang.String#toLowerCase(java.util.Locale)
91 */
92 public LinkedCaseInsensitiveMap(int initialCapacity, Locale locale) {
93 super(initialCapacity);
94 this.caseInsensitiveKeys = new HashMap<String, String>(initialCapacity);
95 this.locale = (locale != null ? locale : Locale.getDefault());
96 }
97
98 @Override
99 public V put(String key, V value) {
100 String oldKey = this.caseInsensitiveKeys.put(convertKey(key), key);
101 if (oldKey != null && !oldKey.equals(key)) {
102 super.remove(oldKey);
103 }
104 return super.put(key, value);
105 }
106
107 @Override
108 public void putAll(Map<? extends String, ? extends V> map) {
109 if (map.isEmpty()) {
110 return;
111 }
112 for (Map.Entry<? extends String, ? extends V> entry : map.entrySet()) {
113 put(entry.getKey(), entry.getValue());
114 }
115 }
116
117 @Override
118 public boolean containsKey(Object key) {
119 return (key instanceof String && this.caseInsensitiveKeys
120 .containsKey(convertKey((String) key)));
121 }
122
123 @Override
124 public V get(Object key) {
125 if (key instanceof String) {
126 return super.get(this.caseInsensitiveKeys
127 .get(convertKey((String) key)));
128 } else {
129 return null;
130 }
131 }
132
133 @Override
134 public V remove(Object key) {
135 if (key instanceof String) {
136 return super.remove(this.caseInsensitiveKeys
137 .remove(convertKey((String) key)));
138 } else {
139 return null;
140 }
141 }
142
143 @Override
144 public void clear() {
145 this.caseInsensitiveKeys.clear();
146 super.clear();
147 }
148
149 /**
150 * Convert the given key to a case-insensitive key.
151 * <p>
152 * The default implementation converts the key to lower-case according to
153 * this Map's Locale.
154 *
155 * @param key
156 * the user-specified key
157 * @return the key to use for storing
158 * @see java.lang.String#toLowerCase(java.util.Locale)
159 */
160 protected String convertKey(String key) {
161 return key != null ? key.toLowerCase(this.locale) : null;
162 }
163
164 }