java: adds MessagePackNullable annotation

This commit is contained in:
frsyuki 2010-11-09 02:46:23 +09:00
parent 517509db6e
commit 33b43d03ac
3 changed files with 187 additions and 5 deletions

View File

@ -0,0 +1,28 @@
//
// MessagePack for Java
//
// Copyright (C) 2009-2010 FURUHASHI Sadayuki
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
//
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.FIELD)
@Retention(RetentionPolicy.RUNTIME)
public @interface MessagePackNullable {
}

View File

@ -39,7 +39,9 @@ import org.msgpack.Packer;
import org.msgpack.Template;
import org.msgpack.Unpacker;
import org.msgpack.annotation.MessagePackOptional;
import org.msgpack.annotation.MessagePackNullable;
import org.msgpack.template.OptionalTemplate;
import org.msgpack.template.NullableTemplate;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
@ -253,7 +255,6 @@ class DynamicCodeGen extends DynamicCodeGenBase implements Constants {
}
Template createTemplate(Field field) {
boolean isOptional = isAnnotated(field, MessagePackOptional.class);
Class<?> c = field.getType();
Template tmpl = null;
if (List.class.isAssignableFrom(c) || Map.class.isAssignableFrom(c)) {
@ -261,12 +262,15 @@ class DynamicCodeGen extends DynamicCodeGenBase implements Constants {
} else {
tmpl = createTemplate(c);
}
if (isOptional) {
// for pack
if (isAnnotated(field, MessagePackOptional.class)) {
// @Optional types
return new OptionalTemplate(tmpl);
} else {
return tmpl;
}
if (!c.isPrimitive() && isAnnotated(field, MessagePackNullable.class)) {
// @Nullable reference types
return new NullableTemplate(tmpl);
}
return tmpl;
}
private boolean isAnnotated(Field field, Class<? extends Annotation> with) {

View File

@ -0,0 +1,150 @@
package org.msgpack;
import org.msgpack.*;
import org.msgpack.object.*;
import org.msgpack.annotation.*;
import static org.msgpack.Templates.*;
import java.io.*;
import java.util.*;
import java.math.BigInteger;
import org.junit.Test;
import junit.framework.TestCase;
public class TestAnnotations extends TestCase {
@MessagePackMessage
public static class MyClassVersion1 {
// required field, not nullable.
public String name;
// required and nullable field.
@MessagePackNullable
public String nickname;
}
@MessagePackMessage
public static class MyClassVersion2 {
public String name;
@MessagePackNullable
public String nickname;
// adds an optional field on version 2.
@MessagePackOptional
public int age = -1;
}
@MessagePackMessage
public static class MyClassVersion3 {
public String name;
@MessagePackNullable
public String nickname;
// adds required fields on version 3, then
// this class is NOT compatible with version 1.
public int age;
// optional field is nullable.
@MessagePackOptional
public String school;
}
@Test
public void testBackwardCompatibility() throws Exception {
MyClassVersion1 v1 = new MyClassVersion1();
v1.name = "Sadayuki Furuhashi";
v1.nickname = "frsyuki";
byte[] bytes = MessagePack.pack(v1);
MyClassVersion2 v2 = MessagePack.unpack(bytes, MyClassVersion2.class);
assertEquals(v1.name, v2.name);
assertEquals(v1.nickname, v2.nickname);
assertEquals(v2.age, -1);
}
@Test
public void testForwardCompatibility() throws Exception {
MyClassVersion2 v2 = new MyClassVersion2();
v2.name = "Sadayuki Furuhashi";
v2.nickname = "frsyuki";
v2.age = 23;
byte[] bytes = MessagePack.pack(v2);
MyClassVersion1 v1 = MessagePack.unpack(bytes, MyClassVersion1.class);
assertEquals(v2.name, v1.name);
assertEquals(v2.nickname, v1.nickname);
}
@Test
public void testNullFields01() throws Exception {
MyClassVersion1 src = new MyClassVersion1();
src.name = "Sadayuki Furuhashi";
src.nickname = null;
byte[] bytes = MessagePack.pack(src);
MyClassVersion1 dst = MessagePack.unpack(bytes, MyClassVersion1.class);
assertEquals(dst.name, src.name);
assertEquals(dst.nickname, src.nickname);
}
@Test
public void testNullFields02() throws Exception {
MyClassVersion1 src = new MyClassVersion1();
src.name = null;
src.nickname = "frsyuki";
try {
byte[] bytes = MessagePack.pack(src);
} catch (Exception e) {
assertTrue(true);
return;
}
assertTrue(false);
}
@Test
public void testNullFields03() throws Exception {
List<String> src = new ArrayList<String>();
src.add(null);
src.add("frsyuki");
byte[] bytes = MessagePack.pack(src);
try {
MyClassVersion1 dst = MessagePack.unpack(bytes, MyClassVersion1.class);
} catch (Exception e) {
assertTrue(true);
return;
}
assertTrue(false);
}
@Test
public void testNullFields04() throws Exception {
MyClassVersion3 src = new MyClassVersion3();
src.name = "Sadayuki Furuhashi";
src.nickname = null;
src.age = 23;
src.school = null;
byte[] bytes = MessagePack.pack(src);
MyClassVersion3 dst = MessagePack.unpack(bytes, MyClassVersion3.class);
assertEquals(dst.name, src.name);
assertEquals(dst.nickname, src.nickname);
}
}