Mercurial > hg > truffle
comparison truffle/com.oracle.truffle.object/src/com/oracle/truffle/object/PropertyMap.java @ 22153:b59d06483580
PropertyMap refactoring
author | Andreas Woess <andreas.woess@oracle.com> |
---|---|
date | Mon, 14 Sep 2015 18:32:54 +0200 |
parents | 9c8c0937da41 |
children | dc83cc1f94f2 |
comparison
equal
deleted
inserted
replaced
22152:291574f3e498 | 22153:b59d06483580 |
---|---|
1 /* | 1 /* |
2 * Copyright (c) 2014, 2014, Oracle and/or its affiliates. All rights reserved. | 2 * Copyright (c) 2014, 2015, Oracle and/or its affiliates. All rights reserved. |
3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. | 3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. |
4 * | 4 * |
5 * This code is free software; you can redistribute it and/or modify it | 5 * This code is free software; you can redistribute it and/or modify it |
6 * under the terms of the GNU General Public License version 2 only, as | 6 * under the terms of the GNU General Public License version 2 only, as |
7 * published by the Free Software Foundation. | 7 * published by the Free Software Foundation. |
24 | 24 |
25 import java.util.*; | 25 import java.util.*; |
26 | 26 |
27 import com.oracle.truffle.api.object.*; | 27 import com.oracle.truffle.api.object.*; |
28 | 28 |
29 public final class PropertyMap implements Map<Object, Property> { | 29 /** |
30 private final PropertyMap car; | 30 * Immutable property map. |
31 private final Property cdr; | 31 */ |
32 private final int size; | 32 public abstract class PropertyMap implements ImmutableMap<Object, Property> { |
33 | 33 |
34 private static final PropertyMap EMPTY = new PropertyMap(); | 34 public static PropertyMap empty() { |
35 | 35 return ConsListPropertyMap.empty(); |
36 private PropertyMap() { | |
37 this.car = null; | |
38 this.cdr = null; | |
39 this.size = 0; | |
40 } | 36 } |
41 | 37 |
42 private PropertyMap(PropertyMap parent, Property added) { | 38 public abstract Iterator<Object> orderedKeyIterator(); |
43 this.car = Objects.requireNonNull(parent); | |
44 this.cdr = added; | |
45 this.size = parent.size + 1; | |
46 } | |
47 | 39 |
48 public static PropertyMap empty() { | 40 public abstract Iterator<Object> reverseOrderedKeyIterator(); |
49 return EMPTY; | |
50 } | |
51 | 41 |
52 public int size() { | 42 public abstract Iterator<Property> orderedValueIterator(); |
53 return size; | |
54 } | |
55 | 43 |
56 public boolean isEmpty() { | 44 public abstract Iterator<Property> reverseOrderedValueIterator(); |
57 return size() == 0; | |
58 } | |
59 | 45 |
60 public boolean containsKey(Object key) { | 46 public abstract Property getLastProperty(); |
61 for (Map.Entry<Object, Property> entry : reverseOrderEntrySet()) { | |
62 if (entry.getKey().equals(key)) { | |
63 return true; | |
64 } | |
65 } | |
66 return false; | |
67 } | |
68 | 47 |
69 public boolean containsValue(Object value) { | 48 public abstract PropertyMap putCopy(final Property element); |
70 for (Map.Entry<Object, Property> entry : reverseOrderEntrySet()) { | |
71 if (entry.getValue().equals(value)) { | |
72 return true; | |
73 } | |
74 } | |
75 return false; | |
76 } | |
77 | 49 |
78 public Property get(Object key) { | 50 public abstract PropertyMap replaceCopy(final Property oldValue, final Property newValue); |
79 for (Map.Entry<Object, Property> entry : reverseOrderEntrySet()) { | |
80 if (entry.getKey().equals(key)) { | |
81 return entry.getValue(); | |
82 } | |
83 } | |
84 return null; | |
85 } | |
86 | 51 |
87 public Property put(Object key, Property value) { | 52 public abstract PropertyMap removeCopy(final Property value); |
53 | |
54 public abstract PropertyMap getParentMap(); | |
55 | |
56 @Override | |
57 public Property put(final Object key, final Property value) { | |
88 throw unmodifiableException(); | 58 throw unmodifiableException(); |
89 } | 59 } |
90 | 60 |
91 public Property remove(Object key) { | 61 @Override |
62 public void putAll(final Map<? extends Object, ? extends Property> m) { | |
92 throw unmodifiableException(); | 63 throw unmodifiableException(); |
93 } | 64 } |
94 | 65 |
95 public void putAll(Map<? extends Object, ? extends Property> m) { | 66 @Override |
67 public Property remove(final Object key) { | |
96 throw unmodifiableException(); | 68 throw unmodifiableException(); |
97 } | 69 } |
98 | 70 |
71 @Override | |
99 public void clear() { | 72 public void clear() { |
100 throw unmodifiableException(); | 73 throw unmodifiableException(); |
101 } | 74 } |
102 | 75 |
103 public Set<Object> keySet() { | 76 protected static RuntimeException unmodifiableException() { |
104 return new AbstractSet<Object>() { | 77 throw new UnsupportedOperationException(); |
105 @Override | |
106 public Iterator<Object> iterator() { | |
107 Object[] keys = new Object[size()]; | |
108 Iterator<Map.Entry<Object, Property>> iterator = reverseOrderEntrySet().iterator(); | |
109 for (int pos = size() - 1; pos >= 0; pos--) { | |
110 keys[pos] = iterator.next().getKey(); | |
111 } | |
112 return Arrays.asList(keys).iterator(); | |
113 } | |
114 | |
115 @Override | |
116 public int size() { | |
117 return PropertyMap.this.size(); | |
118 } | |
119 }; | |
120 } | |
121 | |
122 public Collection<Property> values() { | |
123 return new AbstractSet<Property>() { | |
124 @Override | |
125 public Iterator<Property> iterator() { | |
126 Property[] values = new Property[size()]; | |
127 Iterator<Map.Entry<Object, Property>> iterator = reverseOrderEntrySet().iterator(); | |
128 for (int pos = size() - 1; pos >= 0; pos--) { | |
129 values[pos] = iterator.next().getValue(); | |
130 } | |
131 return Arrays.asList(values).iterator(); | |
132 } | |
133 | |
134 @Override | |
135 public int size() { | |
136 return PropertyMap.this.size(); | |
137 } | |
138 }; | |
139 } | |
140 | |
141 public Set<Map.Entry<Object, Property>> entrySet() { | |
142 return new AbstractSet<Map.Entry<Object, Property>>() { | |
143 @Override | |
144 public Iterator<Map.Entry<Object, Property>> iterator() { | |
145 @SuppressWarnings("unchecked") | |
146 Map.Entry<Object, Property>[] entries = (Map.Entry<Object, Property>[]) new Map.Entry<?, ?>[size()]; | |
147 Iterator<Map.Entry<Object, Property>> iterator = reverseOrderEntrySet().iterator(); | |
148 for (int pos = size() - 1; pos >= 0; pos--) { | |
149 entries[pos] = iterator.next(); | |
150 } | |
151 return Arrays.asList(entries).iterator(); | |
152 } | |
153 | |
154 @Override | |
155 public int size() { | |
156 return PropertyMap.this.size(); | |
157 } | |
158 }; | |
159 } | |
160 | |
161 public Set<Map.Entry<Object, Property>> reverseOrderEntrySet() { | |
162 return new AbstractSet<Map.Entry<Object, Property>>() { | |
163 @Override | |
164 public Iterator<Map.Entry<Object, Property>> iterator() { | |
165 return new Iterator<Map.Entry<Object, Property>>() { | |
166 PropertyMap current = PropertyMap.this; | |
167 | |
168 public Entry<Object, Property> next() { | |
169 if (hasNext()) { | |
170 try { | |
171 return new MapEntryImpl(current.cdr); | |
172 } finally { | |
173 current = current.car; | |
174 } | |
175 } else { | |
176 throw new NoSuchElementException(); | |
177 } | |
178 } | |
179 | |
180 public boolean hasNext() { | |
181 return current != empty(); | |
182 } | |
183 | |
184 public void remove() { | |
185 throw new UnsupportedOperationException(); | |
186 } | |
187 }; | |
188 } | |
189 | |
190 @Override | |
191 public int size() { | |
192 return PropertyMap.this.size(); | |
193 } | |
194 }; | |
195 } | |
196 | |
197 public Set<Object> reverseOrderKeys() { | |
198 return new AbstractSet<Object>() { | |
199 @Override | |
200 public Iterator<Object> iterator() { | |
201 return new Iterator<Object>() { | |
202 PropertyMap current = PropertyMap.this; | |
203 | |
204 public Object next() { | |
205 if (hasNext()) { | |
206 try { | |
207 return current.cdr.getKey(); | |
208 } finally { | |
209 current = current.car; | |
210 } | |
211 } else { | |
212 throw new NoSuchElementException(); | |
213 } | |
214 } | |
215 | |
216 public boolean hasNext() { | |
217 return current != empty(); | |
218 } | |
219 | |
220 public void remove() { | |
221 throw new UnsupportedOperationException(); | |
222 } | |
223 }; | |
224 } | |
225 | |
226 @Override | |
227 public int size() { | |
228 return PropertyMap.this.size(); | |
229 } | |
230 }; | |
231 } | |
232 | |
233 public Set<Property> reverseOrderValues() { | |
234 return new AbstractSet<Property>() { | |
235 @Override | |
236 public Iterator<Property> iterator() { | |
237 return new Iterator<Property>() { | |
238 PropertyMap current = PropertyMap.this; | |
239 | |
240 public Property next() { | |
241 if (hasNext()) { | |
242 try { | |
243 return current.cdr; | |
244 } finally { | |
245 current = current.car; | |
246 } | |
247 } else { | |
248 throw new NoSuchElementException(); | |
249 } | |
250 } | |
251 | |
252 public boolean hasNext() { | |
253 return current != empty(); | |
254 } | |
255 | |
256 public void remove() { | |
257 throw new UnsupportedOperationException(); | |
258 } | |
259 }; | |
260 } | |
261 | |
262 @Override | |
263 public int size() { | |
264 return PropertyMap.this.size(); | |
265 } | |
266 }; | |
267 } | |
268 | |
269 private static final class MapEntryImpl implements Map.Entry<Object, Property> { | |
270 private final Property backingProperty; | |
271 | |
272 public MapEntryImpl(Property backingProperty) { | |
273 this.backingProperty = backingProperty; | |
274 } | |
275 | |
276 public Object getKey() { | |
277 return backingProperty.getKey(); | |
278 } | |
279 | |
280 public Property getValue() { | |
281 return backingProperty; | |
282 } | |
283 | |
284 public Property setValue(Property value) { | |
285 throw unmodifiableException(); | |
286 } | |
287 } | |
288 | |
289 private static UnsupportedOperationException unmodifiableException() { | |
290 throw new UnsupportedOperationException("unmodifiable"); | |
291 } | |
292 | |
293 public PropertyMap putCopy(Property value) { | |
294 return new PropertyMap(this, value); | |
295 } | |
296 | |
297 public PropertyMap removeCopy(Property value) { | |
298 Deque<Property> shelve = new ArrayDeque<>(); | |
299 PropertyMap current = this; | |
300 while (!current.isEmpty()) { | |
301 if (current.getLastProperty().equals(value)) { | |
302 PropertyMap newMap = current.getParentMap(); | |
303 for (Property property : shelve) { | |
304 newMap = newMap.putCopy(property); | |
305 } | |
306 return newMap; | |
307 } else { | |
308 shelve.push(current.getLastProperty()); | |
309 current = current.getParentMap(); | |
310 } | |
311 } | |
312 return this; | |
313 } | |
314 | |
315 public PropertyMap replaceCopy(Property oldValue, Property newValue) { | |
316 Deque<Property> shelve = new ArrayDeque<>(); | |
317 PropertyMap current = this; | |
318 while (!current.isEmpty()) { | |
319 if (current.getLastProperty().equals(oldValue)) { | |
320 PropertyMap newMap = current.getParentMap(); | |
321 newMap = newMap.putCopy(newValue); | |
322 for (Property property : shelve) { | |
323 newMap = newMap.putCopy(property); | |
324 } | |
325 return newMap; | |
326 } else { | |
327 shelve.push(current.getLastProperty()); | |
328 current = current.getParentMap(); | |
329 } | |
330 } | |
331 return this; | |
332 } | |
333 | |
334 public PropertyMap getOwningMap(Property value) { | |
335 PropertyMap current = this; | |
336 while (!current.isEmpty()) { | |
337 if (current.getLastProperty().equals(value)) { | |
338 return current; | |
339 } | |
340 current = current.getParentMap(); | |
341 } | |
342 return null; | |
343 } | |
344 | |
345 PropertyMap getParentMap() { | |
346 return car; | |
347 } | |
348 | |
349 public Property getLastProperty() { | |
350 return cdr; | |
351 } | |
352 | |
353 @Override | |
354 public String toString() { | |
355 return values().toString(); | |
356 } | 78 } |
357 } | 79 } |