1 | |
package org.kuali.rice.core.api.mo.common; |
2 | |
|
3 | |
import org.apache.commons.lang.builder.EqualsBuilder; |
4 | |
import org.apache.commons.lang.builder.HashCodeBuilder; |
5 | |
import org.apache.commons.lang.builder.ToStringBuilder; |
6 | |
import org.kuali.rice.core.util.ConcreteKeyValue; |
7 | |
import org.kuali.rice.core.util.KeyValue; |
8 | |
import org.kuali.rice.core.util.jaxb.StringMapEntry; |
9 | |
import org.kuali.rice.core.util.jaxb.StringMapEntryList; |
10 | |
|
11 | |
import javax.xml.bind.annotation.XmlRootElement; |
12 | |
import javax.xml.bind.annotation.adapters.XmlAdapter; |
13 | |
import javax.xml.bind.annotation.adapters.XmlJavaTypeAdapter; |
14 | |
import java.io.IOException; |
15 | |
import java.io.ObjectInputStream; |
16 | |
import java.io.Serializable; |
17 | |
import java.util.AbstractMap; |
18 | |
import java.util.ArrayList; |
19 | |
import java.util.Collection; |
20 | |
import java.util.Collections; |
21 | |
import java.util.HashMap; |
22 | |
import java.util.HashSet; |
23 | |
import java.util.List; |
24 | |
import java.util.Map; |
25 | |
import java.util.Set; |
26 | |
|
27 | |
|
28 | |
|
29 | |
|
30 | |
|
31 | |
@XmlRootElement |
32 | |
@XmlJavaTypeAdapter(Attributes.Adapter.class) |
33 | 5 | public final class Attributes implements Serializable { |
34 | |
|
35 | |
private static final long serialVersionUID = -2804341886674598357L; |
36 | |
|
37 | 1 | private static final Attributes EMPTY = new Attributes(Collections.<String, String>emptyMap()); |
38 | |
|
39 | |
private final Map<String, String> keyValues; |
40 | |
|
41 | |
|
42 | 14 | private transient Object lock = new Object(); |
43 | |
private transient Set<Map.Entry<String, String>> entrySetCache; |
44 | |
|
45 | |
|
46 | |
|
47 | |
|
48 | |
@SuppressWarnings("unused") |
49 | 0 | private Attributes() { |
50 | 0 | this.keyValues = null; |
51 | 0 | } |
52 | |
|
53 | 14 | private Attributes(final Map<String, String> map) { |
54 | 14 | this.keyValues = new HashMap<String, String>(map); |
55 | 14 | } |
56 | |
|
57 | |
|
58 | |
|
59 | |
|
60 | |
|
61 | |
|
62 | |
public static Attributes empty() { |
63 | 10 | return EMPTY; |
64 | |
} |
65 | |
|
66 | |
|
67 | |
|
68 | |
|
69 | |
|
70 | |
|
71 | |
|
72 | |
public static Attributes fromMap(Map<String, String> map) { |
73 | 13 | if (map == null) { |
74 | 1 | return empty(); |
75 | |
} |
76 | |
|
77 | 12 | if (map.isEmpty()) { |
78 | 1 | return empty(); |
79 | |
} |
80 | |
|
81 | 11 | return new Attributes(map); |
82 | |
} |
83 | |
|
84 | |
|
85 | |
|
86 | |
|
87 | |
|
88 | |
|
89 | |
|
90 | |
public static Attributes fromMapEntry(Map.Entry<String, String> entry) { |
91 | 3 | if (entry == null) { |
92 | 1 | return empty(); |
93 | |
} |
94 | |
|
95 | 2 | if (entry.getKey() == null) { |
96 | 1 | throw new IllegalArgumentException("entry.key is null"); |
97 | |
} |
98 | |
|
99 | 1 | return fromMap(Collections.singletonMap(entry.getKey(), entry.getValue())); |
100 | |
} |
101 | |
|
102 | |
|
103 | |
|
104 | |
|
105 | |
|
106 | |
|
107 | |
|
108 | |
public static Attributes fromStrings(String key, String value) { |
109 | 2 | if (key == null) { |
110 | 1 | throw new IllegalArgumentException("key is null"); |
111 | |
} |
112 | |
|
113 | 1 | return fromMap(Collections.singletonMap(key, value)); |
114 | |
} |
115 | |
|
116 | |
|
117 | |
|
118 | |
|
119 | |
|
120 | |
|
121 | |
|
122 | |
public static Attributes fromKeyValue(KeyValue keyValue) { |
123 | 3 | if (keyValue == null) { |
124 | 1 | return empty(); |
125 | |
} |
126 | |
|
127 | 2 | if (keyValue.getKey() == null) { |
128 | 1 | throw new IllegalArgumentException("keyValue.key is null"); |
129 | |
} |
130 | |
|
131 | 1 | return fromMap(Collections.singletonMap(keyValue.getKey(), keyValue.getValue())); |
132 | |
} |
133 | |
|
134 | |
|
135 | |
|
136 | |
|
137 | |
|
138 | |
|
139 | |
|
140 | |
public static Attributes fromKeyValues(Collection<? extends KeyValue> keyValues) { |
141 | 0 | if (keyValues == null) { |
142 | 0 | return empty(); |
143 | |
} |
144 | 0 | final Map<String, String> pairs = new HashMap<String, String>(); |
145 | 0 | for (KeyValue keyValue : keyValues) { |
146 | 0 | if (keyValue == null) { |
147 | 0 | throw new IllegalArgumentException("keyValue is null"); |
148 | |
} |
149 | |
|
150 | 0 | if (keyValue.getKey() == null) { |
151 | 0 | throw new IllegalArgumentException("keyValue.key is null"); |
152 | |
} |
153 | |
|
154 | 0 | pairs.put(keyValue.getKey(), keyValue.getValue()); |
155 | |
} |
156 | 0 | return fromMap(pairs); |
157 | |
} |
158 | |
|
159 | |
|
160 | |
|
161 | |
|
162 | |
|
163 | |
|
164 | |
|
165 | |
public Map<String, String> toMap() { |
166 | 2 | return new HashMap<String, String>(keyValues); |
167 | |
} |
168 | |
|
169 | |
|
170 | |
|
171 | |
|
172 | |
|
173 | |
public List<KeyValue> toKeyValues() { |
174 | 0 | final List<KeyValue> kv = new ArrayList<KeyValue>(); |
175 | 0 | for (Map.Entry<String, String> entry : keyValues.entrySet()) { |
176 | 0 | kv.add(new ConcreteKeyValue(entry)); |
177 | |
} |
178 | 0 | return kv; |
179 | |
} |
180 | |
|
181 | |
|
182 | |
|
183 | |
|
184 | |
|
185 | |
|
186 | |
|
187 | |
public int size() { |
188 | 0 | return keyValues.size(); |
189 | |
} |
190 | |
|
191 | |
|
192 | |
|
193 | |
|
194 | |
|
195 | |
|
196 | |
public boolean isEmpty() { |
197 | 0 | return keyValues.isEmpty(); |
198 | |
} |
199 | |
|
200 | |
|
201 | |
|
202 | |
|
203 | |
|
204 | |
|
205 | |
|
206 | |
|
207 | |
public boolean containsKey(String key) { |
208 | 1 | validateKey(key); |
209 | 1 | return keyValues.containsKey(key); |
210 | |
} |
211 | |
|
212 | |
|
213 | |
|
214 | |
|
215 | |
|
216 | |
|
217 | |
|
218 | |
public boolean containsValue(String value) { |
219 | 0 | return keyValues.containsValue(value); |
220 | |
} |
221 | |
|
222 | |
|
223 | |
|
224 | |
|
225 | |
|
226 | |
|
227 | |
|
228 | |
public String get(String key) { |
229 | 0 | validateKey(key); |
230 | 0 | return keyValues.get(key); |
231 | |
} |
232 | |
|
233 | |
|
234 | |
|
235 | |
|
236 | |
|
237 | |
|
238 | |
public Set<String> keySet() { |
239 | 0 | return keyValues.keySet(); |
240 | |
} |
241 | |
|
242 | |
|
243 | |
|
244 | |
|
245 | |
|
246 | |
|
247 | |
public Collection<String> values() { |
248 | 0 | return keyValues.values(); |
249 | |
} |
250 | |
|
251 | |
|
252 | |
|
253 | |
|
254 | |
|
255 | |
|
256 | |
public Set<Map.Entry<String, String>> entrySet() { |
257 | |
|
258 | |
|
259 | 6 | synchronized (lock) { |
260 | 6 | if (entrySetCache == null) { |
261 | 6 | final Set<Map.Entry<String, String>> temp = new HashSet<Map.Entry<String, String>>(); |
262 | 6 | for (Map.Entry<String, String> e : keyValues.entrySet()) { |
263 | 6 | if (e != null) { |
264 | 6 | temp.add(new AbstractMap.SimpleImmutableEntry<String, String>(e.getKey(), e.getValue())); |
265 | |
} |
266 | |
} |
267 | 6 | entrySetCache = Collections.unmodifiableSet(temp); |
268 | |
} |
269 | 6 | } |
270 | 6 | return entrySetCache; |
271 | |
} |
272 | |
|
273 | |
private static void validateKey(String key) { |
274 | 1 | if (key == null) { |
275 | 0 | throw new IllegalArgumentException("key is null"); |
276 | |
} |
277 | 1 | } |
278 | |
|
279 | |
@Override |
280 | |
public int hashCode() { |
281 | 0 | return HashCodeBuilder.reflectionHashCode(this, Constants.HASH_CODE_EQUALS_EXCLUDE); |
282 | |
} |
283 | |
|
284 | |
@Override |
285 | |
public boolean equals(Object obj) { |
286 | 6 | return EqualsBuilder.reflectionEquals(obj, this, Constants.HASH_CODE_EQUALS_EXCLUDE); |
287 | |
} |
288 | |
|
289 | |
@Override |
290 | |
public String toString() { |
291 | 0 | return ToStringBuilder.reflectionToString(this); |
292 | |
} |
293 | |
|
294 | |
|
295 | |
private void readObject(ObjectInputStream in) throws IOException, ClassNotFoundException { |
296 | 1 | in.defaultReadObject(); |
297 | 1 | lock = new Object(); |
298 | 1 | } |
299 | |
|
300 | |
|
301 | |
|
302 | |
|
303 | 0 | static class Constants { |
304 | 1 | final static String[] HASH_CODE_EQUALS_EXCLUDE = {"entrySetCache", "lock"}; |
305 | |
} |
306 | |
|
307 | 5 | public static class Adapter extends XmlAdapter<StringMapEntryList, Attributes> { |
308 | |
|
309 | |
@Override |
310 | |
public StringMapEntryList marshal(Attributes attributes) throws Exception { |
311 | 1 | if (attributes == null || attributes.keyValues == null) { |
312 | 0 | return null; |
313 | |
} |
314 | 1 | List<StringMapEntry> entries = new ArrayList<StringMapEntry>(attributes.keyValues.size()); |
315 | 1 | for (Map.Entry<String, String> entry : attributes.keyValues.entrySet()) { |
316 | 1 | entries.add(new StringMapEntry(entry)); |
317 | |
} |
318 | 1 | return new StringMapEntryList(entries); |
319 | |
} |
320 | |
|
321 | |
@Override |
322 | |
public Attributes unmarshal(StringMapEntryList entries) throws Exception { |
323 | 2 | if (entries == null || entries.getEntries() == null) { |
324 | 0 | return null; |
325 | |
} |
326 | 2 | Map<String, String> resultMap = new HashMap<String, String>(); |
327 | 2 | for (StringMapEntry entry : entries.getEntries()) { |
328 | 2 | resultMap.put(entry.getKey(), entry.getValue()); |
329 | |
} |
330 | 2 | return new Attributes(resultMap); |
331 | |
} |
332 | |
|
333 | |
} |
334 | |
|
335 | |
} |