KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > eclipse > core > internal > resources > MarkerAttributeMap


1 /*******************************************************************************
2  * Copyright (c) 2000, 2005 IBM Corporation and others.
3  * All rights reserved. This program and the accompanying materials
4  * are made available under the terms of the Eclipse Public License v1.0
5  * which accompanies this distribution, and is available at
6  * http://www.eclipse.org/legal/epl-v10.html
7  *
8  * Contributors:
9  * IBM Corporation - initial API and implementation
10  *******************************************************************************/

11 package org.eclipse.core.internal.resources;
12
13 import java.util.*;
14 import org.eclipse.core.internal.utils.IStringPoolParticipant;
15 import org.eclipse.core.internal.utils.StringPool;
16
17 /**
18  * A specialized map implementation that is optimized for a
19  * small set of interned strings as keys. The provided keys
20  * MUST be instances of java.lang.String.
21  *
22  * Implemented as a single array that alternates keys and values.
23  */

24 public class MarkerAttributeMap implements Map, IStringPoolParticipant {
25     protected Object JavaDoc[] elements = null;
26     protected int count = 0;
27
28     // 8 attribute keys, 8 attribute values
29
protected static final int DEFAULT_SIZE = 16;
30     protected static final int GROW_SIZE = 10;
31
32     /**
33      * Creates a new marker attribute map of default size
34      */

35     public MarkerAttributeMap() {
36         super();
37     }
38
39     /**
40      * Creates a new marker attribute map.
41      * @param initialCapacity The initial number of elements that will fit in the map.
42      */

43     public MarkerAttributeMap(int initialCapacity) {
44         elements = new Object JavaDoc[Math.max(initialCapacity * 2, 0)];
45     }
46
47     /**
48      * Creates a new marker attribute map of default size
49      * @param map The entries in the given map will be added to the new map.
50      */

51     public MarkerAttributeMap(Map map) {
52         this(map.size());
53         putAll(map);
54     }
55
56     /* (non-Javadoc)
57      * @see Map#clear()
58      */

59     public void clear() {
60         elements = null;
61         count = 0;
62     }
63
64     /* (non-Javadoc)
65      * @see Map#containsKey(java.lang.Object)
66      */

67     public boolean containsKey(Object JavaDoc key) {
68         key = ((String JavaDoc) key).intern();
69         if (elements == null || count == 0)
70             return false;
71         for (int i = 0; i < elements.length; i = i + 2)
72             if (elements[i] == key)
73                 return true;
74         return false;
75     }
76
77     /* (non-Javadoc)
78      * @see Map#containsValue(java.lang.Object)
79      */

80     public boolean containsValue(Object JavaDoc value) {
81         if (elements == null || count == 0)
82             return false;
83         for (int i = 1; i < elements.length; i = i + 2)
84             if (elements[i] != null && elements[i].equals(value))
85                 return true;
86         return false;
87     }
88
89     /* (non-Javadoc)
90      * @see Map#entrySet()
91      * This implementation does not conform properly to the specification
92      * in the Map interface. The returned collection will not be bound to
93      * this map and will not remain in sync with this map.
94      */

95     public Set entrySet() {
96         return toHashMap().entrySet();
97     }
98
99     /* (non-Javadoc)
100      * @see Object#equals(java.lang.Object)
101      */

102     public boolean equals(Object JavaDoc o) {
103         if (!(o instanceof Map))
104             return false;
105         Map other = (Map) o;
106         //must be same size
107
if (count != other.size())
108             return false;
109
110         //keysets must be equal
111
if (!keySet().equals(other.keySet()))
112             return false;
113
114         //values for each key must be equal
115
for (int i = 0; i < elements.length; i = i + 2) {
116             if (elements[i] != null && (!elements[i + 1].equals(other.get(elements[i]))))
117                 return false;
118         }
119         return true;
120     }
121
122     /* (non-Javadoc)
123      * @see Map#get(java.lang.Object)
124      */

125     public Object JavaDoc get(Object JavaDoc key) {
126         key = ((String JavaDoc) key).intern();
127         if (elements == null || count == 0)
128             return null;
129         for (int i = 0; i < elements.length; i = i + 2)
130             if (elements[i] == key)
131                 return elements[i + 1];
132         return null;
133     }
134
135     /**
136      * The capacity of the map has been exceeded, grow the array by
137      * GROW_SIZE to accomodate more entries.
138      */

139     protected void grow() {
140         Object JavaDoc[] expanded = new Object JavaDoc[elements.length + GROW_SIZE];
141         System.arraycopy(elements, 0, expanded, 0, elements.length);
142         elements = expanded;
143     }
144
145     /* (non-Javadoc)
146      * @see Object#hashCode()
147      */

148     public int hashCode() {
149         int hash = 0;
150         for (int i = 0; i < elements.length; i = i + 2) {
151             if (elements[i] != null) {
152                 hash += elements[i].hashCode();
153             }
154         }
155         return hash;
156     }
157
158     /* (non-Javadoc)
159      * @see Map#isEmpty()
160      */

161     public boolean isEmpty() {
162         return count == 0;
163     }
164
165     /* (non-Javadoc)
166      * @see Map#keySet()
167      * This implementation does not conform properly to the specification
168      * in the Map interface. The returned collection will not be bound to
169      * this map and will not remain in sync with this map.
170      */

171     public Set keySet() {
172         Set result = new HashSet(size());
173         for (int i = 0; i < elements.length; i = i + 2) {
174             if (elements[i] != null) {
175                 result.add(elements[i]);
176             }
177         }
178         return result;
179     }
180
181     /* (non-Javadoc)
182      * @see Map#put(java.lang.Object, java.lang.Object)
183      */

184     public Object JavaDoc put(Object JavaDoc key, Object JavaDoc value) {
185         if (key == null)
186             throw new NullPointerException JavaDoc();
187         if (value == null)
188             return remove(key);
189         key = ((String JavaDoc) key).intern();
190
191         // handle the case where we don't have any attributes yet
192
if (elements == null)
193             elements = new Object JavaDoc[DEFAULT_SIZE];
194         if (count == 0) {
195             elements[0] = key;
196             elements[1] = value;
197             count++;
198             return null;
199         }
200
201         // replace existing value if it exists
202
for (int i = 0; i < elements.length; i = i + 2) {
203             if (elements[i] == key) {
204                 Object JavaDoc oldValue = elements[i + 1];
205                 elements[i + 1] = value;
206                 return oldValue;
207             }
208         }
209
210         // otherwise add it to the list of elements.
211
// grow if necessary
212
if (elements.length <= (count * 2))
213             grow();
214         for (int i = 0; i < elements.length; i = i + 2) {
215             if (elements[i] == null) {
216                 elements[i] = key;
217                 elements[i + 1] = value;
218                 count++;
219                 return null;
220             }
221         }
222         return null;
223     }
224
225     /* (non-Javadoc)
226      * @see Map#putAll(java.util.Map)
227      */

228     public void putAll(Map map) {
229         for (Iterator i = map.keySet().iterator(); i.hasNext();) {
230             Object JavaDoc key = i.next();
231             Object JavaDoc value = map.get(key);
232             put(key, value);
233         }
234     }
235
236     /* (non-Javadoc)
237      * @see Map#remove(java.lang.Object)
238      */

239     public Object JavaDoc remove(Object JavaDoc key) {
240         key = ((String JavaDoc) key).intern();
241         if (elements == null || count == 0)
242             return null;
243         for (int i = 0; i < elements.length; i = i + 2) {
244             if (elements[i] == key) {
245                 elements[i] = null;
246                 Object JavaDoc result = elements[i + 1];
247                 elements[i + 1] = null;
248                 count--;
249                 return result;
250             }
251         }
252         return null;
253     }
254
255     /* (non-Javadoc)
256      * @see Map#size()
257      */

258     public int size() {
259         return count;
260     }
261
262     /* (non-Javadoc
263      * Method declared on IStringPoolParticipant
264      */

265     public void shareStrings(StringPool set) {
266         //copy elements for thread safety
267
Object JavaDoc[] array = elements;
268         if (array == null)
269             return;
270         //don't share keys because they are already interned
271
for (int i = 1; i < array.length; i = i + 2) {
272             Object JavaDoc o = array[i];
273             if (o instanceof String JavaDoc)
274                 array[i] = set.add((String JavaDoc)o);
275             else if (o instanceof IStringPoolParticipant)
276                 ((IStringPoolParticipant)o).shareStrings(set);
277         }
278     }
279
280     /**
281      * Creates a new hash map with the same contents as this map.
282      */

283     private HashMap toHashMap() {
284         HashMap result = new HashMap(size());
285         for (int i = 0; i < elements.length; i = i + 2) {
286             if (elements[i] != null) {
287                 result.put(elements[i], elements[i + 1]);
288             }
289         }
290         return result;
291     }
292
293     /* (non-Javadoc)
294      * @see Map#values()
295      * This implementation does not conform properly to the specification
296      * in the Map interface. The returned collection will not be bound to
297      * this map and will not remain in sync with this map.
298      */

299     public Collection values() {
300         Set result = new HashSet(size());
301         for (int i = 1; i < elements.length; i = i + 2) {
302             if (elements[i] != null) {
303                 result.add(elements[i]);
304             }
305         }
306         return result;
307     }
308 }
309
Popular Tags