package org.psjava.ds.map;

import java.util.Iterator;

import org.psjava.javautil.AssertStatus;
import org.psjava.javautil.ConvertedDataIterator;
import org.psjava.javautil.DataConverter;
import org.psjava.javautil.EqualityTester;
import org.psjava.javautil.StrictEqualityTester;
import org.psjava.math.PairHash;


public class MutableMapUsingJavaMap {
	
	public static <K, V> MutableMap<K, V> create(final java.util.Map<K, V> map) {
		return new MutableMap<K, V>() {

			@Override
			public boolean containsKey(K key) {
				return map.containsKey(key);
			}

			@Override
			public V get(K key) {
				AssertStatus.assertTrue(containsKey(key));
				return map.get(key);
			}

			@Override
			public V get(K key, V def) {
				if (!containsKey(key))
					return def;
				return map.get(key);
			}

			@Override
			public Iterable<K> keys() {
				return map.keySet();
			}

			@Override
			public void put(K key, V value) {
				map.put(key, value);
			}

			@Override
			public Iterable<V> values() {
				return map.values();
			}

			@Override
			public void clear() {
				map.clear();
			}

			@Override
			public boolean isEmpty() {
				return map.isEmpty();
			}

			@Override
			public Iterator<MapEntry<K, V>> iterator() {
				return ConvertedDataIterator.create(map.entrySet().iterator(), new DataConverter<java.util.Map.Entry<K, V>, MapEntry<K, V>>() {
					@Override
					public MapEntry<K, V> convert(java.util.Map.Entry<K, V> e) {
						return new EntryWrapper<K, V>(e);
					}
				});
			}

			@Override
			public int size() {
				return map.size();
			}

			@Override
			public void remove(K key) {
				map.remove(key);
			}

			@Override
			public String toString() {
				return map.toString();
			}

		};
	}

	private static class EntryWrapper<K, V> implements MapEntry<K, V>, EqualityTester<EntryWrapper<K, V>> {
		private java.util.Map.Entry<K, V> e;
		private EntryWrapper(java.util.Map.Entry<K, V> e) {
			this.e = e;
		}
		@Override
		public K getKey() {
			return e.getKey();
		}
		@Override
		public V getValue() { 
			return e.getValue();
		}
		@Override
		public boolean equals(Object obj) {
			return StrictEqualityTester.areEqual(this, obj, this);
		}
		@Override
		public boolean areEqual(EntryWrapper<K, V> o1, EntryWrapper<K, V> o2) {
			return o1.getKey().equals(o2.getKey()) && o1.getValue().equals(o2.getValue());
		}
		@Override
		public int hashCode() {
			return PairHash.hash(getKey().hashCode(), getValue().hashCode());
		}
	}

}

@@ -308,17 +308,16 @@
 rHash;%0A%0A
-%0A
 public c
@@ -350,10 +350,9 @@
 p %7B%0A
-%09
 %0A
+
 %09pub
@@ -586,24 +586,160 @@
 et(K key) %7B%0A
+%09%09%09%09V r = map.get(key);%0A%09%09%09%09if (r != null) %7B%0A%09%09%09%09%09return r;%0A%09%09%09%09%7D else %7B // because java map's get returns null even if value is null.%0A%09
 %09%09%09%09AssertSt
@@ -774,35 +774,64 @@
 key)
+, %22the key in not int the map%22
 );%0A%09%09%09%09
+%09
 return 
-map.get(key);
+null;%0A%09%09%09%09%7D
 %0A%09%09%09
@@ -2022,16 +2022,17 @@
 , V%3E e;%0A
+%0A
 %09%09privat
@@ -2092,24 +2092,25 @@
 .e = e;%0A%09%09%7D%0A
+%0A
 %09%09@Override%0A
@@ -2149,32 +2149,33 @@
 e.getKey();%0A%09%09%7D%0A
+%0A
 %09%09@Override%0A%09%09pu
@@ -2193,17 +2193,16 @@
 alue() %7B
- 
 %0A%09%09%09retu
@@ -2218,24 +2218,25 @@
 alue();%0A%09%09%7D%0A
+%0A
 %09%09@Override%0A
@@ -2331,24 +2331,25 @@
  this);%0A%09%09%7D%0A
+%0A
 %09%09@Override%0A
@@ -2504,20 +2504,21 @@
 lue());%0A
-
 %09%09%7D%0A
+%0A
 %09%09@Overr

improve speed of map