content: /*******************************************************************************
   * Copyright (c) 2000, 2007 IBM Corporation and others.
   * All rights reserved. This program and the accompanying materials
   * are made available under the terms of the Eclipse Public License v1.0
   * which accompanies this distribution, and is available at
   * http://www.eclipse.org/legal/epl-v10.html
   *
   * Contributors:
   *   Robert M. Fuhrer (rfuhrer@watson.ibm.com), IBM Corporation - initial API and implementation
   *******************************************************************************/
  package org.eclipse.wst.jsdt.internal.corext.refactoring.typeconstraints.typesets;
  
  import java.util.Iterator;
  
  import org.eclipse.wst.jsdt.internal.corext.refactoring.typeconstraints.types.ArrayType;
  import org.eclipse.wst.jsdt.internal.corext.refactoring.typeconstraints.types.TType;
  import org.eclipse.wst.jsdt.internal.corext.refactoring.typeconstraints2.TTypes;
  
  /**
   * Represents the super-types of a set of array types. Special because this set
   * always includes Object.
   */
  public class ArraySuperTypeSet extends ArrayTypeSet {
  	public ArraySuperTypeSet(TypeSet s) {
  		super(s.getTypeSetEnvironment());
  		if (s instanceof SuperTypesOfSingleton || s instanceof SuperTypesSet)
  			fElemTypeSet= s.lowerBound(); // optimization: array-super(super(s)) == array-super(s)
  		else
  			fElemTypeSet= s;
  	}
  
  	/* (non-Javadoc)
  	 * @see org.eclipse.wst.jsdt.internal.corext.refactoring.typeconstraints.typesets.ArrayTypeSet#anyMember()
  	 */
  	public TType anyMember() {
  		return getJavaLangObject();
  	}
  
  	/* (non-Javadoc)
  	 * @see org.eclipse.wst.jsdt.internal.corext.refactoring.typeconstraints.typesets.ArrayTypeSet#contains(TType)
  	 */
  	public boolean contains(TType t) {
  		if (t.equals(getJavaLangObject())) return true;
  		if (!(t instanceof ArrayType))
  			return false;
  
  		ArrayType at= (ArrayType) t;
  		TType atElemType= at.getComponentType();
  
  		if (fElemTypeSet.contains(atElemType)) // try to avoid enumeration
  			return true;
  
  		for(Iterator iter= fElemTypeSet.iterator(); iter.hasNext(); ) {
  			TType elemType= (TType) iter.next();
  
  			if (TTypes.canAssignTo(elemType, atElemType))
  				return true;
  		}
  		return false;
  	}
  
  	/* (non-Javadoc)
  	 * @see org.eclipse.wst.jsdt.internal.corext.refactoring.typeconstraints.typesets.ArrayTypeSet#containsAll(org.eclipse.wst.jsdt.internal.corext.refactoring.typeconstraints.typesets.TypeSet)
  	 */
  	public boolean containsAll(TypeSet s) {
  		if (s instanceof ArraySuperTypeSet) {
  			ArraySuperTypeSet ats= (ArraySuperTypeSet) s;
  
  			return fElemTypeSet.containsAll(ats.fElemTypeSet);
  		} else if (s instanceof ArrayTypeSet) {
  			ArrayTypeSet ats= (ArrayTypeSet) s;
  
  			return fElemTypeSet.containsAll(ats.fElemTypeSet);
  		} else
  			return enumerate().containsAll(s);
  	}
  
  	/* (non-Javadoc)
  	 * @see org.eclipse.wst.jsdt.internal.corext.refactoring.typeconstraints.typesets.TypeSet#specialCasesIntersectedWith(org.eclipse.wst.jsdt.internal.corext.refactoring.typeconstraints.typesets.TypeSet)
  	 */
  	protected TypeSet specialCasesIntersectedWith(TypeSet s2) {
  		if (s2 instanceof ArraySuperTypeSet) {
  			ArraySuperTypeSet ats2= (ArraySuperTypeSet) s2;
  
  			if (ats2.fElemTypeSet.isUniverse())
  				return new ArraySuperTypeSet(fElemTypeSet);
  		} else if (s2 instanceof ArrayTypeSet) {
  			ArrayTypeSet ats2= (ArrayTypeSet) s2;
  
  			if (ats2.fElemTypeSet.isUniverse())
  				return new ArrayTypeSet(fElemTypeSet); // intersection doesn't include Object, which is in 'this'
  		}
  		return super.specialCasesIntersectedWith(s2);
  	}
  
  	private EnumeratedTypeSet fEnumCache= null;
  
  	/* (non-Javadoc)
  	 * @see org.eclipse.wst.jsdt.internal.corext.refactoring.typeconstraints.typesets.ArrayTypeSet#enumerate()
  	 */
  	public EnumeratedTypeSet enumerate() {
  		if (fEnumCache == null) {
  			fEnumCache= new EnumeratedTypeSet(getTypeSetEnvironment());
  			TypeSet elemSupers= fElemTypeSet.superTypes();
  
  			for(Iterator iter= elemSupers.iterator(); iter.hasNext(); ) {
  				TType elemSuper= (TType) iter.next();
  
  				fEnumCache.add(TTypes.createArrayType(elemSuper, 1));
  			}
  
  			fEnumCache.add(getJavaLangObject());
  			fEnumCache.initComplete();
  		}
  		return fEnumCache;
  	}
  
  	/* (non-Javadoc)
  	 * @see org.eclipse.wst.jsdt.internal.corext.refactoring.typeconstraints.typesets.ArrayTypeSet#hasUniqueUpperBound()
  	 */
  	public boolean hasUniqueUpperBound() {
  		return true; // Object is the unique upper bound of any set of array types
  	}
  
  	/* (non-Javadoc)
  	 * @see org.eclipse.wst.jsdt.internal.corext.refactoring.typeconstraints.typesets.ArrayTypeSet#isSingleton()
  	 */
  	public boolean isSingleton() {
  		return false;
  	}
  
  	/* (non-Javadoc)
  	 * @see org.eclipse.wst.jsdt.internal.corext.refactoring.typeconstraints.typesets.ArrayTypeSet#isUniverse()
  	 */
  	public boolean isUniverse() {
  		return false;
  	}
  
  	/* (non-Javadoc)
  	 * @see org.eclipse.wst.jsdt.internal.corext.refactoring.typeconstraints.typesets.ArrayTypeSet#iterator()
  	 */
  	public Iterator iterator() {
  		return enumerate().iterator();
  	}
  
  	/* (non-Javadoc)
  	 * @see org.eclipse.wst.jsdt.internal.corext.refactoring.typeconstraints.typesets.ArrayTypeSet#makeClone()
  	 */
  	public TypeSet makeClone() {
  		return new ArraySuperTypeSet(fElemTypeSet);
  	}
  
  	/* (non-Javadoc)
  	 * @see org.eclipse.wst.jsdt.internal.corext.refactoring.typeconstraints.typesets.TypeSet#superTypes()
  	 */
  	public TypeSet superTypes() {
  		return makeClone();
  	}
  
  	/* (non-Javadoc)
  	 * @see org.eclipse.wst.jsdt.internal.corext.refactoring.typeconstraints.typesets.ArrayTypeSet#uniqueUpperBound()
  	 */
  	public TType uniqueUpperBound() {
  		return getJavaLangObject();
  	}
  
  	/* (non-Javadoc)
  	 * @see org.eclipse.wst.jsdt.internal.corext.refactoring.typeconstraints.typesets.ArrayTypeSet#upperBound()
  	 */
  	public TypeSet upperBound() {
  		return new SingletonTypeSet(getJavaLangObject(), getTypeSetEnvironment());
  	}
  
  	/* (non-Javadoc)
  	 * @see org.eclipse.wst.jsdt.internal.corext.refactoring.typeconstraints.typesets.ArrayTypeSet#equals(java.lang.Object)
  	 */
  	public boolean equals(Object obj) {
  		if (obj == this) return true;
  		if (obj instanceof ArraySuperTypeSet) {
  			ArraySuperTypeSet other= (ArraySuperTypeSet) obj;
  
  			return fElemTypeSet.equals(other.fElemTypeSet);
  		}
  		return false;
  	}
  
  	/* (non-Javadoc)
  	 * @see org.eclipse.wst.jsdt.internal.corext.refactoring.typeconstraints.typesets.TypeSet#subTypes()
  	 */
  	public TypeSet subTypes() {
  		return getTypeSetEnvironment().getUniverseTypeSet();
  	}
  
  	public String toString() {
  		return "{" + fID + ": array-super(" + fElemTypeSet + ")}"; //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$
  	}
  }
  