package com.googlecode.objectify.test;

import com.googlecode.objectify.Key;
import com.googlecode.objectify.TranslateException;
import com.googlecode.objectify.annotation.Id;
import com.googlecode.objectify.test.entity.Trivial;
import com.googlecode.objectify.test.util.TestBase;
import org.testng.annotations.Test;

import java.util.HashMap;
import java.util.Map;

import static com.googlecode.objectify.test.util.TestObjectifyService.fact;
import static com.googlecode.objectify.test.util.TestObjectifyService.ofy;

/**
 * Test of expando-type maps that hold primitve values
 */
public class EmbeddedMapTests extends TestBase
{
	@com.googlecode.objectify.annotation.Entity
	public static class HasMapLong {
		@Id
		Long id;

		Map<String, Long> primitives = new HashMap<String, Long>();
	}

	@Test
	public void valuesCanBePrimitives() throws Exception {
		fact().register(HasMapLong.class);

		HasMapLong hml = new HasMapLong();
		hml.primitives.put("one", 1L);
		hml.primitives.put("two", 2L);

		HasMapLong fetched = ofy().saveClearLoad(hml);

		assert fetched.primitives.equals(hml.primitives);
	}

	@Test
	public void dotsAreAllowed() {
		fact().register(HasMapLong.class);

		HasMapLong hml = new HasMapLong();
		hml.primitives.put("legal.name", 123L);

		HasMapLong fetched = ofy().saveClearLoad(hml);

		assert fetched.primitives.equals(hml.primitives);
	}

	@Test
	public void nullKeysAreForbidden() {
		fact().register(HasMapLong.class);

		HasMapLong hml = new HasMapLong();
		hml.primitives.put(null, 123L);

		try {
			ofy().save().entity(hml).now();
			assert false;
		}
		catch (TranslateException e) {
			// expected
		}
	}

	@Test
	public void nullValuesWork() throws Exception {
		fact().register(HasMapLong.class);

		HasMapLong hml = new HasMapLong();
		hml.primitives.put("nullvalue", null);

		HasMapLong fetched = ofy().saveClearLoad(hml);
		assert (fetched.primitives.equals(hml.primitives));
	}

	/**
	 * We should be able to store a Key<?> as the EmbedMap key
	 */
	@com.googlecode.objectify.annotation.Entity
	public static class HasMapWithKeyKey {
		@Id
		Long id;

		Map<Key<Trivial>, Long> primitives = new HashMap<>();
	}

	@Test
	public void keyKeyStoresOk() throws Exception {
		fact().register(HasMapWithKeyKey.class);

		HasMapWithKeyKey hml = new HasMapWithKeyKey();
		hml.primitives.put(Key.create(Trivial.class, 123L), 1L);
		hml.primitives.put(Key.create(Trivial.class, 456L), 2L);

		HasMapWithKeyKey fetched = ofy().saveClearLoad(hml);

		assert fetched.primitives.equals(hml.primitives);
	}
}

@@ -102,34 +102,29 @@
 jectify.
-TranslateException
+annotation.Id
 ;%0Aimport
@@ -152,34 +152,101 @@
 tify.annotation.
-Id
+Stringify;%0Aimport com.googlecode.objectify.stringifier.KeyStringifier
 ;%0Aimport com.goo
@@ -778,25 +778,24 @@
 %0A%09%09Long id;%0A
-%0A
 %09%09Map%3CString
@@ -827,28 +827,16 @@
 HashMap%3C
-String, Long
 %3E();%0A%09%7D%0A
@@ -1408,32 +1408,81 @@
 ves);%0A%09%7D%0A%0A%09@Test
+(expectedExceptions = NullPointerException.class)
 %0A%09public void nu
@@ -1618,17 +1618,8 @@
 );%0A%0A
-%09%09try %7B%0A%09
 %09%09of
@@ -1652,81 +1652,8 @@
 ();%0A
-%09%09%09assert false;%0A%09%09%7D%0A%09%09catch (TranslateException e) %7B%0A%09%09%09// expected%0A%09%09%7D%0A
 %09%7D%0A%0A
@@ -1996,16 +1996,36 @@
 dMap key
+ using a Stringifier
 %0A%09 */%0A%09@
@@ -2125,16 +2125,51 @@
 ng id;%0A%0A
+%09%09@Stringify(KeyStringifier.class)%0A
 %09%09Map%3CKe
@@ -2247,19 +2247,24 @@
  key
-KeyStoresOk
+StringifierWorks
 () t

Test for embedded map stringifier