From dfb97e7961e7947d09240f18234a5aaced6e2d6f Mon Sep 17 00:00:00 2001
From: Muga Nishizawa <muga@f11vm.(none)>
Date: Mon, 27 Sep 2010 10:00:47 +0900
Subject: [PATCH] java: adds several annotations in an org.msgpack.annotation
 package and edits Packer.java and its test program

---
 .../main/java/org/msgpack/CustomPacker.java   | 17 ++++-----
 java/src/main/java/org/msgpack/Packer.java    | 38 +++++++++++++++----
 .../annotation/MessagePackDelegate.java       | 12 ++++++
 .../annotation/MessagePackMessage.java        | 12 ++++++
 .../annotation/MessagePackOrdinalEnum.java    | 12 ++++++
 .../msgpack/TestReflectionPackerTemplate.java | 28 ++++++++++++++
 6 files changed, 101 insertions(+), 18 deletions(-)
 create mode 100644 java/src/main/java/org/msgpack/annotation/MessagePackDelegate.java
 create mode 100644 java/src/main/java/org/msgpack/annotation/MessagePackMessage.java
 create mode 100644 java/src/main/java/org/msgpack/annotation/MessagePackOrdinalEnum.java

diff --git a/java/src/main/java/org/msgpack/CustomPacker.java b/java/src/main/java/org/msgpack/CustomPacker.java
index f0c6b62c..743a52bb 100644
--- a/java/src/main/java/org/msgpack/CustomPacker.java
+++ b/java/src/main/java/org/msgpack/CustomPacker.java
@@ -17,23 +17,20 @@
 //
 package org.msgpack;
 
-import java.util.Map;
-import java.util.HashMap;
+import java.util.concurrent.ConcurrentHashMap;
 
