comparison graal/com.oracle.truffle.object/src/com/oracle/truffle/object/PropertyMap.java @ 18408:2c3666f44855

Truffle: initial commit of object API implementation
author Andreas Woess <andreas.woess@jku.at>
date Tue, 18 Nov 2014 23:19:43 +0100
parents
children de8880bbf2e1
comparison
equal deleted inserted replaced
18407:f439fdb137a3 18408:2c3666f44855
1 /*
2 * Copyright (c) 2014, 2014, Oracle and/or its affiliates. All rights reserved.
3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4 *
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
7 * published by the Free Software Foundation.
8 *
9 * This code is distributed in the hope that it will be useful, but WITHOUT
10 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
11 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
12 * version 2 for more details (a copy is included in the LICENSE file that
13 * accompanied this code).
14 *
15 * You should have received a copy of the GNU General Public License version
16 * 2 along with this work; if not, write to the Free Software Foundation,
17 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
18 *
19 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
20 * or visit www.oracle.com if you need additional information or have any
21 * questions.
22 */
23 package com.oracle.truffle.object;
24
25 import java.util.*;
26
27 import com.oracle.truffle.api.object.*;
28
29 public final class PropertyMap implements Map<Object, Property> {
30 private final PropertyMap car;
31 private final Property cdr;
32 private final int size;
33
34 private static final PropertyMap EMPTY = new PropertyMap();
35
36 private PropertyMap() {
37 this.car = null;
38 this.cdr = null;
39 this.size = 0;
40 }
41
42 private PropertyMap(PropertyMap parent, Property added) {
43 this.car = Objects.requireNonNull(parent);
44 this.cdr = added;
45 this.size = parent.size + 1;
46 }
47
48 public static PropertyMap empty() {
49 return EMPTY;
50 }
51
52 public int size() {
53 return size;
54 }
55
56 public boolean isEmpty() {
57 return size() == 0;
58 }
59
60 public boolean containsKey(Object key) {
61 for (Map.Entry<Object, Property> entry : reverseOrderEntrySet()) {
62 if (entry.getKey().equals(key)) {
63 return true;
64 }
65 }
66 return false;
67 }
68
69 public boolean containsValue(Object value) {
70 for (Map.Entry<Object, Property> entry : reverseOrderEntrySet()) {
71 if (entry.getValue().equals(value)) {
72 return true;
73 }
74 }
75 return false;
76 }
77
78 public Property get(Object key) {
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
87 public Property put(Object key, Property value) {
88 throw unmodifiableException();
89 }
90
91 public Property remove(Object key) {
92 throw unmodifiableException();
93 }
94
95 public void putAll(Map<? extends Object, ? extends Property> m) {
96 throw unmodifiableException();
97 }
98
99 public void clear() {
100 throw unmodifiableException();
101 }
102
103 public Set<Object> keySet() {
104 return new AbstractSet<Object>() {
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 assert !this.containsValue(value);
295 return new PropertyMap(this, value);
296 }
297
298 public PropertyMap removeCopy(Property value) {
299 LinkedList<Property> shelve = new LinkedList<>();
300 PropertyMap current = this;
301 while (!current.isEmpty()) {
302 if (current.getLastProperty().equals(value)) {
303 PropertyMap newMap = current.getParentMap();
304 for (Property property : shelve) {
305 newMap = newMap.putCopy(property);
306 }
307 return newMap;
308 } else {
309 shelve.push(current.getLastProperty());
310 current = current.getParentMap();
311 }
312 }
313 return this;
314 }
315
316 public PropertyMap replaceCopy(Property oldValue, Property newValue) {
317 LinkedList<Property> shelve = new LinkedList<>();
318 PropertyMap current = this;
319 while (!current.isEmpty()) {
320 if (current.getLastProperty().equals(oldValue)) {
321 PropertyMap newMap = current.getParentMap();
322 newMap = newMap.putCopy(newValue);
323 for (Property property : shelve) {
324 newMap = newMap.putCopy(property);
325 }
326 return newMap;
327 } else {
328 shelve.push(current.getLastProperty());
329 current = current.getParentMap();
330 }
331 }
332 return this;
333 }
334
335 public PropertyMap getOwningMap(Property value) {
336 PropertyMap current = this;
337 while (!current.isEmpty()) {
338 if (current.getLastProperty().equals(value)) {
339 return current;
340 }
341 current = current.getParentMap();
342 }
343 return null;
344 }
345
346 PropertyMap getParentMap() {
347 return car;
348 }
349
350 public Property getLastProperty() {
351 return cdr;
352 }
353 }