/* Soot - a J*va Optimization Framework
 * Copyright (C) 2003 Ondrej Lhotak
 *
 * This library is free software; you can redistribute it and/or
 * modify it under the terms of the GNU Lesser General Public
 * License as published by the Free Software Foundation; either
 * version 2.1 of the License, or (at your option) any later version.
 *
 * This library is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 * Lesser General Public License for more details.
 *
 * You should have received a copy of the GNU Lesser General Public
 * License along with this library; if not, write to the
 * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
 * Boston, MA 02111-1307, USA.
 */

package soot.jimple.toolkits.pointer;

import soot.*;

import java.util.*;

public class MemoryEfficientRasUnion extends Union {
	HashSet<PointsToSet> subsets;

	public boolean isEmpty() {
		if (subsets == null)
			return true;
		for (PointsToSet subset : subsets) {
			if (!subset.isEmpty())
				return false;
		}
		return true;
	}

	public boolean hasNonEmptyIntersection(PointsToSet other) {
		if (subsets == null)
			return true;
		for (PointsToSet subset : subsets) {
			if (other instanceof Union) {
				if (other.hasNonEmptyIntersection(subset))
					return true;
			} else {
				if (subset.hasNonEmptyIntersection(other))
					return true;
			}
		}
		return false;
	}

	public boolean addAll(PointsToSet s) {
		boolean result;
		
		if (subsets == null)
			subsets = new HashSet<PointsToSet>();
		if (s instanceof MemoryEfficientRasUnion) {
			MemoryEfficientRasUnion meru = (MemoryEfficientRasUnion) s;
			if (meru.subsets == null || subsets.containsAll(meru.subsets)) {
				return false;
			}
			result = subsets.addAll(meru.subsets);
		} else {
			result = subsets.add(s);
		}
		
		return result;
	}

	public Object clone() {
		MemoryEfficientRasUnion ret = new MemoryEfficientRasUnion();
		ret.addAll(this);
		return ret;
	}

	public Set possibleTypes() {
		if (subsets == null) {
			return Collections.EMPTY_SET;
		}
		HashSet ret = new HashSet();
		for (PointsToSet subset : subsets) {
			ret.addAll(subset.possibleTypes());
		}
		return ret;
	}

	/**
	 * {@inheritDoc}
	 */
	public int hashCode() {
		final int PRIME = 31;
		int result = 1;
		result = PRIME * result + ((subsets == null) ? 0 : subsets.hashCode());
		return result;
	}

	/**
	 * {@inheritDoc}
	 */
	public boolean equals(Object obj) {
		if (this == obj)
			return true;
		if (obj == null)
			return false;
		if (getClass() != obj.getClass())
			return false;
		final MemoryEfficientRasUnion other = (MemoryEfficientRasUnion) obj;
		if (subsets == null) {
			if (other.subsets != null)
				return false;
		} else if (!subsets.equals(other.subsets))
			return false;
		return true;
	}

	/**
	 * {@inheritDoc}
	 */
	public String toString() {
		return subsets.toString();
	}

}

@@ -3059,17 +3059,74 @@
 g() %7B%0D%0A%09
-%09
+  if(subsets == null)%7B%0D%0A%09    return %22%5B%5D%22;%0D%0A%09  %7Delse%7B%0D%0A%09%09  
 return s
@@ -3145,16 +3145,21 @@
 ing();%0D%0A
+%09%09%7D%0D%0A
 %09%7D%0D%0A%0D%0A%7D%0D

Fix NullPointerException in MemoryEfficientRasUnion.toString when subsets is null.