/*******************************************************************************
 * Copyright (c) 2000, 2008 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:
 *     IBM Corporation - initial API and implementation
 *******************************************************************************/
package java.util;

public abstract class AbstractMap implements Map {
	
	class KeySetIterator implements Iterator {
		Iterator entrySetIter;
		
		public KeySetIterator() {
			entrySetIter = entrySet().iterator();
		}
		
		public boolean hasNext() {
			return entrySetIter.hasNext();
		}

		public Object next() throws NoSuchElementException {
			Entry entry = (Entry)entrySetIter.next();
			return entry.getKey();
		}

		public void remove() throws UnsupportedOperationException, IllegalStateException {
			entrySetIter.remove();
		}		
	}
	
	class ValueSetIterator implements Iterator {
		Iterator entrySetIter;
		
		public ValueSetIterator() {
			entrySetIter = entrySet().iterator();
		}
		
		public boolean hasNext() {
			return entrySetIter.hasNext();
		}

		public Object next() throws NoSuchElementException {
			Entry entry = (Entry)entrySetIter.next();
			return entry.getValue();
		}

		public void remove() throws UnsupportedOperationException, IllegalStateException {
			entrySetIter.remove();
		}		
	}

protected AbstractMap() {
}

public void clear() {
	entrySet().clear();
}

protected Object clone() throws CloneNotSupportedException {
	return super.clone();
}

public boolean containsKey(Object key) {
	Iterator iter = entrySet().iterator();
	while (iter.hasNext()) {
		Entry entry = (Entry)iter.next();
		if (key == null ? entry.getKey() == null : key.equals(entry.getKey())) {
			return true;
		}
	}
	return false;
}

public boolean containsValue(Object value) {
	Iterator iter = entrySet().iterator();
	while (iter.hasNext()) {
		Entry entry = (Entry)iter.next();
		if (value == null ? entry.getValue() == null : value.equals(entry.getValue())) {
			return true;
		}
	}
	return false;
}

public abstract Set entrySet();

public boolean equals(Object other) {
	if (this == other) return true;
	if (!(other instanceof Map)) return false;
	Map map = (Map)other;
	if (size() != map.size()) return false;
	//TODO
//	Iterator iter = entrySet().iterator();
//	while (iter.hasNext()) {
//		Entry entry = (Entry)iter.next();
//		Object value = get(key);
//		Object otherValue = map.get(key);
//		if (value == null ? otherValue == null : value.equals(otherValue)) {
//			return false;
//		}
//	}
	return true;
}

public Object get(Object key) {
	Iterator iter = entrySet().iterator();
	while (iter.hasNext()) {
		Entry entry = (Entry)iter.next();
		if (key == null ? entry.getKey() == null : key.equals(entry.getKey())) {
			return entry.getValue();
		}
	}
	return null;
}

public int hashCode() {
	Iterator iter = entrySet().iterator();
	int hash = 0;
	while (iter.hasNext()) {
		Entry entry = (Entry)iter.next();
		hash += entry.hashCode();
	}
	return hash;
}

public boolean isEmpty() {
	return size() == 0;
}

public Set keySet() {
	return new AbstractSet() {
		
		public boolean contains(Object o) {
			return containsKey(o);
		}

		public Iterator iterator() {
			return new KeySetIterator();
		}

		public int size() {
			return AbstractMap.this.size();
		}
		
	};
}

public Object put(Object key, Object value) {
	throw new UnsupportedOperationException();
}

public void putAll(Map t) {
	Iterator iter = t.entrySet().iterator();
	while (iter.hasNext()) {
		Entry entry = (Entry)iter.next();
		put(entry.getKey(), entry.getValue());
	}
}

public Object remove(Object key) {
	Object result = null;
	Iterator iter = entrySet().iterator();
	while (iter.hasNext()) {
		Entry entry = (Entry)iter.next();
		if (key == null ? entry.getKey() == null : key.equals(entry.getKey())) {
			result = entry.getValue();
			break;
		}
	}
	return result;
}

public int size() {
	return entrySet().size();
}

public Collection values() {
	return new AbstractSet() {
		
		public boolean contains(Object o) {
			return containsValue(o);
		}

		public Iterator iterator() {
			return new ValueSetIterator();
		}

		public int size() {
			return AbstractMap.this.size();
		}
		
	};
}
	
}
