]>
Commit | Line | Data |
---|---|---|
1b2798f6 EK |
1 | /******************************************************************************* |
2 | * Copyright (c) 2000, 2011 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 | * Robert M. Fuhrer (rfuhrer@watson.ibm.com), IBM Corporation - initial API and implementation | |
10 | *******************************************************************************/ | |
11 | package org.eclipse.jdt.internal.corext.refactoring.typeconstraints.typesets; | |
12 | ||
13 | import java.util.Iterator; | |
14 | import java.util.LinkedHashSet; | |
15 | import java.util.Set; | |
16 | ||
17 | import org.eclipse.core.runtime.Assert; | |
18 | ||
19 | import org.eclipse.jdt.internal.corext.refactoring.typeconstraints.types.ArrayType; | |
20 | import org.eclipse.jdt.internal.corext.refactoring.typeconstraints.types.TType; | |
21 | import org.eclipse.jdt.internal.corext.refactoring.typeconstraints2.TTypes; | |
22 | ||
23 | /** | |
24 | * A type-safe wrapper for {@code Set<TType>} that also adds {@code TType}-specific | |
25 | * functionality, e.g. subTypes() and superTypes(). | |
26 | */ | |
27 | public class EnumeratedTypeSet extends TypeSet { | |
28 | static private int sCount= 0; | |
29 | ||
30 | static public int getCount() { | |
31 | return sCount; | |
32 | } | |
33 | ||
34 | static public void resetCount() { | |
35 | sCount= 0; | |
36 | } | |
37 | ||
38 | /** | |
39 | * Set containing the TTypes in this EnumeratedTypeSet. | |
40 | */ | |
41 | Set<TType> fMembers= new LinkedHashSet<TType>(); | |
42 | ||
43 | /** | |
44 | * Constructs a new EnumeratedTypeSet with the members of Set s in it. | |
45 | * All elements of s must be TTypes. | |
46 | * | |
47 | * @param types the types | |
48 | * @param typeSetEnvironment the environment | |
49 | */ | |
50 | public EnumeratedTypeSet(Iterator<TType> types, TypeSetEnvironment typeSetEnvironment) { | |
51 | super(typeSetEnvironment); | |
52 | while (types.hasNext()) { | |
53 | fMembers.add(types.next()); | |
54 | } | |
55 | sCount++; | |
56 | } | |
57 | ||
58 | /** | |
59 | * Constructs an empty EnumeratedTypeSet. | |
60 | * | |
61 | * @param typeSetEnvironment the environment | |
62 | */ | |
63 | public EnumeratedTypeSet(TypeSetEnvironment typeSetEnvironment) { | |
64 | super(typeSetEnvironment); | |
65 | sCount++; | |
66 | } | |
67 | ||
68 | /** | |
69 | * Constructs a new EnumeratedTypeSet with the given single TType in it. | |
70 | * | |
71 | * @param t the type | |
72 | * @param typeSetEnvironment the environment | |
73 | */ | |
74 | public EnumeratedTypeSet(TType t, TypeSetEnvironment typeSetEnvironment) { | |
75 | super(typeSetEnvironment); | |
76 | Assert.isNotNull(t); | |
77 | fMembers.add(t); | |
78 | sCount++; | |
79 | } | |
80 | ||
81 | /** | |
82 | * @return <code>true</code> iff this set represents the universe of TTypes | |
83 | */ | |
84 | @Override | |
85 | public boolean isUniverse() { | |
86 | return false; | |
87 | } | |
88 | ||
89 | @Override | |
90 | public boolean equals(Object o) { | |
91 | if (this == o) return true; | |
92 | if (o instanceof EnumeratedTypeSet) { | |
93 | EnumeratedTypeSet other= (EnumeratedTypeSet) o; | |
94 | ||
95 | return fMembers.equals(other.fMembers); | |
96 | } else if (o instanceof SingletonTypeSet) { | |
97 | SingletonTypeSet other= (SingletonTypeSet) o; | |
98 | ||
99 | return (fMembers.size() == 1) && fMembers.contains(other.anyMember()); | |
100 | } else if (o instanceof TypeSet) { | |
101 | TypeSet other= (TypeSet) o; | |
102 | ||
103 | for(Iterator<TType> otherIter= other.iterator(); otherIter.hasNext(); ) { | |
104 | if (!fMembers.contains(otherIter.next())) | |
105 | return false; | |
106 | } | |
107 | for(Iterator<TType> myIter= fMembers.iterator(); myIter.hasNext(); ) { | |
108 | if (!other.contains(myIter.next())) | |
109 | return false; | |
110 | } | |
111 | return true; | |
112 | } else | |
113 | return false; | |
114 | } | |
115 | ||
116 | @Override | |
117 | public int hashCode() { | |
118 | return 37 + fMembers.hashCode(); | |
119 | } | |
120 | ||
121 | /** | |
122 | * Computes and returns a <em>new</em> EnumeratedTypeSet representing the intersection of the | |
123 | * receiver with s2. Does not modify the receiver. | |
124 | * @param s2 the other type set | |
125 | */ | |
126 | @Override | |
127 | protected TypeSet specialCasesIntersectedWith(TypeSet s2) { | |
128 | if (s2 instanceof EnumeratedTypeSet) { | |
129 | EnumeratedTypeSet result= new EnumeratedTypeSet(getTypeSetEnvironment()); | |
130 | ||
131 | result.addAll(this); // copy first since retainAll() modifies in-place | |
132 | result.retainAll(s2); | |
133 | if (result.size() > 0) | |
134 | return result; | |
135 | else | |
136 | return getTypeSetEnvironment().getEmptyTypeSet(); | |
137 | } | |
138 | return null; | |
139 | } | |
140 | ||
141 | /** | |
142 | * Modifies this EnumeratedTypeSet to represent the intersection of the receiver with s2. | |
143 | * @param s2 the other type set | |
144 | */ | |
145 | public void intersectWith(TypeSet s2) { | |
146 | if (isUniverse()) { | |
147 | if (s2.isUniverse()) | |
148 | return; | |
149 | // More than an optimization: the universe never contains array types, so | |
150 | // if s2 has array types, the following will retain them, as it should. | |
151 | EnumeratedTypeSet ets2= (EnumeratedTypeSet) s2; | |
152 | fMembers= new LinkedHashSet<TType>(); | |
153 | fMembers.addAll(ets2.fMembers); | |
154 | } else | |
155 | retainAll(s2); | |
156 | } | |
157 | ||
158 | /** | |
159 | * @return a new TypeSet representing the set of all sub-types of the | |
160 | * types in the receiver | |
161 | */ | |
162 | @Override | |
163 | public TypeSet subTypes() { | |
164 | if (isUniverse()) | |
165 | return makeClone(); // subtypes(universe) = universe | |
166 | ||
167 | if (fMembers.contains(getJavaLangObject())) | |
168 | return getTypeSetEnvironment().getUniverseTypeSet(); | |
169 | ||
170 | return getTypeSetEnvironment().createSubTypesSet(this); | |
171 | } | |
172 | ||
173 | public static EnumeratedTypeSet makeArrayTypesForElements(Iterator<TType> elemTypes, TypeSetEnvironment typeSetEnvironment) { | |
174 | EnumeratedTypeSet result= new EnumeratedTypeSet(typeSetEnvironment); | |
175 | ||
176 | while (elemTypes.hasNext()) { | |
177 | TType t= elemTypes.next(); | |
178 | result.add(TTypes.createArrayType(t, 1)); | |
179 | } | |
180 | // result.initComplete(); | |
181 | return result; | |
182 | } | |
183 | ||
184 | /** | |
185 | * @return a new TypeSet representing the set of all super-types of the | |
186 | * types in the receiver | |
187 | */ | |
188 | @Override | |
189 | public TypeSet superTypes() { | |
190 | if (isUniverse()) | |
191 | return makeClone(); // The supertypes of the universe is the universe | |
192 | ||
193 | return getTypeSetEnvironment().createSuperTypesSet(this); | |
194 | } | |
195 | ||
196 | @Override | |
197 | public TypeSet makeClone() { | |
198 | EnumeratedTypeSet result= new EnumeratedTypeSet(getTypeSetEnvironment()); | |
199 | ||
200 | result.fMembers.addAll(fMembers); | |
201 | result.initComplete(); | |
202 | return result; | |
203 | } | |
204 | ||
205 | /* (non-Javadoc) | |
206 | * @see java.util.Set#size() | |
207 | */ | |
208 | public int size() { | |
209 | return fMembers.size(); | |
210 | } | |
211 | ||
212 | /* (non-Javadoc) | |
213 | * @see java.util.Set#clear() | |
214 | */ | |
215 | public void clear() { | |
216 | if (isUniverse()) | |
217 | fMembers= new LinkedHashSet<TType>(); | |
218 | else | |
219 | fMembers.clear(); | |
220 | } | |
221 | ||
222 | /* (non-Javadoc) | |
223 | * @see java.util.Set#isEmpty() | |
224 | */ | |
225 | @Override | |
226 | public boolean isEmpty() { | |
227 | return fMembers.isEmpty(); | |
228 | } | |
229 | ||
230 | /* (non-Javadoc) | |
231 | * @see java.util.Set#toArray() | |
232 | */ | |
233 | public TType[] toArray() { | |
234 | return fMembers.toArray(new TType[fMembers.size()]); | |
235 | } | |
236 | ||
237 | /* (non-Javadoc) | |
238 | * @see java.util.Set#add(java.lang.Object) | |
239 | */ | |
240 | public boolean add(TType t) { | |
241 | // Doesn't make sense to do here what other methods do (copy-and-modify) | |
242 | Assert.isTrue(!isUniverse(), "Someone's trying to expand the universe!"); //$NON-NLS-1$ | |
243 | return fMembers.add(t); | |
244 | } | |
245 | ||
246 | /* (non-Javadoc) | |
247 | * @see java.util.Set#contains(java.lang.Object) | |
248 | */ | |
249 | @Override | |
250 | public boolean contains(TType t) { | |
251 | if (isUniverse()) | |
252 | return true; | |
253 | return fMembers.contains(t); | |
254 | } | |
255 | ||
256 | /* (non-Javadoc) | |
257 | * @see java.util.Set#remove(java.lang.Object) | |
258 | */ | |
259 | public boolean remove(TType t) { | |
260 | if (isUniverse()) | |
261 | fMembers= cloneSet(fMembers); | |
262 | return fMembers.remove(t); | |
263 | } | |
264 | ||
265 | private Set<TType> cloneSet(Set<TType> members) { | |
266 | Set<TType> result= new LinkedHashSet<TType>(); | |
267 | result.addAll(members); | |
268 | return result; | |
269 | } | |
270 | ||
271 | /* (non-Javadoc) | |
272 | * @see java.util.Set#addAll(java.util.Collection) | |
273 | */ | |
274 | public boolean addAll(TypeSet s) { | |
275 | if (s instanceof EnumeratedTypeSet) { | |
276 | EnumeratedTypeSet ets= (EnumeratedTypeSet) s; | |
277 | ||
278 | return fMembers.addAll(ets.fMembers); | |
279 | } else { | |
280 | EnumeratedTypeSet ets= s.enumerate(); | |
281 | ||
282 | return fMembers.addAll(ets.fMembers); | |
283 | } | |
284 | } | |
285 | ||
286 | @Override | |
287 | public TypeSet addedTo(TypeSet that) { | |
288 | EnumeratedTypeSet result= new EnumeratedTypeSet(getTypeSetEnvironment()); | |
289 | ||
290 | result.addAll(this); | |
291 | result.addAll(that); | |
292 | result.initComplete(); | |
293 | return result; | |
294 | } | |
295 | ||
296 | /* (non-Javadoc) | |
297 | * @see java.util.Set#containsAll(java.util.Collection) | |
298 | */ | |
299 | @Override | |
300 | public boolean containsAll(TypeSet s) { | |
301 | if (isUniverse()) | |
302 | return true; | |
303 | if (s.isUniverse()) | |
304 | return false; | |
305 | EnumeratedTypeSet ets= s.enumerate(); | |
306 | ||
307 | return fMembers.containsAll(ets.fMembers); | |
308 | } | |
309 | ||
310 | /* (non-Javadoc) | |
311 | * @see java.util.Set#removeAll(java.util.Collection) | |
312 | */ | |
313 | public boolean removeAll(EnumeratedTypeSet s) { | |
314 | if (isUniverse()) | |
315 | fMembers= cloneSet(fMembers); | |
316 | return fMembers.removeAll(s.fMembers); | |
317 | } | |
318 | ||
319 | /* (non-Javadoc) | |
320 | * @see java.util.Set#retainAll(java.util.Collection) | |
321 | */ | |
322 | public boolean retainAll(TypeSet s) { | |
323 | if (s.isUniverse()) return false; | |
324 | ||
325 | EnumeratedTypeSet ets= (EnumeratedTypeSet) s; | |
326 | ||
327 | if (isUniverse()) { | |
328 | fMembers= cloneSet(ets.fMembers); | |
329 | return true; | |
330 | } else | |
331 | return fMembers.retainAll(ets.fMembers); | |
332 | } | |
333 | ||
334 | /* (non-Javadoc) | |
335 | * @see org.eclipse.jdt.internal.corext.refactoring.typeconstraints.typesets.TypeSet#isSingleton() | |
336 | */ | |
337 | @Override | |
338 | public boolean isSingleton() { | |
339 | return fMembers.size() == 1; | |
340 | } | |
341 | ||
342 | /* (non-Javadoc) | |
343 | * @see org.eclipse.jdt.internal.corext.refactoring.typeconstraints.typesets.TypeSet#anyMember() | |
344 | */ | |
345 | @Override | |
346 | public TType anyMember() { | |
347 | return fMembers.iterator().next(); | |
348 | } | |
349 | ||
350 | /* (non-Javadoc) | |
351 | * @see org.eclipse.jdt.internal.corext.refactoring.typeconstraints.typesets.TypeSet#upperBound() | |
352 | */ | |
353 | @Override | |
354 | public TypeSet upperBound() { | |
355 | if (fMembers.size() == 1) | |
356 | return new SingletonTypeSet(fMembers.iterator().next(), getTypeSetEnvironment()); | |
357 | if (fMembers.contains(getJavaLangObject())) | |
358 | return new SingletonTypeSet(getJavaLangObject(), getTypeSetEnvironment()); | |
359 | ||
360 | EnumeratedTypeSet result= new EnumeratedTypeSet(getTypeSetEnvironment()); | |
361 | ||
362 | // Add to result each element of fMembers that has no proper supertype in fMembers | |
363 | result.fMembers.addAll(fMembers); | |
364 | for(Iterator<TType> iter= fMembers.iterator(); iter.hasNext(); ) { | |
365 | TType t= iter.next(); | |
366 | ||
367 | if (t.isArrayType()) { | |
368 | ArrayType at= (ArrayType) t; | |
369 | int numDims= at.getDimensions(); | |
370 | for(Iterator<TType> subIter=TTypes.getAllSubTypesIterator(at.getElementType()); subIter.hasNext(); ) { | |
371 | result.fMembers.remove(TTypes.createArrayType(subIter.next(), numDims)); | |
372 | } | |
373 | } else { | |
374 | for (Iterator<TType> iterator= TTypes.getAllSubTypesIterator(t); iterator.hasNext();) { | |
375 | result.fMembers.remove(iterator.next()); | |
376 | } | |
377 | } | |
378 | } | |
379 | result.initComplete(); | |
380 | return result; | |
381 | } | |
382 | ||
383 | /* (non-Javadoc) | |
384 | * @see org.eclipse.jdt.internal.corext.refactoring.typeconstraints.typesets.TypeSet#lowerBound() | |
385 | */ | |
386 | @Override | |
387 | public TypeSet lowerBound() { | |
388 | if (fMembers.size() == 1) | |
389 | return new SingletonTypeSet(fMembers.iterator().next(), getTypeSetEnvironment()); | |
390 | ||
391 | EnumeratedTypeSet result= new EnumeratedTypeSet(getTypeSetEnvironment()); | |
392 | ||
393 | // Add to result each element of fMembers that has no proper subtype in fMembers | |
394 | result.fMembers.addAll(fMembers); | |
395 | ||
396 | for(Iterator<TType> iter= fMembers.iterator(); iter.hasNext(); ) { | |
397 | TType t= iter.next(); | |
398 | ||
399 | // java.lang.Object is only in the lower bound if fMembers consists | |
400 | // of only java.lang.Object, but that case is handled above. | |
401 | if (t.equals(getJavaLangObject())) { | |
402 | result.fMembers.remove(t); | |
403 | continue; | |
404 | } | |
405 | ||
406 | if (t instanceof ArrayType) { | |
407 | ArrayType at= (ArrayType) t; | |
408 | int numDims= at.getDimensions(); | |
409 | for(Iterator<TType> superIter=TTypes.getAllSuperTypesIterator(at.getElementType()); superIter.hasNext(); ) { | |
410 | result.fMembers.remove(TTypes.createArrayType(superIter.next(), numDims)); | |
411 | } | |
412 | } else { | |
413 | for (Iterator<TType> iterator= TTypes.getAllSuperTypesIterator(t); iterator.hasNext();) { | |
414 | result.fMembers.remove(iterator.next()); | |
415 | } | |
416 | } | |
417 | } | |
418 | if (result.size() > 0) | |
419 | return result; | |
420 | else | |
421 | return getTypeSetEnvironment().getEmptyTypeSet(); | |
422 | } | |
423 | ||
424 | /* (non-Javadoc) | |
425 | * @see org.eclipse.jdt.internal.corext.refactoring.typeconstraints.typesets.TypeSet#hasUniqueLowerBound() | |
426 | */ | |
427 | @Override | |
428 | public boolean hasUniqueLowerBound() { | |
429 | return fMembers.size() == 1; | |
430 | } | |
431 | ||
432 | /* (non-Javadoc) | |
433 | * @see org.eclipse.jdt.internal.corext.refactoring.typeconstraints.typesets.TypeSet#hasUniqueUpperBound() | |
434 | */ | |
435 | @Override | |
436 | public boolean hasUniqueUpperBound() { | |
437 | return fMembers.size() == 1; | |
438 | } | |
439 | ||
440 | /* (non-Javadoc) | |
441 | * @see org.eclipse.jdt.internal.corext.refactoring.typeconstraints.typesets.TypeSet#uniqueLowerBound() | |
442 | */ | |
443 | @Override | |
444 | public TType uniqueLowerBound() { | |
445 | if (fMembers.size() == 1) | |
446 | return fMembers.iterator().next(); | |
447 | return null; | |
448 | } | |
449 | ||
450 | /* (non-Javadoc) | |
451 | * @see org.eclipse.jdt.internal.corext.refactoring.typeconstraints.typesets.TypeSet#uniqueUpperBound() | |
452 | */ | |
453 | @Override | |
454 | public TType uniqueUpperBound() { | |
455 | if (fMembers.size() == 1) | |
456 | return fMembers.iterator().next(); | |
457 | return null; | |
458 | } | |
459 | ||
460 | /* (non-Javadoc) | |
461 | * @see java.util.Set#iterator() | |
462 | */ | |
463 | @Override | |
464 | public Iterator<TType> iterator() { | |
465 | return fMembers.iterator(); | |
466 | } | |
467 | ||
468 | /** | |
469 | * Limits the display of set elements to the first sMaxElements. | |
470 | */ | |
471 | private static final int sMaxElements= 10; // Integer.MAX_VALUE; | |
472 | ||
473 | /* | |
474 | * (non-Javadoc) | |
475 | * @see java.lang.Object#toString() | |
476 | */ | |
477 | @Override | |
478 | public String toString() { | |
479 | StringBuffer b= new StringBuffer(); | |
480 | b.append("{" + fID+ ":"); //$NON-NLS-1$ //$NON-NLS-2$ | |
481 | if (isUniverse()) | |
482 | b.append(" <universe>"); //$NON-NLS-1$ | |
483 | else { | |
484 | int count=0; | |
485 | Iterator<TType> iter; | |
486 | for(iter= iterator(); iter.hasNext() && count < sMaxElements; count++) { | |
487 | TType type= iter.next(); | |
488 | b.append(' ') | |
489 | .append(type.getPrettySignature()); | |
490 | if (iter.hasNext()) | |
491 | b.append(','); | |
492 | } | |
493 | if (iter.hasNext()) | |
494 | b.append(" ..."); //$NON-NLS-1$ | |
495 | } | |
496 | b.append(" }"); //$NON-NLS-1$ | |
497 | return b.toString(); | |
498 | } | |
499 | ||
500 | /* (non-Javadoc) | |
501 | * @see org.eclipse.jdt.internal.corext.refactoring.typeconstraints.typesets.TypeSet#enumerate() | |
502 | */ | |
503 | @Override | |
504 | public EnumeratedTypeSet enumerate() { | |
505 | return this; // (EnumeratedTypeSet) makeClone(); | |
506 | } | |
507 | ||
508 | public void initComplete() { | |
509 | Assert.isTrue(! fMembers.isEmpty()); | |
510 | } | |
511 | ||
512 | } |