-// FIXME package private?
 public class CustomPacker {
-	public static void register(Class target, MessagePacker converter) {
-		map.put(target, converter);
+	private static ConcurrentHashMap<Class<?>, MessagePacker> map = new ConcurrentHashMap<Class<?>, MessagePacker>();
+
+	public static void register(Class<?> target, MessagePacker packer) {
+		map.putIfAbsent(target, packer);
 	}
 
-	public static MessagePacker get(Class target) {
+	public static MessagePacker get(Class<?> target) {
 		return map.get(target);
 	}
 
-	public static boolean isRegistered(Class target) {
+	public static boolean isRegistered(Class<?> target) {
 		return map.containsKey(target);
 	}
-
-	private static Map<Class, MessagePacker> map = new HashMap<Class, MessagePacker>();
 }
-
diff --git a/java/src/main/java/org/msgpack/Packer.java b/java/src/main/java/org/msgpack/Packer.java
index dd8cdee2..2f34bde8 100644
--- a/java/src/main/java/org/msgpack/Packer.java
+++ b/java/src/main/java/org/msgpack/Packer.java
@@ -22,8 +22,13 @@ import java.io.IOException;
 import java.nio.ByteBuffer;
 import java.util.List;
 import java.util.Map;
+import java.lang.annotation.Annotation;
 import java.math.BigInteger;
 
+import org.msgpack.annotation.MessagePackDelegate;
+import org.msgpack.annotation.MessagePackMessage;
+import org.msgpack.annotation.MessagePackOrdinalEnum;
+
 /**
  * Packer enables you to serialize objects into OutputStream.
  *
@@ -473,19 +478,36 @@ public class Packer {
 			return packDouble((Double)o);
 		} else if(o instanceof BigInteger) {
 			return packBigInteger((BigInteger)o);
-		}
+		} 
 
-		Class klass = o.getClass();
-
-		MessagePacker packer = CustomPacker.get(klass);
-		if(packer != null) {
+		Class<?> klass = o.getClass();
+		if (CustomPacker.isRegistered(klass)) {
+			MessagePacker packer = CustomPacker.get(klass);
 			packer.pack(this, o);
 			return this;
+		} else if (isAnnotated(klass, MessagePackMessage.class)) {
+			MessagePacker packer = ReflectionPacker.create(klass);
+			CustomPacker.register(klass, packer);
+			packer.pack(this, o);
+			return this;
+		} else if (isAnnotated(klass, MessagePackDelegate.class)) {
+			throw new UnsupportedOperationException("not supported yet. : " + klass.getName());
+		} else if (isAnnotated(klass, MessagePackOrdinalEnum.class)) {
+			throw new UnsupportedOperationException("not supported yet. : " + klass.getName());
 		}
-
-		// FIXME check annotations -> code generation -> CustomMessage.registerPacker
+//      Class<?> klass = o.getClass();
+//		MessagePacker packer = CustomPacker.get(klass);
+//		if(packer != null) {
+//			packer.pack(this, o);
+//			return this;
+//		}
+//
+//		// FIXME check annotations -> code generation -> CustomMessage.registerPacker
 
 		throw new MessageTypeException("unknown object "+o+" ("+o.getClass()+")");
 	}
+	
+	static boolean isAnnotated(Class<?> target, Class<? extends Annotation> with) {
+		return target.getAnnotation(with) != null;
+	}
 }
-
diff --git a/java/src/main/java/org/msgpack/annotation/MessagePackDelegate.java b/java/src/main/java/org/msgpack/annotation/MessagePackDelegate.java
new file mode 100644
index 00000000..2a72d730
--- /dev/null
+++ b/java/src/main/java/org/msgpack/annotation/MessagePackDelegate.java
@@ -0,0 +1,12 @@
+package org.msgpack.annotation;
+
+import java.lang.annotation.ElementType;
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+import java.lang.annotation.Target;
+
+@Target(ElementType.TYPE)
+@Retention(RetentionPolicy.RUNTIME)
+public @interface MessagePackDelegate {
+
+}
diff --git a/java/src/main/java/org/msgpack/annotation/MessagePackMessage.java b/java/src/main/java/org/msgpack/annotation/MessagePackMessage.java
new file mode 100644
index 00000000..6efeb9d3
--- /dev/null
+++ b/java/src/main/java/org/msgpack/annotation/MessagePackMessage.java
@@ -0,0 +1,12 @@
+package org.msgpack.annotation;
+
+import java.lang.annotation.ElementType;
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+import java.lang.annotation.Target;
+
+@Target(ElementType.TYPE)
+@Retention(RetentionPolicy.RUNTIME)
+public @interface MessagePackMessage {
+
+}
diff --git a/java/src/main/java/org/msgpack/annotation/MessagePackOrdinalEnum.java b/java/src/main/java/org/msgpack/annotation/MessagePackOrdinalEnum.java
new file mode 100644
index 00000000..4b0d9bb2
--- /dev/null
+++ b/java/src/main/java/org/msgpack/annotation/MessagePackOrdinalEnum.java
@@ -0,0 +1,12 @@
+package org.msgpack.annotation;
+
+import java.lang.annotation.ElementType;
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+import java.lang.annotation.Target;
+
+@Target(ElementType.TYPE)
+@Retention(RetentionPolicy.RUNTIME)
+public @interface MessagePackOrdinalEnum {
+
+}
diff --git a/java/src/test/java/org/msgpack/TestReflectionPackerTemplate.java b/java/src/test/java/org/msgpack/TestReflectionPackerTemplate.java
index f361eb46..27edde1f 100644
--- a/java/src/test/java/org/msgpack/TestReflectionPackerTemplate.java
+++ b/java/src/test/java/org/msgpack/TestReflectionPackerTemplate.java
@@ -42,5 +42,33 @@ public class TestReflectionPackerTemplate {
 		assertEquals(src.s1, dst.s1);
 		assertEquals(src.s2, dst.s2);
 	}
+
+	@Test
+	public void testPackConvert02() throws Exception {
+		tString();  // FIXME link StringTemplate
+
+		ByteArrayOutputStream out = new ByteArrayOutputStream();
+
+		CustomPacker.register(StringFieldClass.class, ReflectionPacker.create(StringFieldClass.class));
+				
+
+		StringFieldClass src = new StringFieldClass();
+
+		src.s1 = "kumofs";
+		src.s2 = "frsyuki";
+
+		new Packer(out).pack(src);
+
+		Template tmpl = ReflectionTemplate.create(StringFieldClass.class);
+
+		ByteArrayInputStream in = new ByteArrayInputStream(out.toByteArray());
+
+		Object obj = tmpl.unpack(new Unpacker(in));
+		assertEquals(obj.getClass(), StringFieldClass.class);
+
+		StringFieldClass dst = (StringFieldClass)obj;
+		assertEquals(src.s1, dst.s1);
+		assertEquals(src.s2, dst.s2);
+	}
 }