1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19 package org.eclipse.jetty.util;
20
21 import java.util.Arrays;
22 import java.util.Collections;
23 import java.util.Iterator;
24 import java.util.LinkedHashMap;
25 import java.util.LinkedHashSet;
26 import java.util.Locale;
27 import java.util.Map;
28 import java.util.Set;
29
30
31
32
33
34
35
36
37 public class Fields implements Iterable<Fields.Field>
38 {
39 private final boolean caseSensitive;
40 private final Map<String, Field> fields;
41
42
43
44
45
46 public Fields()
47 {
48 this(false);
49 }
50
51
52
53
54
55
56 public Fields(boolean caseSensitive)
57 {
58 this.caseSensitive = caseSensitive;
59 fields = new LinkedHashMap<>();
60 }
61
62
63
64
65
66
67
68
69 public Fields(Fields original, boolean immutable)
70 {
71 this.caseSensitive = original.caseSensitive;
72 Map<String, Field> copy = new LinkedHashMap<>();
73 copy.putAll(original.fields);
74 fields = immutable ? Collections.unmodifiableMap(copy) : copy;
75 }
76
77 @Override
78 public boolean equals(Object obj)
79 {
80 if (this == obj)
81 return true;
82 if (obj == null || getClass() != obj.getClass())
83 return false;
84 Fields that = (Fields)obj;
85 if (size() != that.size())
86 return false;
87 if (caseSensitive != that.caseSensitive)
88 return false;
89 for (Map.Entry<String, Field> entry : fields.entrySet())
90 {
91 String name = entry.getKey();
92 Field value = entry.getValue();
93 if (!value.equals(that.get(name), caseSensitive))
94 return false;
95 }
96 return true;
97 }
98
99 @Override
100 public int hashCode()
101 {
102 return fields.hashCode();
103 }
104
105
106
107
108 public Set<String> names()
109 {
110 Set<String> result = new LinkedHashSet<>();
111 for (Field field : fields.values())
112 result.add(field.name());
113 return result;
114 }
115
116 private String normalizeName(String name)
117 {
118 return caseSensitive ? name : name.toLowerCase(Locale.ENGLISH);
119 }
120
121
122
123
124
125 public Field get(String name)
126 {
127 return fields.get(normalizeName(name));
128 }
129
130
131
132
133
134
135
136 public void put(String name, String value)
137 {
138
139 Field field = new Field(name, value);
140 fields.put(normalizeName(name), field);
141 }
142
143
144
145
146
147
148 public void put(Field field)
149 {
150 if (field != null)
151 fields.put(normalizeName(field.name()), field);
152 }
153
154
155
156
157
158
159
160
161 public void add(String name, String value)
162 {
163 String key = normalizeName(name);
164 Field field = fields.get(key);
165 if (field == null)
166 {
167
168 field = new Field(name, value);
169 fields.put(key, field);
170 }
171 else
172 {
173 field = new Field(field.name(), field.values(), value);
174 fields.put(key, field);
175 }
176 }
177
178
179
180
181
182
183
184 public Field remove(String name)
185 {
186 return fields.remove(normalizeName(name));
187 }
188
189
190
191
192
193 public void clear()
194 {
195 fields.clear();
196 }
197
198
199
200
201 public boolean isEmpty()
202 {
203 return fields.isEmpty();
204 }
205
206
207
208
209 public int size()
210 {
211 return fields.size();
212 }
213
214
215
216
217 @Override
218 public Iterator<Field> iterator()
219 {
220 return fields.values().iterator();
221 }
222
223 @Override
224 public String toString()
225 {
226 return fields.toString();
227 }
228
229
230
231
232
233 public static class Field
234 {
235 private final String name;
236 private final String[] values;
237
238 private Field(String name, String value)
239 {
240 this(name, new String[]{value});
241 }
242
243 private Field(String name, String[] values, String... moreValues)
244 {
245 this.name = name;
246 this.values = new String[values.length + moreValues.length];
247 System.arraycopy(values, 0, this.values, 0, values.length);
248 System.arraycopy(moreValues, 0, this.values, values.length, moreValues.length);
249 }
250
251 public boolean equals(Field that, boolean caseSensitive)
252 {
253 if (this == that)
254 return true;
255 if (that == null)
256 return false;
257 if (caseSensitive)
258 return equals(that);
259 return name.equalsIgnoreCase(that.name) && Arrays.equals(values, that.values);
260 }
261
262 @Override
263 public boolean equals(Object obj)
264 {
265 if (this == obj)
266 return true;
267 if (obj == null || getClass() != obj.getClass())
268 return false;
269 Field that = (Field)obj;
270 return name.equals(that.name) && Arrays.equals(values, that.values);
271 }
272
273 @Override
274 public int hashCode()
275 {
276 int result = name.hashCode();
277 result = 31 * result + Arrays.hashCode(values);
278 return result;
279 }
280
281
282
283
284 public String name()
285 {
286 return name;
287 }
288
289
290
291
292 public String value()
293 {
294 return values[0];
295 }
296
297
298
299
300
301
302
303
304
305 public Integer valueAsInt()
306 {
307 final String value = value();
308 return value == null ? null : Integer.valueOf(value);
309 }
310
311
312
313
314 public String[] values()
315 {
316 return values;
317 }
318
319
320
321
322 public boolean hasMultipleValues()
323 {
324 return values.length > 1;
325 }
326
327 @Override
328 public String toString()
329 {
330 return Arrays.toString(values);
331 }
332 }
333 }