Chris@2
|
1 /*
|
Chris@2
|
2 Copyright (C) 2001, 2006 by Simon Dixon
|
Chris@2
|
3
|
Chris@2
|
4 This program is free software; you can redistribute it and/or modify
|
Chris@2
|
5 it under the terms of the GNU General Public License as published by
|
Chris@2
|
6 the Free Software Foundation; either version 2 of the License, or
|
Chris@2
|
7 (at your option) any later version.
|
Chris@2
|
8
|
Chris@2
|
9 This program is distributed in the hope that it will be useful,
|
Chris@2
|
10 but WITHOUT ANY WARRANTY; without even the implied warranty of
|
Chris@2
|
11 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
Chris@2
|
12 GNU General Public License for more details.
|
Chris@2
|
13
|
Chris@2
|
14 You should have received a copy of the GNU General Public License along
|
Chris@2
|
15 with this program (the file gpl.txt); if not, download it from
|
Chris@2
|
16 http://www.gnu.org/licenses/gpl.txt or write to the
|
Chris@2
|
17 Free Software Foundation, Inc.,
|
Chris@2
|
18 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
|
Chris@2
|
19 */
|
Chris@2
|
20
|
Chris@2
|
21 package at.ofai.music.util;
|
Chris@2
|
22
|
Chris@2
|
23 import java.util.ArrayList;
|
Chris@2
|
24 import java.util.Collection;
|
Chris@2
|
25 import java.util.Map;
|
Chris@2
|
26 import java.util.Set;
|
Chris@2
|
27 import java.util.TreeSet;
|
Chris@2
|
28
|
Chris@2
|
29 // An implementation of the Map interface, backed by an ArrayList, which
|
Chris@2
|
30 // preserves the elements in the order that they are added to the map.
|
Chris@2
|
31 // Operations will take linear rather than constant time (as for the efficient
|
Chris@2
|
32 // implementations of Map). Operations are not synchronized; caveat programmer!
|
Chris@2
|
33 // Used by class Parameters
|
Chris@2
|
34 // Updated to use generics; demonstrates that generics do not necessarily make
|
Chris@2
|
35 // programs more readable, simple, safe, etc.
|
Chris@2
|
36 class ArrayMap implements Map<String,Object> {
|
Chris@2
|
37
|
Chris@2
|
38 protected ArrayList<Entry> entries;
|
Chris@2
|
39
|
Chris@2
|
40 protected class Entry implements Map.Entry<String,Object>,
|
Chris@2
|
41 Comparable<Object> {
|
Chris@2
|
42 protected String key;
|
Chris@2
|
43 protected Object value;
|
Chris@2
|
44 protected Entry(String k, Object v) {
|
Chris@2
|
45 key = k;
|
Chris@2
|
46 value = v;
|
Chris@2
|
47 } // constructor
|
Chris@2
|
48 public boolean equals(Object o) {
|
Chris@2
|
49 return (o instanceof Entry) && key.equals(((Entry)o).key) &&
|
Chris@2
|
50 value.equals(((Entry)o).value);
|
Chris@2
|
51 } // equals()
|
Chris@2
|
52 public String getKey() { return key; }
|
Chris@2
|
53 public Object getValue() { return value; }
|
Chris@2
|
54 public Object setValue(Object newValue) {
|
Chris@2
|
55 Object oldValue = value;
|
Chris@2
|
56 value = newValue;
|
Chris@2
|
57 return oldValue;
|
Chris@2
|
58 } // setValue()
|
Chris@2
|
59 public int hashCode() {
|
Chris@2
|
60 return (key==null? 0 : key.hashCode()) ^
|
Chris@2
|
61 (value==null? 0 : value.hashCode());
|
Chris@2
|
62 } // hashCode()
|
Chris@2
|
63 public int compareTo(Object o) {
|
Chris@2
|
64 return key.compareTo(((Entry)o).key);
|
Chris@2
|
65 } // compareTo()
|
Chris@2
|
66 } // inner class Entry
|
Chris@2
|
67
|
Chris@2
|
68 public ArrayMap() { entries = new ArrayList<Entry>(); }//default constructor
|
Chris@2
|
69 public ArrayMap(Map<String,Object> m) { this(); putAll(m); } // copy constructor
|
Chris@2
|
70
|
Chris@2
|
71 // Returns the index of an entry, given its key, or -1 if it is not in map.
|
Chris@2
|
72 // Note that ArrayList.indexOf() can't be used, because it doesn't call
|
Chris@2
|
73 // ArrayMap$Entry.equals() [bug?? or does it call key.equals(entry)??]
|
Chris@2
|
74 public int indexOf(String key) {
|
Chris@2
|
75 for (int i = 0; i < size(); i++)
|
Chris@2
|
76 if (key.equals(entries.get(i).key))
|
Chris@2
|
77 return i;
|
Chris@2
|
78 return -1;
|
Chris@2
|
79 } // indexOf()
|
Chris@2
|
80
|
Chris@2
|
81 // Returns the map entry at the given index
|
Chris@2
|
82 public Entry getEntry(int i) { return entries.get(i); }
|
Chris@2
|
83
|
Chris@2
|
84 // Removes all mappings from this map (optional operation).
|
Chris@2
|
85 public void clear() { entries.clear(); }
|
Chris@2
|
86
|
Chris@2
|
87 // Returns true if this map contains a mapping for the specified key.
|
Chris@2
|
88 public boolean containsKey(Object key) {
|
Chris@2
|
89 return indexOf((String)key) >= 0;
|
Chris@2
|
90 } // containsKey()
|
Chris@2
|
91
|
Chris@2
|
92 // Returns true if this map maps one or more keys to the specified value.
|
Chris@2
|
93 public boolean containsValue(Object value) {
|
Chris@2
|
94 for (int i = 0; i < size(); i++)
|
Chris@2
|
95 if (value.equals(entries.get(i).value))
|
Chris@2
|
96 return true;
|
Chris@2
|
97 return false;
|
Chris@2
|
98 } // containsValue()
|
Chris@2
|
99
|
Chris@2
|
100 // Returns a set view of the mappings contained in this map.
|
Chris@2
|
101 public Set<Map.Entry<String,Object>> entrySet() {
|
Chris@2
|
102 TreeSet<Map.Entry<String,Object>> s =
|
Chris@2
|
103 new TreeSet<Map.Entry<String,Object>>();
|
Chris@2
|
104 for (int i = 0; i < size(); i++)
|
Chris@2
|
105 s.add(entries.get(i));
|
Chris@2
|
106 return s;
|
Chris@2
|
107 } // entrySet()
|
Chris@2
|
108
|
Chris@2
|
109 // Compares the specified object with this map for equality.
|
Chris@2
|
110 public boolean equals(Object o) { return (o == this); }
|
Chris@2
|
111
|
Chris@2
|
112 // Returns the value to which this map maps the specified key.
|
Chris@2
|
113 public Object get(Object key) {
|
Chris@2
|
114 int i = indexOf((String)key);
|
Chris@2
|
115 if (i == -1)
|
Chris@2
|
116 return null;
|
Chris@2
|
117 return entries.get(i).value;
|
Chris@2
|
118 } // get()
|
Chris@2
|
119
|
Chris@2
|
120 // Returns the hash code value for this map.
|
Chris@2
|
121 public int hashCode() {
|
Chris@2
|
122 int h = 0;
|
Chris@2
|
123 for (int i = 0; i < size(); i++)
|
Chris@2
|
124 h ^= entries.get(i).hashCode();
|
Chris@2
|
125 return h;
|
Chris@2
|
126 } // hashCode()
|
Chris@2
|
127
|
Chris@2
|
128 // Returns true if this map contains no key-value mappings.
|
Chris@2
|
129 public boolean isEmpty() { return entries.isEmpty(); }
|
Chris@2
|
130
|
Chris@2
|
131 // Returns a set view of the keys contained in this map.
|
Chris@2
|
132 public Set<String> keySet() {
|
Chris@2
|
133 TreeSet<String> s = new TreeSet<String>();
|
Chris@2
|
134 for (int i = 0; i < size(); i++)
|
Chris@2
|
135 s.add(entries.get(i).key);
|
Chris@2
|
136 return s;
|
Chris@2
|
137 } // keySet()
|
Chris@2
|
138
|
Chris@2
|
139 // Associates the specified value with the specified key in this map
|
Chris@2
|
140 public Object put(String key, Object value) {
|
Chris@2
|
141 int i = indexOf(key);
|
Chris@2
|
142 if (i < 0) {
|
Chris@2
|
143 entries.add(new Entry(key, value));
|
Chris@2
|
144 return null;
|
Chris@2
|
145 } else
|
Chris@2
|
146 return entries.get(i).setValue(value);
|
Chris@2
|
147 } // put()
|
Chris@2
|
148
|
Chris@2
|
149 // Copies all of the mappings from the specified map to this map
|
Chris@2
|
150 public void putAll(Map m) {
|
Chris@2
|
151 // The following warning seems to be unavoidable:
|
Chris@2
|
152 // warning: [unchecked] unchecked conversion
|
Chris@2
|
153 Map<String,Object> m1 = (Map<String,Object>)m;
|
Chris@2
|
154 for (Map.Entry<String,Object> me : m1.entrySet()) {
|
Chris@2
|
155 put(me.getKey(), me.getValue());
|
Chris@2
|
156 }
|
Chris@2
|
157 } // putAll()
|
Chris@2
|
158
|
Chris@2
|
159 // Removes the mapping for this key from this map if present
|
Chris@2
|
160 public Object remove(Object key) {
|
Chris@2
|
161 int i = indexOf((String)key);
|
Chris@2
|
162 if (i < 0)
|
Chris@2
|
163 return null;
|
Chris@2
|
164 return entries.remove(i);
|
Chris@2
|
165 } // remove()
|
Chris@2
|
166
|
Chris@2
|
167 // Returns the number of key-value mappings in this map.
|
Chris@2
|
168 public int size() { return entries.size(); }
|
Chris@2
|
169
|
Chris@2
|
170 // Returns a collection view of the values contained in this map.
|
Chris@2
|
171 public Collection<Object> values() {
|
Chris@2
|
172 ArrayList<Object> s = new ArrayList<Object>();
|
Chris@2
|
173 for (int i = 0; i < size(); i++)
|
Chris@2
|
174 s.add(entries.get(i).value);
|
Chris@2
|
175 return s;
|
Chris@2
|
176 } // values()
|
Chris@2
|
177
|
Chris@2
|
178 } // class ArrayMap
|