1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20 package com.cosylab.util;
21
22 import java.util.AbstractCollection;
23 import java.util.AbstractSet;
24 import java.util.Collection;
25 import java.util.Iterator;
26 import java.util.Map;
27 import java.util.Set;
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67 public class NameValueList implements Map
68 {
69 private String[] names = null;
70 private Object[] values = null;
71 private int ix = 0;
72 private KeySet keySet = new KeySet();
73 private EntrySet entrySet = new EntrySet();
74 private ValueCollection valueCollection = new ValueCollection();
75 private static final int DEFAULT_CAPACITY = 10;
76
77 private class EntrySet extends AbstractSet
78 {
79
80
81
82
83
84 public Iterator iterator()
85 {
86 return new EntryIterator();
87 }
88
89
90
91
92
93
94 public int size()
95 {
96 return NameValueList.this.size();
97 }
98 }
99
100 private class EntryIterator implements Iterator
101 {
102 private class Entry implements Map.Entry
103 {
104 private int ix = 0;
105
106
107
108
109
110
111 public Entry(int ix)
112 {
113 this.ix = ix;
114 }
115
116
117
118
119
120
121 public Object getValue()
122 {
123 return values[ix];
124 }
125
126
127
128
129
130
131
132
133 public Object setValue(Object value)
134 {
135 Object retVal = values[ix];
136 values[ix] = value;
137
138 return retVal;
139 }
140
141
142
143
144
145
146 public Object getKey()
147 {
148 return names[ix];
149 }
150 }
151
152 private int ix = 0;
153
154
155
156
157
158
159 public boolean hasNext()
160 {
161 if (ix < NameValueList.this.ix) {
162 return true;
163 } else {
164 return false;
165 }
166 }
167
168
169
170
171
172
173 public Object next()
174 {
175 Entry retVal = new Entry(ix);
176 ix++;
177
178 return retVal;
179 }
180
181
182
183
184 public void remove()
185 {
186 NameValueList.this.remove(names[ix]);
187 }
188 }
189
190 private class KeySet extends AbstractSet
191 {
192
193
194
195
196
197 public Iterator iterator()
198 {
199 return new KeyIterator();
200 }
201
202
203
204
205
206
207 public int size()
208 {
209 return NameValueList.this.size();
210 }
211 }
212
213 private class KeyIterator implements Iterator
214 {
215 private int ix = 0;
216
217
218
219
220
221
222 public boolean hasNext()
223 {
224 return (ix < NameValueList.this.ix);
225 }
226
227
228
229
230
231
232 public Object next()
233 {
234 Object retVal = names[ix];
235 ix++;
236
237 return retVal;
238 }
239
240
241
242
243 public void remove()
244 {
245 NameValueList.this.remove(names[ix]);
246 }
247 }
248
249 private class CollectionIterator implements Iterator
250 {
251 private int ix = 0;
252
253
254
255
256
257
258 public boolean hasNext()
259 {
260 return (ix < NameValueList.this.ix);
261 }
262
263
264
265
266 public void remove()
267 {
268 NameValueList.this.remove(names[ix]);
269 }
270
271
272
273
274
275
276 public Object next()
277 {
278 Object retVal = values[ix];
279 ix++;
280
281 return retVal;
282 }
283 }
284
285 private class ValueCollection extends AbstractCollection
286 {
287
288
289
290
291
292 public Iterator iterator()
293 {
294 return new CollectionIterator();
295 }
296
297
298
299
300
301
302 public int size()
303 {
304 return NameValueList.this.size();
305 }
306 }
307
308
309
310
311
312 public NameValueList()
313 {
314 this(DEFAULT_CAPACITY);
315 }
316
317
318
319
320
321
322
323
324 public NameValueList(int initialCapacity)
325 {
326 assert (initialCapacity > 0);
327 names = new String[initialCapacity];
328 values = new Object[initialCapacity];
329 }
330
331
332
333
334
335
336 public synchronized int size()
337 {
338 return ix;
339 }
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354 public synchronized Object put(Object name, Object value)
355 {
356 assert (name != null);
357
358 if (!(name instanceof String)) {
359 throw new ClassCastException("name !instanceof String");
360 }
361
362 String cast = (String)name;
363
364 int index = find(cast);
365
366 if (index != -1) {
367 Object retVal = values[index];
368 values[index] = value;
369
370 return retVal;
371 }
372
373 if (ix < names.length) {
374 names[ix] = cast;
375 values[ix] = value;
376 ix++;
377
378 return null;
379 } else {
380 resizeUp();
381
382 return put(cast, value);
383 }
384 }
385
386
387
388
389
390
391
392
393
394
395
396
397
398 public synchronized Object remove(Object name)
399 {
400 assert (name != null);
401
402 if (!(name instanceof String)) {
403 throw new ClassCastException("name !instanceof String");
404 }
405
406 int ix = find((String)name);
407
408 if (ix == -1) {
409 return null;
410 }
411
412 Object retVal = values[ix];
413 String[] newNames = new String[names.length - 1];
414 Object[] newValues = new Object[names.length - 1];
415 System.arraycopy(names, 0, newNames, 0, ix);
416 System.arraycopy(values, 0, newValues, 0, ix);
417 System.arraycopy(names, ix + 1, newNames, ix, names.length - ix - 1);
418 System.arraycopy(values, ix + 1, newValues, ix, names.length - ix - 1);
419 values = newValues;
420 names = newNames;
421 this.ix--;
422
423 return retVal;
424 }
425
426
427
428
429
430
431
432
433
434
435
436
437 public synchronized Object get(Object name)
438 {
439 if (!(name instanceof String)) {
440 throw new ClassCastException("name !instanceof String");
441 }
442
443 assert (name != null);
444
445 int ix = find((String)name);
446
447 if (ix == -1) {
448 return null;
449 }
450
451 return values[ix];
452 }
453
454
455
456
457
458
459
460
461 public synchronized String[] getNames()
462 {
463 String[] array = new String[ix];
464 System.arraycopy(names, 0, array, 0, ix);
465
466 return array;
467 }
468
469 private synchronized int find(String name)
470 {
471 assert (name != null);
472
473 for (int i = 0; i < ix; i++) {
474 if (names[i] != null && names[i].equals(name)) {
475 return i;
476 }
477 }
478
479 return -1;
480 }
481
482 private synchronized void resizeUp()
483 {
484 if (ix == names.length) {
485 String[] newNames = new String[names.length + DEFAULT_CAPACITY];
486 Object[] newValues = new Object[names.length + DEFAULT_CAPACITY];
487 System.arraycopy(names, 0, newNames, 0, names.length);
488 System.arraycopy(values, 0, newValues, 0, names.length);
489 names = newNames;
490 values = newValues;
491 }
492 }
493
494
495
496
497
498
499
500 public synchronized void clear()
501 {
502 for (int i = 0; i < names.length; i++) {
503 names[i] = null;
504 values[i] = null;
505 }
506
507 ix = 0;
508 }
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523 public synchronized boolean containsKey(Object name)
524 {
525 if (name == null) {
526 throw new NullPointerException("name");
527 }
528
529 if (find((String)name) == -1) {
530 return false;
531 } else {
532 return true;
533 }
534 }
535
536
537
538
539
540
541
542
543
544
545
546 public synchronized boolean containsValue(Object value)
547 {
548 for (int i = 0; i < values.length; i++) {
549 if (value == null && values[i] == null) {
550 return true;
551 }
552
553 if (value != null && values[i] != null && value.equals(values[i])) {
554 return true;
555 }
556 }
557
558 return false;
559 }
560
561
562
563
564
565
566
567
568
569 public Set entrySet()
570 {
571 return entrySet;
572 }
573
574
575
576
577
578
579
580
581
582 public boolean isEmpty()
583 {
584 return (ix == 0);
585 }
586
587
588
589
590
591
592
593
594 public Set keySet()
595 {
596 return keySet;
597 }
598
599
600
601
602
603
604
605
606 public synchronized void putAll(Map t)
607 {
608 Iterator it = t.entrySet().iterator();
609
610 while (it.hasNext()) {
611 Entry e = (Entry)it.next();
612 put(e.getKey(), e.getValue());
613 }
614 }
615
616
617
618
619
620
621
622
623 public Collection values()
624 {
625 return valueCollection;
626 }
627
628
629
630
631
632
633
634 public String toString()
635 {
636 StringBuffer sb = new StringBuffer(1000);
637 sb.append('{');
638
639 for (int i = 0; i < size(); i++) {
640 sb.append(' ');
641 sb.append(names[i]);
642 sb.append('=');
643 sb.append(values[i]);
644 }
645
646 sb.append(" }");
647
648 return new String(sb);
649 }
650 }
651
652