001: /*******************************************************************************
002: * Copyright (c) 2000, 2006 IBM Corporation and others.
003: * All rights reserved. This program and the accompanying materials
004: * are made available under the terms of the Eclipse Public License v1.0
005: * which accompanies this distribution, and is available at
006: * http://www.eclipse.org/legal/epl-v10.html
007: *
008: * Contributors:
009: * Robert M. Fuhrer (rfuhrer@watson.ibm.com), IBM Corporation - initial API and implementation
010: *******************************************************************************/package org.eclipse.jdt.internal.corext.refactoring.typeconstraints.typesets;
011:
012: import java.util.Iterator;
013: import java.util.LinkedHashSet;
014: import java.util.Set;
015:
016: import org.eclipse.core.runtime.Assert;
017:
018: import org.eclipse.jdt.internal.corext.refactoring.typeconstraints.types.ArrayType;
019: import org.eclipse.jdt.internal.corext.refactoring.typeconstraints.types.TType;
020: import org.eclipse.jdt.internal.corext.refactoring.typeconstraints2.TTypes;
021:
022: /**
023: * A type-safe wrapper for Set<TType> that also adds TType-specific
024: * functionality, e.g. subTypes() and superTypes().
025: */
026: public class EnumeratedTypeSet extends TypeSet {
027: static private int sCount = 0;
028:
029: static public int getCount() {
030: return sCount;
031: }
032:
033: static public void resetCount() {
034: sCount = 0;
035: }
036:
037: /**
038: * Set containing the TTypes in this EnumeratedTypeSet.
039: */
040: Set/*<TType>*/fMembers = new LinkedHashSet();
041:
042: /**
043: * Constructs a new EnumeratedTypeSet with the members of Set s in it.
044: * All elements of s must be TTypes.
045: */
046: public EnumeratedTypeSet(Iterator types,
047: TypeSetEnvironment typeSetEnvironment) {
048: super (typeSetEnvironment);
049: while (types.hasNext()) {
050: fMembers.add(types.next());
051: }
052: sCount++;
053: }
054:
055: /**
056: * Constructs an empty EnumeratedTypeSet.
057: */
058: public EnumeratedTypeSet(TypeSetEnvironment typeSetEnvironment) {
059: super (typeSetEnvironment);
060: sCount++;
061: }
062:
063: /**
064: * Constructs a new EnumeratedTypeSet with the given single TType in it.
065: */
066: public EnumeratedTypeSet(TType t,
067: TypeSetEnvironment typeSetEnvironment) {
068: super (typeSetEnvironment);
069: Assert.isNotNull(t);
070: fMembers.add(t);
071: sCount++;
072: }
073:
074: /**
075: * @return <code>true</code> iff this set represents the universe of TTypes
076: */
077: public boolean isUniverse() {
078: return false;
079: }
080:
081: public boolean equals(Object o) {
082: if (this == o)
083: return true;
084: if (o instanceof EnumeratedTypeSet) {
085: EnumeratedTypeSet other = (EnumeratedTypeSet) o;
086:
087: return fMembers.equals(other.fMembers);
088: } else if (o instanceof SingletonTypeSet) {
089: SingletonTypeSet other = (SingletonTypeSet) o;
090:
091: return (fMembers.size() == 1)
092: && fMembers.contains(other.anyMember());
093: } else if (o instanceof TypeSet) {
094: TypeSet other = (TypeSet) o;
095:
096: for (Iterator otherIter = other.iterator(); otherIter
097: .hasNext();) {
098: if (!fMembers.contains(otherIter.next()))
099: return false;
100: }
101: for (Iterator myIter = fMembers.iterator(); myIter
102: .hasNext();) {
103: if (!other.contains((TType) myIter.next()))
104: return false;
105: }
106: return true;
107: } else
108: return false;
109: }
110:
111: public int hashCode() {
112: return 37 + fMembers.hashCode();
113: }
114:
115: /**
116: * Computes and returns a <em>new</em> EnumeratedTypeSet representing the intersection of the
117: * receiver with s2. Does not modify the receiver.
118: * @param s2
119: */
120: protected TypeSet specialCasesIntersectedWith(TypeSet s2) {
121: if (s2 instanceof EnumeratedTypeSet) {
122: EnumeratedTypeSet result = new EnumeratedTypeSet(
123: getTypeSetEnvironment());
124:
125: result.addAll(this ); // copy first since retainAll() modifies in-place
126: result.retainAll(s2);
127: if (result.size() > 0)
128: return result;
129: else
130: return getTypeSetEnvironment().getEmptyTypeSet();
131: }
132: return null;
133: }
134:
135: /**
136: * Modifies this EnumeratedTypeSet to represent the intersection of the receiver with s2.
137: * @param s2
138: */
139: public void intersectWith(TypeSet s2) {
140: if (isUniverse()) {
141: if (s2.isUniverse())
142: return;
143: // More than an optimization: the universe never contains array types, so
144: // if s2 has array types, the following will retain them, as it should.
145: EnumeratedTypeSet ets2 = (EnumeratedTypeSet) s2;
146: fMembers = new LinkedHashSet();
147: fMembers.addAll(ets2.fMembers);
148: } else
149: retainAll(s2);
150: }
151:
152: /**
153: * @return a new TypeSet representing the set of all sub-types of the
154: * types in the receiver
155: */
156: public TypeSet subTypes() {
157: if (isUniverse())
158: return makeClone(); // subtypes(universe) = universe
159:
160: if (fMembers.contains(getJavaLangObject()))
161: return getTypeSetEnvironment().getUniverseTypeSet();
162:
163: return getTypeSetEnvironment().createSubTypesSet(this );
164: }
165:
166: public static EnumeratedTypeSet makeArrayTypesForElements(
167: Iterator/*<TType>*/elemTypes,
168: TypeSetEnvironment typeSetEnvironment) {
169: EnumeratedTypeSet result = new EnumeratedTypeSet(
170: typeSetEnvironment);
171:
172: while (elemTypes.hasNext()) {
173: TType t = (TType) elemTypes.next();
174: result.add(TTypes.createArrayType(t, 1));
175: }
176: // result.initComplete();
177: return result;
178: }
179:
180: /**
181: * @return a new TypeSet representing the set of all super-types of the
182: * types in the receiver
183: */
184: public TypeSet super Types() {
185: if (isUniverse())
186: return makeClone(); // The supertypes of the universe is the universe
187:
188: return getTypeSetEnvironment().createSuperTypesSet(this );
189: }
190:
191: public TypeSet makeClone() {
192: EnumeratedTypeSet result = new EnumeratedTypeSet(
193: getTypeSetEnvironment());
194:
195: result.fMembers.addAll(fMembers);
196: result.initComplete();
197: return result;
198: }
199:
200: /* (non-Javadoc)
201: * @see java.util.Set#size()
202: */
203: public int size() {
204: return fMembers.size();
205: }
206:
207: /* (non-Javadoc)
208: * @see java.util.Set#clear()
209: */
210: public void clear() {
211: if (isUniverse())
212: fMembers = new LinkedHashSet();
213: else
214: fMembers.clear();
215: }
216:
217: /* (non-Javadoc)
218: * @see java.util.Set#isEmpty()
219: */
220: public boolean isEmpty() {
221: return fMembers.isEmpty();
222: }
223:
224: /* (non-Javadoc)
225: * @see java.util.Set#toArray()
226: */
227: public TType[] toArray() {
228: return (TType[]) fMembers.toArray(new TType[fMembers.size()]);
229: }
230:
231: /* (non-Javadoc)
232: * @see java.util.Set#add(java.lang.Object)
233: */
234: public boolean add(TType t) {
235: // Doesn't make sense to do here what other methods do (copy-and-modify)
236: Assert.isTrue(!isUniverse(),
237: "Someone's trying to expand the universe!"); //$NON-NLS-1$
238: return fMembers.add(t);
239: }
240:
241: /* (non-Javadoc)
242: * @see java.util.Set#contains(java.lang.Object)
243: */
244: public boolean contains(TType t) {
245: if (isUniverse())
246: return true;
247: return fMembers.contains(t);
248: }
249:
250: /* (non-Javadoc)
251: * @see java.util.Set#remove(java.lang.Object)
252: */
253: public boolean remove(TType t) {
254: if (isUniverse())
255: fMembers = cloneSet(fMembers);
256: return fMembers.remove(t);
257: }
258:
259: private Set cloneSet(Set members) {
260: Set result = new LinkedHashSet();
261: result.addAll(members);
262: return result;
263: }
264:
265: /* (non-Javadoc)
266: * @see java.util.Set#addAll(java.util.Collection)
267: */
268: public boolean addAll(TypeSet s) {
269: if (s instanceof EnumeratedTypeSet) {
270: EnumeratedTypeSet ets = (EnumeratedTypeSet) s;
271:
272: return fMembers.addAll(ets.fMembers);
273: } else {
274: EnumeratedTypeSet ets = s.enumerate();
275:
276: return fMembers.addAll(ets.fMembers);
277: }
278: }
279:
280: public TypeSet addedTo(TypeSet that) {
281: EnumeratedTypeSet result = new EnumeratedTypeSet(
282: getTypeSetEnvironment());
283:
284: result.addAll(this );
285: result.addAll(that);
286: result.initComplete();
287: return result;
288: }
289:
290: /* (non-Javadoc)
291: * @see java.util.Set#containsAll(java.util.Collection)
292: */
293: public boolean containsAll(TypeSet s) {
294: if (isUniverse())
295: return true;
296: if (s.isUniverse())
297: return false;
298: EnumeratedTypeSet ets = s.enumerate();
299:
300: return fMembers.containsAll(ets.fMembers);
301: }
302:
303: /* (non-Javadoc)
304: * @see java.util.Set#removeAll(java.util.Collection)
305: */
306: public boolean removeAll(EnumeratedTypeSet s) {
307: if (isUniverse())
308: fMembers = cloneSet(fMembers);
309: return fMembers.removeAll(s.fMembers);
310: }
311:
312: /* (non-Javadoc)
313: * @see java.util.Set#retainAll(java.util.Collection)
314: */
315: public boolean retainAll(TypeSet s) {
316: if (s.isUniverse())
317: return false;
318:
319: EnumeratedTypeSet ets = (EnumeratedTypeSet) s;
320:
321: if (isUniverse()) {
322: fMembers = cloneSet(ets.fMembers);
323: return true;
324: } else
325: return fMembers.retainAll(ets.fMembers);
326: }
327:
328: /* (non-Javadoc)
329: * @see org.eclipse.jdt.internal.corext.refactoring.typeconstraints.typesets.TypeSet#isSingleton()
330: */
331: public boolean isSingleton() {
332: return fMembers.size() == 1;
333: }
334:
335: /* (non-Javadoc)
336: * @see org.eclipse.jdt.internal.corext.refactoring.typeconstraints.typesets.TypeSet#anyMember()
337: */
338: public TType anyMember() {
339: return (TType) fMembers.iterator().next();
340: }
341:
342: /* (non-Javadoc)
343: * @see org.eclipse.jdt.internal.corext.refactoring.typeconstraints.typesets.TypeSet#upperBound()
344: */
345: public TypeSet upperBound() {
346: if (fMembers.size() == 1)
347: return new SingletonTypeSet((TType) fMembers.iterator()
348: .next(), getTypeSetEnvironment());
349: if (fMembers.contains(getJavaLangObject()))
350: return new SingletonTypeSet(getJavaLangObject(),
351: getTypeSetEnvironment());
352:
353: EnumeratedTypeSet result = new EnumeratedTypeSet(
354: getTypeSetEnvironment());
355:
356: // Add to result each element of fMembers that has no proper supertype in fMembers
357: result.fMembers.addAll(fMembers);
358: for (Iterator iter = fMembers.iterator(); iter.hasNext();) {
359: TType t = (TType) iter.next();
360:
361: if (t.isArrayType()) {
362: ArrayType at = (ArrayType) t;
363: int numDims = at.getDimensions();
364: for (Iterator subIter = TTypes
365: .getAllSubTypesIterator(at.getElementType()); subIter
366: .hasNext();) {
367: result.fMembers.remove(TTypes.createArrayType(
368: ((TType) subIter.next()), numDims));
369: }
370: } else {
371: for (Iterator iterator = TTypes
372: .getAllSubTypesIterator(t); iterator.hasNext();) {
373: result.fMembers.remove(iterator.next());
374: }
375: }
376: }
377: result.initComplete();
378: return result;
379: }
380:
381: /* (non-Javadoc)
382: * @see org.eclipse.jdt.internal.corext.refactoring.typeconstraints.typesets.TypeSet#lowerBound()
383: */
384: public TypeSet lowerBound() {
385: if (fMembers.size() == 1)
386: return new SingletonTypeSet((TType) fMembers.iterator()
387: .next(), getTypeSetEnvironment());
388:
389: EnumeratedTypeSet result = new EnumeratedTypeSet(
390: getTypeSetEnvironment());
391:
392: // Add to result each element of fMembers that has no proper subtype in fMembers
393: result.fMembers.addAll(fMembers);
394:
395: for (Iterator iter = fMembers.iterator(); iter.hasNext();) {
396: TType t = (TType) iter.next();
397:
398: // java.lang.Object is only in the lower bound if fMembers consists
399: // of only java.lang.Object, but that case is handled above.
400: if (t.equals(getJavaLangObject())) {
401: result.fMembers.remove(t);
402: continue;
403: }
404:
405: if (t instanceof ArrayType) {
406: ArrayType at = (ArrayType) t;
407: int numDims = at.getDimensions();
408: for (Iterator super Iter = TTypes
409: .getAllSuperTypesIterator(at.getElementType()); super Iter
410: .hasNext();) {
411: result.fMembers.remove(TTypes.createArrayType(
412: ((TType) super Iter.next()), numDims));
413: }
414: } else {
415: for (Iterator iterator = TTypes
416: .getAllSuperTypesIterator(t); iterator
417: .hasNext();) {
418: result.fMembers.remove(iterator.next());
419: }
420: }
421: }
422: if (result.size() > 0)
423: return result;
424: else
425: return getTypeSetEnvironment().getEmptyTypeSet();
426: }
427:
428: /* (non-Javadoc)
429: * @see org.eclipse.jdt.internal.corext.refactoring.typeconstraints.typesets.TypeSet#hasUniqueLowerBound()
430: */
431: public boolean hasUniqueLowerBound() {
432: return fMembers.size() == 1;
433: }
434:
435: /* (non-Javadoc)
436: * @see org.eclipse.jdt.internal.corext.refactoring.typeconstraints.typesets.TypeSet#hasUniqueUpperBound()
437: */
438: public boolean hasUniqueUpperBound() {
439: return fMembers.size() == 1;
440: }
441:
442: /* (non-Javadoc)
443: * @see org.eclipse.jdt.internal.corext.refactoring.typeconstraints.typesets.TypeSet#uniqueLowerBound()
444: */
445: public TType uniqueLowerBound() {
446: if (fMembers.size() == 1)
447: return (TType) fMembers.iterator().next();
448: return null;
449: }
450:
451: /* (non-Javadoc)
452: * @see org.eclipse.jdt.internal.corext.refactoring.typeconstraints.typesets.TypeSet#uniqueUpperBound()
453: */
454: public TType uniqueUpperBound() {
455: if (fMembers.size() == 1)
456: return (TType) fMembers.iterator().next();
457: return null;
458: }
459:
460: /* (non-Javadoc)
461: * @see java.util.Set#iterator()
462: */
463: public Iterator iterator() {
464: return fMembers.iterator();
465: }
466:
467: /* (non-Javadoc)
468: * @see java.util.Set#toArray(java.lang.Object[])
469: */
470: public TType[] toArray(TType[] a) {
471: return (TType[]) fMembers.toArray(a);
472: }
473:
474: /**
475: * Limits the display of set elements to the first sMaxElements.
476: */
477: private static final int sMaxElements = 10; // Integer.MAX_VALUE;
478:
479: /*
480: * (non-Javadoc)
481: * @see java.lang.Object#toString()
482: */
483: public String toString() {
484: StringBuffer b = new StringBuffer();
485: b.append("{" + fID + ":"); //$NON-NLS-1$ //$NON-NLS-2$
486: if (isUniverse())
487: b.append(" <universe>"); //$NON-NLS-1$
488: else {
489: int count = 0;
490: Iterator iter;
491: for (iter = iterator(); iter.hasNext()
492: && count < sMaxElements; count++) {
493: TType type = (TType) iter.next();
494: b.append(' ').append(type.getPrettySignature());
495: if (iter.hasNext())
496: b.append(',');
497: }
498: if (iter.hasNext())
499: b.append(" ..."); //$NON-NLS-1$
500: }
501: b.append(" }"); //$NON-NLS-1$
502: return b.toString();
503: }
504:
505: /* (non-Javadoc)
506: * @see org.eclipse.jdt.internal.corext.refactoring.typeconstraints.typesets.TypeSet#enumerate()
507: */
508: public EnumeratedTypeSet enumerate() {
509: return this ; // (EnumeratedTypeSet) makeClone();
510: }
511:
512: public void initComplete() {
513: Assert.isTrue(!fMembers.isEmpty());
514: }
515:
516: }
|