From d5e583b09ea084c2e091f2eaf33bbf61866bdc3c Mon Sep 17 00:00:00 2001 From: takeshita <takeshita@geishatokyo.com> Date: Mon, 4 Apr 2011 01:37:24 +0900 Subject: [PATCH 1/2] Implement Scala MessagePack. Change Java MessagePack to fit Scala's. Minor version up for Java's MessagePack. --- java/.settings/org.eclipse.jdt.core.prefs | 6 +- java/msgpack.iml | 17 + java/pom.xml | 18 +- .../main/java/org/msgpack/MessagePack.java | 2 +- .../java/org/msgpack/annotation/Ignore.java | 2 +- .../java/org/msgpack/annotation/Index.java | 2 +- .../msgpack/annotation/MessagePackBeans.java | 35 + .../java/org/msgpack/annotation/Nullable.java | 2 +- .../java/org/msgpack/annotation/Optional.java | 2 +- .../java/org/msgpack/annotation/Required.java | 2 +- .../org/msgpack/template/BeansFieldEntry.java | 149 ++ .../template/BeansFieldEntryReader.java | 174 ++ .../BeansReflectionTemplateBuilder.java | 321 +++ .../java/org/msgpack/template/FieldEntry.java | 143 ++ .../msgpack/template/FieldEntryReader.java | 165 ++ .../java/org/msgpack/template/FieldList.java | 10 +- .../org/msgpack/template/IFieldEntry.java | 25 + .../msgpack/template/IFieldEntryReader.java | 8 + .../template/JavassistTemplateBuilder.java | 513 +--- .../template/ReflectionTemplateBuilder.java | 178 +- .../msgpack/template/TemplateRegistry.java | 47 +- .../builder/ArrayTemplateBuilder.java | 173 ++ .../builder/ArrayTemplateBuilderSelector.java | 35 + .../template/builder/BuilderSelector.java | 27 + .../builder/BuilderSelectorRegistry.java | 213 ++ .../builder/CustomTemplateBuilder.java | 53 + .../template/builder/EnumBuilderSelector.java | 26 + .../MessagePackBeansBuilderSelector.java | 40 + .../MessagePackMessageBuilderSelector.java | 38 + ...MessagePackOrdinalEnumBuilderSelector.java | 34 + .../builder/OrdinalEnumTemplateBuilder.java | 68 + .../template/builder/TemplateBuilder.java | 327 +++ .../template/javassist/BeansBuildContext.java | 273 ++ .../template/javassist/BuildContext.java | 273 ++ .../template/javassist/BuildContextBase.java | 244 ++ .../javassist/BuildContextFactory.java | 9 + .../template/javassist/JavassistTemplate.java | 36 + .../src/test/java/org/msgpack/TestArrays.java | 4 + .../template/BeansEntryReaderTest.java | 133 + .../org/msgpack/template/BeansEquals.java | 83 + ...ionTemplateBuilderJavaBeansPackUnpack.java | 2207 ++++++++++++++++ ...tReflectionTemplateBuilderPackConvert.java | 1417 +++++++++++ ...stReflectionTemplateBuilderPackUnpack.java | 1422 +++++++++++ ...estTemplateBuilderJavaBeansPackUnpack.java | 2234 +++++++++++++++++ .../TestTemplateBuilderPackConvert.java | 15 +- .../TestTemplateBuilderPackUnpack.java | 16 +- scala/.gitignore | 40 + scala/pom.xml | 158 ++ scala/src/main/scala/org/msgpack/App.scala | 15 + .../JavassistTypeScalaTemplateBuilder.scala | 521 ++++ .../scala/org/msgpack/ScalaMessagePack.scala | 76 + .../org/msgpack/ScalaTemplateBuilder.scala | 16 + .../ScalaTemplateBuilderSelector.scala | 48 + .../template/ImmutableListTemplate.scala | 49 + .../template/ImmutableMapTemplate.scala | 54 + .../template/MutableListTemplate.scala | 56 + .../msgpack/template/MutableMapTemplate.scala | 70 + .../scala/org/msgpack/ClassWithList.scala | 21 + .../test/scala/org/msgpack/ClassWithMap.scala | 19 + .../org/msgpack/CollectionPackSpec.scala | 71 + .../test/scala/org/msgpack/SampleClass.scala | 77 + .../msgpack/ScalaFieldEntryReaderSpec.scala | 120 + .../org/msgpack/ScalaMessagePackSpec.scala | 90 + 63 files changed, 12077 insertions(+), 645 deletions(-) create mode 100644 java/msgpack.iml create mode 100644 java/src/main/java/org/msgpack/annotation/MessagePackBeans.java create mode 100644 java/src/main/java/org/msgpack/template/BeansFieldEntry.java create mode 100644 java/src/main/java/org/msgpack/template/BeansFieldEntryReader.java create mode 100644 java/src/main/java/org/msgpack/template/BeansReflectionTemplateBuilder.java create mode 100644 java/src/main/java/org/msgpack/template/FieldEntry.java create mode 100644 java/src/main/java/org/msgpack/template/FieldEntryReader.java create mode 100644 java/src/main/java/org/msgpack/template/IFieldEntry.java create mode 100644 java/src/main/java/org/msgpack/template/IFieldEntryReader.java create mode 100644 java/src/main/java/org/msgpack/template/builder/ArrayTemplateBuilder.java create mode 100644 java/src/main/java/org/msgpack/template/builder/ArrayTemplateBuilderSelector.java create mode 100644 java/src/main/java/org/msgpack/template/builder/BuilderSelector.java create mode 100644 java/src/main/java/org/msgpack/template/builder/BuilderSelectorRegistry.java create mode 100644 java/src/main/java/org/msgpack/template/builder/CustomTemplateBuilder.java create mode 100644 java/src/main/java/org/msgpack/template/builder/EnumBuilderSelector.java create mode 100644 java/src/main/java/org/msgpack/template/builder/MessagePackBeansBuilderSelector.java create mode 100644 java/src/main/java/org/msgpack/template/builder/MessagePackMessageBuilderSelector.java create mode 100644 java/src/main/java/org/msgpack/template/builder/MessagePackOrdinalEnumBuilderSelector.java create mode 100644 java/src/main/java/org/msgpack/template/builder/OrdinalEnumTemplateBuilder.java create mode 100644 java/src/main/java/org/msgpack/template/builder/TemplateBuilder.java create mode 100644 java/src/main/java/org/msgpack/template/javassist/BeansBuildContext.java create mode 100644 java/src/main/java/org/msgpack/template/javassist/BuildContext.java create mode 100644 java/src/main/java/org/msgpack/template/javassist/BuildContextBase.java create mode 100644 java/src/main/java/org/msgpack/template/javassist/BuildContextFactory.java create mode 100644 java/src/main/java/org/msgpack/template/javassist/JavassistTemplate.java create mode 100644 java/src/test/java/org/msgpack/template/BeansEntryReaderTest.java create mode 100644 java/src/test/java/org/msgpack/template/BeansEquals.java create mode 100644 java/src/test/java/org/msgpack/template/TestReflectionTemplateBuilderJavaBeansPackUnpack.java create mode 100644 java/src/test/java/org/msgpack/template/TestReflectionTemplateBuilderPackConvert.java create mode 100644 java/src/test/java/org/msgpack/template/TestReflectionTemplateBuilderPackUnpack.java create mode 100644 java/src/test/java/org/msgpack/template/TestTemplateBuilderJavaBeansPackUnpack.java create mode 100644 scala/.gitignore create mode 100644 scala/pom.xml create mode 100644 scala/src/main/scala/org/msgpack/App.scala create mode 100644 scala/src/main/scala/org/msgpack/JavassistTypeScalaTemplateBuilder.scala create mode 100644 scala/src/main/scala/org/msgpack/ScalaMessagePack.scala create mode 100644 scala/src/main/scala/org/msgpack/ScalaTemplateBuilder.scala create mode 100644 scala/src/main/scala/org/msgpack/ScalaTemplateBuilderSelector.scala create mode 100644 scala/src/main/scala/org/msgpack/template/ImmutableListTemplate.scala create mode 100644 scala/src/main/scala/org/msgpack/template/ImmutableMapTemplate.scala create mode 100644 scala/src/main/scala/org/msgpack/template/MutableListTemplate.scala create mode 100644 scala/src/main/scala/org/msgpack/template/MutableMapTemplate.scala create mode 100644 scala/src/test/scala/org/msgpack/ClassWithList.scala create mode 100644 scala/src/test/scala/org/msgpack/ClassWithMap.scala create mode 100644 scala/src/test/scala/org/msgpack/CollectionPackSpec.scala create mode 100644 scala/src/test/scala/org/msgpack/SampleClass.scala create mode 100644 scala/src/test/scala/org/msgpack/ScalaFieldEntryReaderSpec.scala create mode 100644 scala/src/test/scala/org/msgpack/ScalaMessagePackSpec.scala diff --git a/java/.settings/org.eclipse.jdt.core.prefs b/java/.settings/org.eclipse.jdt.core.prefs index c75ad473..b20b311f 100755 --- a/java/.settings/org.eclipse.jdt.core.prefs +++ b/java/.settings/org.eclipse.jdt.core.prefs @@ -1,5 +1,5 @@ -#Mon Apr 19 22:18:48 JST 2010 -org.eclipse.jdt.core.compiler.codegen.targetPlatform=1.6 +#Sat Mar 26 02:44:20 JST 2011 eclipse.preferences.version=1 -org.eclipse.jdt.core.compiler.source=1.6 +org.eclipse.jdt.core.compiler.codegen.targetPlatform=1.6 org.eclipse.jdt.core.compiler.compliance=1.6 +org.eclipse.jdt.core.compiler.source=1.6 diff --git a/java/msgpack.iml b/java/msgpack.iml new file mode 100644 index 00000000..3a6d962d --- /dev/null +++ b/java/msgpack.iml @@ -0,0 +1,17 @@ +<?xml version="1.0" encoding="UTF-8"?> +<module org.jetbrains.idea.maven.project.MavenProjectsManager.isMavenModule="true" type="JAVA_MODULE" version="4"> + <component name="NewModuleRootManager" LANGUAGE_LEVEL="JDK_1_6" inherit-compiler-output="false"> + <output url="file://$MODULE_DIR$/target/classes" /> + <output-test url="file://$MODULE_DIR$/target/test-classes" /> + <exclude-output /> + <content url="file://$MODULE_DIR$"> + <sourceFolder url="file://$MODULE_DIR$/src/main/java" isTestSource="false" /> + <sourceFolder url="file://$MODULE_DIR$/src/test/java" isTestSource="true" /> + <excludeFolder url="file://$MODULE_DIR$/target" /> + </content> + <orderEntry type="inheritedJdk" /> + <orderEntry type="sourceFolder" forTests="false" /> + <orderEntry type="library" scope="TEST" name="Maven: junit:junit:4.8.1" level="project" /> + </component> +</module> + diff --git a/java/pom.xml b/java/pom.xml index c8a19b3a..7663b30d 100755 --- a/java/pom.xml +++ b/java/pom.xml @@ -3,7 +3,7 @@ <modelVersion>4.0.0</modelVersion> <groupId>org.msgpack</groupId> <artifactId>msgpack</artifactId> - <version>0.5.1-devel</version> + <version>0.5.2-SNAPSHOT</version> <description>MessagePack for Java</description> <name>MessagePack for Java</name> @@ -81,6 +81,20 @@ <connectionUrl>scm:git://github.com/msgpack/msgpack.git</connectionUrl> </configuration> </plugin> + + <plugin> + <groupId>org.apache.maven.plugins</groupId> + <artifactId>maven-source-plugin</artifactId> + <executions> + <execution> + <id>attach-sources</id> + <goals> + <goal>jar</goal> + </goals> + </execution> + </executions> + </plugin> + </plugins> </build> @@ -132,12 +146,14 @@ <id>msgpack.org</id> <name>Repository at msgpack.org</name> <url>file://${project.build.directory}/website/maven2/</url> + <!--<url>${deploy-release-url}</url>--> </repository> <snapshotRepository> <uniqueVersion>true</uniqueVersion> <id>msgpack.org</id> <name>Repository at msgpack.org</name> <url>file://${project.build.directory}/website/maven2/</url> + <!--<url>${deploy-snapshot-url}</url>--> </snapshotRepository> </distributionManagement> diff --git a/java/src/main/java/org/msgpack/MessagePack.java b/java/src/main/java/org/msgpack/MessagePack.java index f3a73c06..c25023c4 100644 --- a/java/src/main/java/org/msgpack/MessagePack.java +++ b/java/src/main/java/org/msgpack/MessagePack.java @@ -22,8 +22,8 @@ import java.io.InputStream; import java.io.ByteArrayOutputStream; import java.io.IOException; import org.msgpack.template.TemplateRegistry; -import org.msgpack.template.TemplateBuilder; import org.msgpack.template.FieldList; +import org.msgpack.template.builder.TemplateBuilder; public class MessagePack { public static byte[] pack(Object obj) { diff --git a/java/src/main/java/org/msgpack/annotation/Ignore.java b/java/src/main/java/org/msgpack/annotation/Ignore.java index 96a37bb6..e052e58a 100644 --- a/java/src/main/java/org/msgpack/annotation/Ignore.java +++ b/java/src/main/java/org/msgpack/annotation/Ignore.java @@ -22,7 +22,7 @@ import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; import java.lang.annotation.Target; -@Target({ElementType.FIELD, ElementType.PARAMETER}) +@Target({ElementType.FIELD, ElementType.PARAMETER, ElementType.METHOD}) @Retention(RetentionPolicy.RUNTIME) public @interface Ignore { } diff --git a/java/src/main/java/org/msgpack/annotation/Index.java b/java/src/main/java/org/msgpack/annotation/Index.java index 7c1b6598..d3b2181f 100644 --- a/java/src/main/java/org/msgpack/annotation/Index.java +++ b/java/src/main/java/org/msgpack/annotation/Index.java @@ -22,7 +22,7 @@ import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; import java.lang.annotation.Target; -@Target({ElementType.FIELD, ElementType.PARAMETER}) +@Target({ElementType.FIELD, ElementType.PARAMETER, ElementType.METHOD}) @Retention(RetentionPolicy.RUNTIME) public @interface Index { int value(); diff --git a/java/src/main/java/org/msgpack/annotation/MessagePackBeans.java b/java/src/main/java/org/msgpack/annotation/MessagePackBeans.java new file mode 100644 index 00000000..0c361360 --- /dev/null +++ b/java/src/main/java/org/msgpack/annotation/MessagePackBeans.java @@ -0,0 +1,35 @@ +// +// 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; +import org.msgpack.template.FieldOption; + +/** + * Annotation for java beans class + * @author takeshita + * + */ +@Target(ElementType.TYPE) +@Retention(RetentionPolicy.RUNTIME) +public @interface MessagePackBeans { + FieldOption value() default FieldOption.DEFAULT; +} diff --git a/java/src/main/java/org/msgpack/annotation/Nullable.java b/java/src/main/java/org/msgpack/annotation/Nullable.java index e6893e72..56aea89e 100644 --- a/java/src/main/java/org/msgpack/annotation/Nullable.java +++ b/java/src/main/java/org/msgpack/annotation/Nullable.java @@ -22,7 +22,7 @@ import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; import java.lang.annotation.Target; -@Target({ElementType.FIELD, ElementType.PARAMETER}) +@Target({ElementType.FIELD, ElementType.PARAMETER, ElementType.METHOD}) @Retention(RetentionPolicy.RUNTIME) public @interface Nullable { } diff --git a/java/src/main/java/org/msgpack/annotation/Optional.java b/java/src/main/java/org/msgpack/annotation/Optional.java index 7894f881..a137ec86 100644 --- a/java/src/main/java/org/msgpack/annotation/Optional.java +++ b/java/src/main/java/org/msgpack/annotation/Optional.java @@ -22,7 +22,7 @@ import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; import java.lang.annotation.Target; -@Target({ElementType.FIELD, ElementType.PARAMETER}) +@Target({ElementType.FIELD, ElementType.PARAMETER, ElementType.METHOD}) @Retention(RetentionPolicy.RUNTIME) public @interface Optional { } diff --git a/java/src/main/java/org/msgpack/annotation/Required.java b/java/src/main/java/org/msgpack/annotation/Required.java index 16311085..de1d816b 100644 --- a/java/src/main/java/org/msgpack/annotation/Required.java +++ b/java/src/main/java/org/msgpack/annotation/Required.java @@ -22,7 +22,7 @@ import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; import java.lang.annotation.Target; -@Target({ElementType.FIELD, ElementType.PARAMETER}) +@Target({ElementType.FIELD, ElementType.PARAMETER, ElementType.METHOD}) @Retention(RetentionPolicy.RUNTIME) public @interface Required { } diff --git a/java/src/main/java/org/msgpack/template/BeansFieldEntry.java b/java/src/main/java/org/msgpack/template/BeansFieldEntry.java new file mode 100644 index 00000000..00e1bcad --- /dev/null +++ b/java/src/main/java/org/msgpack/template/BeansFieldEntry.java @@ -0,0 +1,149 @@ +// +// 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.template; + +import java.beans.PropertyDescriptor; +import java.io.IOException; +import java.lang.reflect.*; +import java.lang.annotation.*; +import java.util.List; +import java.util.ArrayList; +import java.util.EnumSet; +import org.msgpack.*; +import org.msgpack.annotation.*; + +/** + * Field entry for Java beans property. + * @author takeshita + * + */ +public class BeansFieldEntry implements IFieldEntry { + + PropertyDescriptor desc; + FieldOption option = FieldOption.DEFAULT; + + public BeansFieldEntry(PropertyDescriptor desc) { + this.desc = desc; + } + + @Override + public String getName() { + return desc.getDisplayName(); + } + public String getGetterName(){ + return desc.getReadMethod().getName(); + } + public String getSetterName(){ + return desc.getWriteMethod().getName(); + } + + @Override + public Class<?> getType() { + return desc.getPropertyType(); + } + + @Override + public String getJavaTypeName() { + Class<?> type = getType(); + if(type.isArray()) { + return arrayTypeToString(type); + } else { + return type.getName(); + } + } + static String arrayTypeToString(Class<?> type) { + int dim = 1; + Class<?> baseType = type.getComponentType(); + while(baseType.isArray()) { + baseType = baseType.getComponentType(); + dim += 1; + } + StringBuilder sb = new StringBuilder(); + sb.append(baseType.getName()); + for (int i = 0; i < dim; ++i) { + sb.append("[]"); + } + return sb.toString(); + } + + @Override + public Type getGenericType() { + return desc.getReadMethod().getGenericReturnType(); + } + + @Override + public FieldOption getOption() { + return option; + } + public void setOption(FieldOption option){ + this.option = option; + } + + @Override + public boolean isAvailable() { + return option != FieldOption.IGNORE; + } + + /* (non-Javadoc) + * @see org.msgpack.template.IFieldEntry#isRequired() + */ + @Override + public boolean isRequired() { + return option == FieldOption.REQUIRED; + } + + /* (non-Javadoc) + * @see org.msgpack.template.IFieldEntry#isOptional() + */ + @Override + public boolean isOptional() { + return option == FieldOption.OPTIONAL; + } + + /* (non-Javadoc) + * @see org.msgpack.template.IFieldEntry#isNullable() + */ + @Override + public boolean isNullable() { + return option == FieldOption.NULLABLE; + } + + public Object get(Object target){ + try { + return desc.getReadMethod().invoke(target); + } catch (IllegalArgumentException e) { + throw new MessageTypeException(e); + } catch (IllegalAccessException e) { + throw new MessageTypeException(e); + } catch (InvocationTargetException e) { + throw new MessageTypeException(e); + } + } + public void set(Object target , Object value){ + try { + desc.getWriteMethod().invoke(target, value); + } catch (IllegalArgumentException e) { + throw new MessageTypeException(e); + } catch (IllegalAccessException e) { + throw new MessageTypeException(e); + } catch (InvocationTargetException e) { + throw new MessageTypeException(e); + } + } + +} \ No newline at end of file diff --git a/java/src/main/java/org/msgpack/template/BeansFieldEntryReader.java b/java/src/main/java/org/msgpack/template/BeansFieldEntryReader.java new file mode 100644 index 00000000..43536dcb --- /dev/null +++ b/java/src/main/java/org/msgpack/template/BeansFieldEntryReader.java @@ -0,0 +1,174 @@ +package org.msgpack.template; + +import java.beans.BeanDescriptor; +import java.beans.BeanInfo; +import java.beans.IntrospectionException; +import java.beans.Introspector; +import java.beans.PropertyDescriptor; +import java.lang.annotation.Annotation; +import java.lang.reflect.AccessibleObject; +import java.lang.reflect.Field; +import java.lang.reflect.Method; +import java.lang.reflect.Modifier; +import java.util.ArrayList; +import java.util.List; +import java.util.Properties; + +import org.msgpack.annotation.Ignore; +import org.msgpack.annotation.Index; +import org.msgpack.annotation.MessagePackMessage; +import org.msgpack.annotation.Nullable; +import org.msgpack.annotation.Optional; +import org.msgpack.annotation.Required; + +/** + * List up Java beans property methods. + * @author takeshita + * + */ +public class BeansFieldEntryReader implements IFieldEntryReader{ + + + public IFieldEntry[] convertFieldEntries(Class<?> targetClass, FieldList flist) throws NoSuchFieldException { + List<FieldList.Entry> src = flist.getList(); + FieldEntry[] result = new FieldEntry[src.size()]; + for(int i=0; i < src.size(); i++) { + FieldList.Entry s = src.get(i); + if(s.isAvailable()) { + result[i] = new FieldEntry(targetClass.getDeclaredField(s.getName()), s.getOption()); + } else { + result[i] = new FieldEntry(); + } + } + return result; + } + + @Override + public IFieldEntry[] readFieldEntries(Class<?> targetClass, + FieldOption implicitOption) { + BeanInfo desc; + try { + desc = Introspector.getBeanInfo(targetClass); + } catch (IntrospectionException e1) { + throw new TemplateBuildException("Class must be java beans class:" + targetClass.getName()); + } + + PropertyDescriptor[] props = desc.getPropertyDescriptors(); + ArrayList<PropertyDescriptor> list = new ArrayList<PropertyDescriptor>(); + for(int i = 0;i < props.length;i++){ + PropertyDescriptor pd = props[i]; + if(!isIgnoreProp(pd)){ + list.add(pd); + } + } + props = new PropertyDescriptor[list.size()]; + list.toArray(props); + + BeansFieldEntry[] entries = new BeansFieldEntry[props.length]; + for(int i = 0;i < props.length;i++){ + PropertyDescriptor p = props[i]; + int index = readPropIndex(p); + if(index >= 0){ + if(entries[index] != null){ + throw new TemplateBuildException("duplicated index: "+index); + } + if(index >= entries.length){ + throw new TemplateBuildException("invalid index: "+index); + } + entries[index] = new BeansFieldEntry(p); + props[index] = null; + } + } + int insertIndex = 0; + for(int i = 0;i < props.length;i++){ + PropertyDescriptor p = props[i]; + if(p != null){ + while(entries[insertIndex] != null){ + insertIndex++; + } + entries[insertIndex] = new BeansFieldEntry(p); + } + + } + for(int i = 0;i < entries.length;i++){ + BeansFieldEntry e = entries[i]; + FieldOption op = readPropOption(e.desc, implicitOption); + e.setOption(op); + } + return entries; + } + + public FieldOption readImplicitFieldOption(Class<?> targetClass) { + MessagePackMessage a = targetClass.getAnnotation(MessagePackMessage.class); + if(a == null) { + return FieldOption.DEFAULT; + } + return a.value(); + } + + + private FieldOption readPropOption(PropertyDescriptor desc, FieldOption implicitOption) { + + FieldOption forGetter = readMethodOption(desc.getReadMethod()); + if(forGetter != FieldOption.DEFAULT){ + return forGetter; + } + FieldOption forSetter = readMethodOption(desc.getWriteMethod()); + if(forSetter != FieldOption.DEFAULT){ + return forSetter; + }else{ + return implicitOption; + } + + } + private FieldOption readMethodOption(Method method){ + + if(isAnnotated(method, Ignore.class)) { + return FieldOption.IGNORE; + } else if(isAnnotated(method, Required.class)) { + return FieldOption.REQUIRED; + } else if(isAnnotated(method, Optional.class)) { + return FieldOption.OPTIONAL; + } else if(isAnnotated(method, Nullable.class)) { + if(method.getDeclaringClass().isPrimitive()) { + return FieldOption.REQUIRED; + } else { + return FieldOption.NULLABLE; + } + } + return FieldOption.DEFAULT; + } + + private int readPropIndex(PropertyDescriptor desc) { + + int forGetter = readMethodIndex(desc.getReadMethod()); + if(forGetter >= 0){ + return forGetter; + } + int forSetter = readMethodIndex(desc.getWriteMethod()); + return forSetter; + } + private int readMethodIndex(Method method){ + Index a = method.getAnnotation(Index.class); + if(a == null) { + return -1; + } else { + return a.value(); + } + } + + private boolean isAnnotated(AccessibleObject ao, Class<? extends Annotation> with) { + return ao.getAnnotation(with) != null; + } + boolean isIgnoreProp(PropertyDescriptor desc){ + if(desc == null)return true; + Method getter = desc.getReadMethod(); + Method setter = desc.getWriteMethod(); + return getter == null || + setter == null || + !Modifier.isPublic(getter.getModifiers()) || + !Modifier.isPublic(setter.getModifiers()) || + isAnnotated(getter,Ignore.class) || + isAnnotated(setter, Ignore.class); + } +} diff --git a/java/src/main/java/org/msgpack/template/BeansReflectionTemplateBuilder.java b/java/src/main/java/org/msgpack/template/BeansReflectionTemplateBuilder.java new file mode 100644 index 00000000..8899399f --- /dev/null +++ b/java/src/main/java/org/msgpack/template/BeansReflectionTemplateBuilder.java @@ -0,0 +1,321 @@ +package org.msgpack.template; + +import java.io.IOException; +import java.lang.reflect.Field; + +import org.msgpack.AbstractTemplate; +import org.msgpack.MessagePackObject; +import org.msgpack.MessageTypeException; +import org.msgpack.Packer; +import org.msgpack.Template; +import org.msgpack.Unpacker; +import org.msgpack.template.ReflectionTemplateBuilder.BooleanFieldEntry; +import org.msgpack.template.ReflectionTemplateBuilder.ByteFieldEntry; +import org.msgpack.template.ReflectionTemplateBuilder.DoubleFieldEntry; +import org.msgpack.template.ReflectionTemplateBuilder.FloatFieldEntry; +import org.msgpack.template.ReflectionTemplateBuilder.IntFieldEntry; +import org.msgpack.template.ReflectionTemplateBuilder.LongFieldEntry; +import org.msgpack.template.ReflectionTemplateBuilder.NullFieldEntry; +import org.msgpack.template.ReflectionTemplateBuilder.ObjectFieldEntry; +import org.msgpack.template.ReflectionTemplateBuilder.ShortFieldEntry; +import org.msgpack.template.builder.CustomTemplateBuilder; + +/** + * Class for building java reflection template builder for java beans class. + * @author takeshita + * + */ +public class BeansReflectionTemplateBuilder extends CustomTemplateBuilder{ + + IFieldEntryReader reader = new BeansFieldEntryReader(); + + public BeansReflectionTemplateBuilder(){} + + @Override + public IFieldEntryReader getFieldEntryReader(){ + return reader; + } + + static class ReflectionEntry{ + BeansFieldEntry entry; + public ReflectionEntry(BeansFieldEntry entry){ + this.entry = entry; + } + + public void pack(Object value , Packer packer) throws IOException{ + packer.pack(value); + } + public void convert(Object target, MessagePackObject obj) throws MessageTypeException, IllegalAccessException { + entry.set(target, obj.convert(entry.getType())); + } + + public void unpack(Object target, Unpacker unpacker) throws IOException, MessageTypeException, IllegalAccessException { + entry.set(target, unpacker.unpack(entry.getType())); + } + + public void setNull(Object target){ + entry.set(target, null); + } + + public boolean isRequired(){ + return entry.isRequired(); + } + public boolean isNullable(){ + return entry.isNullable(); + } + public boolean isAvailable(){ + return entry.isAvailable(); + } + public boolean isOptional(){ + return entry.isOptional(); + } + public Object get(Object target){ + return entry.get(target); + } + + } + + static class ObjectFieldEntry extends ReflectionEntry{ + Template template; + public ObjectFieldEntry(BeansFieldEntry entry,Template template){ + super(entry); + this.template = template; + } + public void pack(Object value , Packer packer) throws IOException{ + template.pack(packer,value); + } + public void convert(Object target, MessagePackObject obj) throws MessageTypeException, IllegalAccessException { + Class<Object> type = (Class<Object>)entry.getType(); + Object fieldReference = entry.get(target); + Object valueReference = template.convert(obj, fieldReference); + if(valueReference != fieldReference) { + entry.set(target, valueReference); + } + } + + public void unpack(Object target, Unpacker unpacker) throws IOException, MessageTypeException, IllegalAccessException { + + Class<Object> type = (Class<Object>)entry.getType(); + Object fieldReference = entry.get(target); + Object valueReference = template.unpack(unpacker, fieldReference); + if(valueReference != fieldReference) { + entry.set(target, valueReference); + } + } + } + + static class BeansReflectionTemplate extends AbstractTemplate{ + + Class<?> targetClass; + ReflectionEntry[] entries = null; + protected int minimumArrayLength; + + public BeansReflectionTemplate( + Class<?> targetClass, + ReflectionEntry[] entries){ + this.targetClass = targetClass; + this.entries = entries; + this.minimumArrayLength = 0; + for(int i=0; i < entries.length; i++) { + ReflectionEntry e = entries[i]; + if(e.isRequired() || e.isNullable()) { + this.minimumArrayLength = i+1; + } + } + } + + + @Override + public void pack(Packer pk, Object target) throws IOException { + + pk.packArray(entries.length); + for(ReflectionEntry e : entries){ + if(!e.isAvailable()){ + pk.packNil(); + continue; + } + Object obj = e.get(target); + if(obj == null) { + if(!e.isNullable() && !e.isOptional()) { + throw new MessageTypeException(); + } + pk.packNil(); + } else { + pk.pack(obj); + } + } + + } + @Override + public Object unpack(Unpacker pac, Object to) throws IOException, MessageTypeException { + try { + if(to == null) { + to = targetClass.newInstance(); + } + + int length = pac.unpackArray(); + if(length < minimumArrayLength) { + throw new MessageTypeException(); + } + + int i; + for(i=0; i < minimumArrayLength; i++) { + ReflectionEntry e = entries[i]; + if(!e.isAvailable()) { + pac.unpackObject(); + continue; + } + + if(pac.tryUnpackNull()) { + if(e.isRequired()) { + // Required + nil => exception + throw new MessageTypeException(); + } else if(e.isOptional()) { + // Optional + nil => keep default value + } else { // Nullable + // Nullable + nil => set null + e.setNull(to); + } + } else { + e.unpack(to,pac); + //e.set(to, pac.unpack(e.getType())); + } + } + + int max = length < entries.length ? length : entries.length; + for(; i < max; i++) { + ReflectionEntry e = entries[i]; + if(!e.isAvailable()) { + pac.unpackObject(); + continue; + } + + if(pac.tryUnpackNull()) { + // this is Optional field becaue i >= minimumArrayLength + // Optional + nil => keep default value + } else { + e.unpack(to, pac); + //e.set(to, pac.unpack(e.getType())); + } + } + + // latter entries are all Optional + nil => keep default value + + for(; i < length; i++) { + pac.unpackObject(); + } + + return to; + + } catch (MessageTypeException e) { + throw e; + } catch (IOException e) { + throw e; + } catch (Exception e) { + throw new MessageTypeException(e); + } + } + + @Override + public Object convert(MessagePackObject from, Object to) + throws MessageTypeException { + try { + if(to == null) { + to = targetClass.newInstance(); + } + + MessagePackObject[] array = from.asArray(); + int length = array.length; + if(length < minimumArrayLength) { + throw new MessageTypeException(); + } + + int i; + for(i=0; i < minimumArrayLength; i++) { + ReflectionEntry e = entries[i]; + if(!e.isAvailable()) { + continue; + } + + MessagePackObject obj = array[i]; + if(obj.isNil()) { + if(e.isRequired()) { + // Required + nil => exception + throw new MessageTypeException(); + } else if(e.isOptional()) { + // Optional + nil => keep default value + } else { // Nullable + // Nullable + nil => set null + e.setNull(to); + //e.set(to,null); + } + } else { + e.convert(to, obj); + //e.set(to, from.convert(e.getType())); + } + } + + int max = length < entries.length ? length : entries.length; + for(; i < max; i++) { + ReflectionEntry e = entries[i]; + if(!e.isAvailable()) { + continue; + } + + MessagePackObject obj = array[i]; + if(obj.isNil()) { + // this is Optional field becaue i >= minimumArrayLength + // Optional + nil => keep default value + } else { + e.convert(to, obj); + //e.set(to, obj.convert(e.getType())); + } + } + + // latter entries are all Optional + nil => keep default value + + return to; + + } catch (MessageTypeException e) { + throw e; + } catch (Exception e) { + throw new MessageTypeException(e); + } + } + + } + + + @Override + public Template buildTemplate(Class<?> targetClass, IFieldEntry[] entries) { + + ReflectionEntry[] refEntries = new ReflectionEntry[entries.length]; + for(int i = 0;i < entries.length;i++){ + BeansFieldEntry e = (BeansFieldEntry)entries[i]; + Class<?> type = e.getType(); + if(type.equals(boolean.class)) { + refEntries[i] = new ReflectionEntry(e); + } else if(type.equals(byte.class)) { + refEntries[i] = new ReflectionEntry(e); + } else if(type.equals(short.class)) { + refEntries[i] = new ReflectionEntry(e); + } else if(type.equals(int.class)) { + refEntries[i] = new ReflectionEntry(e); + } else if(type.equals(long.class)) { + refEntries[i] = new ReflectionEntry(e); + } else if(type.equals(float.class)) { + refEntries[i] = new ReflectionEntry(e); + } else if(type.equals(double.class)) { + refEntries[i] = new ReflectionEntry(e); + } else { + Template tmpl = TemplateRegistry.lookup(e.getGenericType(), true); + refEntries[i] = new ObjectFieldEntry(e, tmpl); + } + } + + + return new BeansReflectionTemplate(targetClass,refEntries); + } + + +} diff --git a/java/src/main/java/org/msgpack/template/FieldEntry.java b/java/src/main/java/org/msgpack/template/FieldEntry.java new file mode 100644 index 00000000..2c474ec3 --- /dev/null +++ b/java/src/main/java/org/msgpack/template/FieldEntry.java @@ -0,0 +1,143 @@ +// +// 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.template; + +import java.io.IOException; +import java.lang.reflect.*; +import java.lang.annotation.*; +import java.util.List; +import java.util.ArrayList; +import java.util.EnumSet; +import org.msgpack.*; +import org.msgpack.annotation.*; + +public class FieldEntry implements IFieldEntry { + private Field field; + private FieldOption option; + + public FieldEntry() { + this.field = null; + this.option = FieldOption.IGNORE; + } + + public FieldEntry(FieldEntry e) { + this.field = e.field; + this.option = e.option; + } + + public FieldEntry(Field field, FieldOption option) { + this.field = field; + this.option = option; + } + + public Field getField() { + return field; + } + + /* (non-Javadoc) + * @see org.msgpack.template.IFieldEntry#getName() + */ + @Override + public String getName() { + return field.getName(); + } + + /* (non-Javadoc) + * @see org.msgpack.template.IFieldEntry#getType() + */ + @Override + public Class<?> getType() { + return field.getType(); + } + + /* (non-Javadoc) + * @see org.msgpack.template.IFieldEntry#getJavaTypeName() + */ + @Override + public String getJavaTypeName() { + Class<?> type = field.getType(); + if(type.isArray()) { + return arrayTypeToString(type); + } else { + return type.getName(); + } + } + + /* (non-Javadoc) + * @see org.msgpack.template.IFieldEntry#getGenericType() + */ + @Override + public Type getGenericType() { + return field.getGenericType(); + } + + /* (non-Javadoc) + * @see org.msgpack.template.IFieldEntry#getOption() + */ + @Override + public FieldOption getOption() { + return option; + } + + /* (non-Javadoc) + * @see org.msgpack.template.IFieldEntry#isAvailable() + */ + @Override + public boolean isAvailable() { + return option != FieldOption.IGNORE; + } + + /* (non-Javadoc) + * @see org.msgpack.template.IFieldEntry#isRequired() + */ + @Override + public boolean isRequired() { + return option == FieldOption.REQUIRED; + } + + /* (non-Javadoc) + * @see org.msgpack.template.IFieldEntry#isOptional() + */ + @Override + public boolean isOptional() { + return option == FieldOption.OPTIONAL; + } + + /* (non-Javadoc) + * @see org.msgpack.template.IFieldEntry#isNullable() + */ + @Override + public boolean isNullable() { + return option == FieldOption.NULLABLE; + } + + static String arrayTypeToString(Class<?> type) { + int dim = 1; + Class<?> baseType = type.getComponentType(); + while(baseType.isArray()) { + baseType = baseType.getComponentType(); + dim += 1; + } + StringBuilder sb = new StringBuilder(); + sb.append(baseType.getName()); + for (int i = 0; i < dim; ++i) { + sb.append("[]"); + } + return sb.toString(); + } +} \ No newline at end of file diff --git a/java/src/main/java/org/msgpack/template/FieldEntryReader.java b/java/src/main/java/org/msgpack/template/FieldEntryReader.java new file mode 100644 index 00000000..9d477465 --- /dev/null +++ b/java/src/main/java/org/msgpack/template/FieldEntryReader.java @@ -0,0 +1,165 @@ +package org.msgpack.template; + +import java.lang.annotation.Annotation; +import java.lang.reflect.AccessibleObject; +import java.lang.reflect.Field; +import java.lang.reflect.Modifier; +import java.util.ArrayList; +import java.util.List; + +import org.msgpack.annotation.Ignore; +import org.msgpack.annotation.Index; +import org.msgpack.annotation.MessagePackMessage; +import org.msgpack.annotation.Nullable; +import org.msgpack.annotation.Optional; +import org.msgpack.annotation.Required; + +public class FieldEntryReader implements IFieldEntryReader{ + + + public IFieldEntry[] convertFieldEntries(Class<?> targetClass, FieldList flist) throws NoSuchFieldException { + List<FieldList.Entry> src = flist.getList(); + FieldEntry[] result = new FieldEntry[src.size()]; + for(int i=0; i < src.size(); i++) { + FieldList.Entry s = src.get(i); + if(s.isAvailable()) { + result[i] = new FieldEntry(targetClass.getDeclaredField(s.getName()), s.getOption()); + } else { + result[i] = new FieldEntry(); + } + } + return result; + } + + @Override + public IFieldEntry[] readFieldEntries(Class<?> targetClass, + FieldOption implicitOption) { + Field[] allFields = readAllFields(targetClass); + + /* index: + * @Index(0) int field_a; // 0 + * int field_b; // 1 + * @Index(3) int field_c; // 3 + * int field_d; // 4 + * @Index(2) int field_e; // 2 + * int field_f; // 5 + */ + List<FieldEntry> indexed = new ArrayList<FieldEntry>(); + int maxIndex = -1; + for(Field f : allFields) { + FieldOption opt = readFieldOption(f, implicitOption); + if(opt == FieldOption.IGNORE) { + // skip + continue; + } + + int index = readFieldIndex(f, maxIndex); + + if(indexed.size() > index && indexed.get(index) != null) { + throw new TemplateBuildException("duplicated index: "+index); + } + if(index < 0) { + throw new TemplateBuildException("invalid index: "+index); + } + + while(indexed.size() <= index) { + indexed.add(null); + } + indexed.set(index, new FieldEntry(f, opt)); + + if(maxIndex < index) { + maxIndex = index; + } + } + + FieldEntry[] result = new FieldEntry[maxIndex+1]; + for(int i=0; i < indexed.size(); i++) { + FieldEntry e = indexed.get(i); + if(e == null) { + result[i] = new FieldEntry(); + } else { + result[i] = e; + } + } + + return result; + } + + public FieldOption readImplicitFieldOption(Class<?> targetClass) { + MessagePackMessage a = targetClass.getAnnotation(MessagePackMessage.class); + if(a == null) { + return FieldOption.DEFAULT; + } + return a.value(); + } + + private Field[] readAllFields(Class<?> targetClass) { + // order: [fields of super class, ..., fields of this class] + List<Field[]> succ = new ArrayList<Field[]>(); + int total = 0; + for(Class<?> c = targetClass; c != Object.class; c = c.getSuperclass()) { + Field[] fields = c.getDeclaredFields(); + total += fields.length; + succ.add(fields); + } + Field[] result = new Field[total]; + int off = 0; + for(int i=succ.size()-1; i >= 0; i--) { + Field[] fields = succ.get(i); + System.arraycopy(fields, 0, result, off, fields.length); + off += fields.length; + } + return result; + } + + private static FieldOption readFieldOption(Field field, FieldOption implicitOption) { + int mod = field.getModifiers(); + if(Modifier.isStatic(mod) || Modifier.isFinal(mod)) { + return FieldOption.IGNORE; + } + + if(isAnnotated(field, Ignore.class)) { + return FieldOption.IGNORE; + } else if(isAnnotated(field, Required.class)) { + return FieldOption.REQUIRED; + } else if(isAnnotated(field, Optional.class)) { + return FieldOption.OPTIONAL; + } else if(isAnnotated(field, Nullable.class)) { + if(field.getDeclaringClass().isPrimitive()) { + return FieldOption.REQUIRED; + } else { + return FieldOption.NULLABLE; + } + } + + if(implicitOption != FieldOption.DEFAULT) { + return implicitOption; + } + + // default mode: + // transient : Ignore + // public : Required + // others : Ignore + if(Modifier.isTransient(mod)) { + return FieldOption.IGNORE; + } else if(Modifier.isPublic(mod)) { + return FieldOption.REQUIRED; + } else { + return FieldOption.IGNORE; + } + } + + private static int readFieldIndex(Field field, int maxIndex) { + Index a = field.getAnnotation(Index.class); + if(a == null) { + return maxIndex + 1; + } else { + return a.value(); + } + } + + private static boolean isAnnotated(AccessibleObject ao, Class<? extends Annotation> with) { + return ao.getAnnotation(with) != null; + } + +} diff --git a/java/src/main/java/org/msgpack/template/FieldList.java b/java/src/main/java/org/msgpack/template/FieldList.java index daf59f5b..a5b141d9 100644 --- a/java/src/main/java/org/msgpack/template/FieldList.java +++ b/java/src/main/java/org/msgpack/template/FieldList.java @@ -43,19 +43,19 @@ public class FieldList { return option; } - boolean isAvailable() { + public boolean isAvailable() { return this.option != FieldOption.IGNORE; } - boolean isRequired() { + public boolean isRequired() { return this.option == FieldOption.REQUIRED; } - boolean isOptional() { + public boolean isOptional() { return this.option == FieldOption.OPTIONAL; } - boolean isNullable() { + public boolean isNullable() { return this.option == FieldOption.NULLABLE; } } @@ -89,7 +89,7 @@ public class FieldList { } } - List<Entry> getList() { + public List<Entry> getList() { return list; } } diff --git a/java/src/main/java/org/msgpack/template/IFieldEntry.java b/java/src/main/java/org/msgpack/template/IFieldEntry.java new file mode 100644 index 00000000..d12f7a8d --- /dev/null +++ b/java/src/main/java/org/msgpack/template/IFieldEntry.java @@ -0,0 +1,25 @@ +package org.msgpack.template; + +import java.lang.reflect.Type; + +public interface IFieldEntry { + + public abstract String getName(); + + public abstract Class<?> getType(); + + public abstract String getJavaTypeName(); + + public abstract Type getGenericType(); + + public abstract FieldOption getOption(); + + public abstract boolean isAvailable(); + + public abstract boolean isRequired(); + + public abstract boolean isOptional(); + + public abstract boolean isNullable(); + +} \ No newline at end of file diff --git a/java/src/main/java/org/msgpack/template/IFieldEntryReader.java b/java/src/main/java/org/msgpack/template/IFieldEntryReader.java new file mode 100644 index 00000000..07a8f877 --- /dev/null +++ b/java/src/main/java/org/msgpack/template/IFieldEntryReader.java @@ -0,0 +1,8 @@ +package org.msgpack.template; + +public interface IFieldEntryReader { + + public IFieldEntry[] convertFieldEntries(Class<?> targetClass, FieldList flist) throws NoSuchFieldException; + public IFieldEntry[] readFieldEntries(Class<?> targetClass, FieldOption implicitOption); + public FieldOption readImplicitFieldOption(Class<?> targetClass) ; +} diff --git a/java/src/main/java/org/msgpack/template/JavassistTemplateBuilder.java b/java/src/main/java/org/msgpack/template/JavassistTemplateBuilder.java index a4d2e4db..03d7f15d 100644 --- a/java/src/main/java/org/msgpack/template/JavassistTemplateBuilder.java +++ b/java/src/main/java/org/msgpack/template/JavassistTemplateBuilder.java @@ -22,6 +22,7 @@ import java.lang.reflect.Array; import java.lang.reflect.Constructor; import java.lang.reflect.InvocationTargetException; import java.lang.reflect.Type; +import java.lang.Thread; import org.msgpack.*; @@ -34,11 +35,14 @@ import javassist.CtNewConstructor; import javassist.CtNewMethod; import javassist.LoaderClassPath; import javassist.NotFoundException; +import javassist.ClassClassPath; import org.slf4j.Logger; import org.slf4j.LoggerFactory; +import org.msgpack.template.builder.CustomTemplateBuilder; +import org.msgpack.template.javassist.*; -public class JavassistTemplateBuilder extends TemplateBuilder { +public class JavassistTemplateBuilder extends CustomTemplateBuilder { private static Logger LOG = LoggerFactory.getLogger(JavassistTemplateBuilder.class); private static JavassistTemplateBuilder instance; @@ -54,12 +58,33 @@ public class JavassistTemplateBuilder extends TemplateBuilder { getInstance().pool.appendClassPath(new LoaderClassPath(cl)); } - private JavassistTemplateBuilder() { + + IFieldEntryReader reader = new FieldEntryReader(); + + public void setFieldEntryReader(IFieldEntryReader reader){ + this.reader = reader; + } + + BuildContextFactory buildContextFactory = new BuildContextFactory() { + + @Override + public BuildContextBase createBuildContext(JavassistTemplateBuilder builder) { + + return new BuildContext(builder); + } + }; + public void setBuildContextFactory(BuildContextFactory factory){ + this.buildContextFactory = factory; + } + + + + public JavassistTemplateBuilder() { pool = new ClassPool(); boolean appended = false; ClassLoader cl = null; try { - Thread.currentThread().getContextClassLoader(); + cl = Thread.currentThread().getContextClassLoader(); if (cl != null) { pool.appendClassPath(new LoaderClassPath(cl)); appended = true; @@ -80,471 +105,40 @@ public class JavassistTemplateBuilder extends TemplateBuilder { pool.appendSystemPath(); } } + /** + * Replace FieldEntryReader and BuilderContextFactory. + * you can replace field entry rules and generated codes easily. + * @param reader + * @param buildContextFactory + */ + public JavassistTemplateBuilder(IFieldEntryReader reader,BuildContextFactory buildContextFactory ){ + this(); + this.reader = reader; + this.buildContextFactory = buildContextFactory; + } + protected ClassPool pool; private int seqId = 0; - CtClass makeCtClass(String className) { + public CtClass makeCtClass(String className) { return pool.makeClass(className); } - CtClass getCtClass(String className) throws NotFoundException { + public CtClass getCtClass(String className) throws NotFoundException { return pool.get(className); } - int nextSeqId() { + public int nextSeqId() { return seqId++; } - private static abstract class BuildContextBase { - protected JavassistTemplateBuilder director; - protected String tmplName; - protected CtClass tmplCtClass; - protected abstract void setSuperClass() throws CannotCompileException, NotFoundException; - - protected abstract void buildConstructor() throws CannotCompileException, NotFoundException; - - protected void buildMethodInit() { } - - protected abstract String buildPackMethodBody(); - - protected abstract String buildUnpackMethodBody(); - - protected abstract String buildConvertMethodBody(); - - protected abstract Template buildInstance(Class<?> c) throws NoSuchMethodException, InstantiationException, IllegalAccessException, InvocationTargetException; - - public BuildContextBase(JavassistTemplateBuilder director) { - this.director = director; - } - - protected Template build(final String className) { - try { - reset(className); - buildClass(); - buildConstructor(); - buildMethodInit(); - buildPackMethod(); - buildUnpackMethod(); - buildConvertMethod(); - return buildInstance(createClass()); - } catch (Exception e) { - String code = getBuiltString(); - if(code != null) { - LOG.error("builder: " + code, e); - throw new TemplateBuildException("cannot compile: " + code, e); - } else { - throw new TemplateBuildException(e); - } - } - } - - protected void reset(String className) { - tmplName = className + "_$$_Template" + director.nextSeqId(); - tmplCtClass = director.makeCtClass(tmplName); - } - - protected void buildClass() throws CannotCompileException, NotFoundException { - setSuperClass(); - tmplCtClass.addInterface(director.getCtClass(Template.class.getName())); - } - - protected void buildPackMethod() throws CannotCompileException, NotFoundException { - String mbody = buildPackMethodBody(); - int mod = javassist.Modifier.PUBLIC; - CtClass returnType = CtClass.voidType; - String mname = "pack"; - CtClass[] paramTypes = new CtClass[] { - director.getCtClass(Packer.class.getName()), - director.getCtClass(Object.class.getName()) - }; - CtClass[] exceptTypes = new CtClass[] { - director.getCtClass(IOException.class.getName()) - }; - CtMethod newCtMethod = CtNewMethod.make( - mod, returnType, mname, - paramTypes, exceptTypes, mbody, tmplCtClass); - tmplCtClass.addMethod(newCtMethod); - } - - protected void buildUnpackMethod() throws CannotCompileException, NotFoundException { - String mbody = buildUnpackMethodBody(); - int mod = javassist.Modifier.PUBLIC; - CtClass returnType = director.getCtClass(Object.class.getName()); - String mname = "unpack"; - CtClass[] paramTypes = new CtClass[] { - director.getCtClass(Unpacker.class.getName()), - director.getCtClass(Object.class.getName()) - }; - CtClass[] exceptTypes = new CtClass[] { - director.getCtClass(MessageTypeException.class.getName()) - }; - CtMethod newCtMethod = CtNewMethod.make( - mod, returnType, mname, - paramTypes, exceptTypes, mbody, tmplCtClass); - tmplCtClass.addMethod(newCtMethod); - } - - protected void buildConvertMethod() throws CannotCompileException, NotFoundException { - String mbody = buildConvertMethodBody(); - int mod = javassist.Modifier.PUBLIC; - CtClass returnType = director.getCtClass(Object.class.getName()); - String mname = "convert"; - CtClass[] paramTypes = new CtClass[] { - director.getCtClass(MessagePackObject.class.getName()), - director.getCtClass(Object.class.getName()) - }; - CtClass[] exceptTypes = new CtClass[] { - director.getCtClass(MessageTypeException.class.getName()) - }; - CtMethod newCtMethod = CtNewMethod.make( - mod, returnType, mname, - paramTypes, exceptTypes, mbody, tmplCtClass); - tmplCtClass.addMethod(newCtMethod); - } - - protected Class<?> createClass() throws CannotCompileException { - return (Class<?>) tmplCtClass.toClass(null, null); - } - - protected StringBuilder stringBuilder = null; - - protected void resetStringBuilder() { - stringBuilder = new StringBuilder(); - } - - protected void buildString(String str) { - stringBuilder.append(str); - } - - protected void buildString(String format, Object... args) { - stringBuilder.append(String.format(format, args)); - } - - protected String getBuiltString() { - if(stringBuilder == null) { - return null; - } - return stringBuilder.toString(); - } - } - - public static abstract class JavassistTemplate extends AbstractTemplate { - public Class<?> targetClass; - public Template[] templates; - - public JavassistTemplate(Class<?> targetClass, Template[] templates) { - this.targetClass = targetClass; - this.templates = templates; - } - } - - private static class BuildContext extends BuildContextBase { - protected FieldEntry[] entries; - protected Class<?> origClass; - protected String origName; - protected Template[] templates; - protected int minimumArrayLength; - - public BuildContext(JavassistTemplateBuilder director) { - super(director); - } - - public Template buildTemplate(Class<?> targetClass, FieldEntry[] entries, Template[] templates) { - this.entries = entries; - this.templates = templates; - this.origClass = targetClass; - this.origName = this.origClass.getName(); - return build(this.origName); - } - - protected void setSuperClass() throws CannotCompileException, NotFoundException { - this.tmplCtClass.setSuperclass( - director.getCtClass(JavassistTemplate.class.getName())); - } - - protected void buildConstructor() throws CannotCompileException, NotFoundException { - // Constructor(Class targetClass, Template[] templates) - CtConstructor newCtCons = CtNewConstructor.make( - new CtClass[] { - director.getCtClass(Class.class.getName()), - director.getCtClass(Template.class.getName()+"[]") - }, - new CtClass[0], - this.tmplCtClass); - this.tmplCtClass.addConstructor(newCtCons); - } - - protected Template buildInstance(Class<?> c) throws NoSuchMethodException, InstantiationException, IllegalAccessException, InvocationTargetException { - Constructor<?> cons = c.getConstructor(new Class[] { - Class.class, - Template[].class - }); - Object tmpl = cons.newInstance(new Object[] { - this.origClass, - this.templates - }); - return (Template)tmpl; - } - - protected void buildMethodInit() { - this.minimumArrayLength = 0; - for(int i=0; i < entries.length; i++) { - FieldEntry e = entries[i]; - if(e.isRequired() || e.isNullable()) { - this.minimumArrayLength = i+1; - } - } - } - - protected String buildPackMethodBody() { - resetStringBuilder(); - buildString("{"); - buildString("%s _$$_t = (%s)$2;", this.origName, this.origName); - buildString("$1.packArray(%d);", entries.length); - for(int i=0; i < entries.length; i++) { - FieldEntry e = entries[i]; - if(!e.isAvailable()) { - buildString("$1.packNil();"); - continue; - } - Class<?> type = e.getType(); - if(type.isPrimitive()) { - buildString("$1.%s(_$$_t.%s);", primitivePackName(type), e.getName()); - } else { - buildString("if(_$$_t.%s == null) {", e.getName()); - if(!e.isNullable() && !e.isOptional()) { - buildString("throw new %s();", MessageTypeException.class.getName()); - } else { - buildString("$1.packNil();"); - } - buildString("} else {"); - buildString(" this.templates[%d].pack($1, _$$_t.%s);", i, e.getName()); - buildString("}"); - } - } - buildString("}"); - return getBuiltString(); - } - - protected String buildUnpackMethodBody() { - resetStringBuilder(); - buildString("{ "); - - buildString("%s _$$_t;", this.origName); - buildString("if($2 == null) {"); - buildString(" _$$_t = new %s();", this.origName); - buildString("} else {"); - buildString(" _$$_t = (%s)$2;", this.origName); - buildString("}"); - - buildString("int length = $1.unpackArray();"); - buildString("if(length < %d) {", this.minimumArrayLength); - buildString(" throw new %s();", MessageTypeException.class.getName()); - buildString("}"); - - int i; - for(i=0; i < this.minimumArrayLength; i++) { - FieldEntry e = entries[i]; - if(!e.isAvailable()) { - buildString("$1.unpackObject();"); - continue; - } - - buildString("if($1.tryUnpackNull()) {"); - if(e.isRequired()) { - // Required + nil => exception - buildString("throw new %s();", MessageTypeException.class.getName()); - } else if(e.isOptional()) { - // Optional + nil => keep default value - } else { // Nullable - // Nullable + nil => set null - buildString("_$$_t.%s = null;", e.getName()); - } - buildString("} else {"); - Class<?> type = e.getType(); - if(type.isPrimitive()) { - buildString("_$$_t.%s = $1.%s();", e.getName(), primitiveUnpackName(type)); - } else { - buildString("_$$_t.%s = (%s)this.templates[%d].unpack($1, _$$_t.%s);", e.getName(), e.getJavaTypeName(), i, e.getName()); - } - buildString("}"); - } - - for(; i < entries.length; i++) { - buildString("if(length <= %d) { return _$$_t; }", i); - - FieldEntry e = entries[i]; - if(!e.isAvailable()) { - buildString("$1.unpackObject();"); - continue; - } - - buildString("if($1.tryUnpackNull()) {"); - // this is Optional field becaue i >= minimumArrayLength - // Optional + nil => keep default value - buildString("} else {"); - Class<?> type = e.getType(); - if(type.isPrimitive()) { - buildString("_$$_t.%s = $1.%s();", e.getName(), primitiveUnpackName(type)); - } else { - buildString("_$$_t.%s = (%s)this.templates[%d].unpack($1, _$$_t.%s);", e.getName(), e.getJavaTypeName(), i, e.getName()); - } - buildString("}"); - } - - // latter entries are all Optional + nil => keep default value - - buildString("for(int i=%d; i < length; i++) {", i); - buildString(" $1.unpackObject();"); - buildString("}"); - - buildString("return _$$_t;"); - - buildString("}"); - return getBuiltString(); - } - - protected String buildConvertMethodBody() { - resetStringBuilder(); - buildString("{ "); - - buildString("%s _$$_t;", this.origName); - buildString("if($2 == null) {"); - buildString(" _$$_t = new %s();", this.origName); - buildString("} else {"); - buildString(" _$$_t = (%s)$2;", this.origName); - buildString("}"); - - buildString("%s[] array = $1.asArray();", MessagePackObject.class.getName()); - buildString("int length = array.length;"); - buildString("if(length < %d) {", this.minimumArrayLength); - buildString(" throw new %s();", MessageTypeException.class.getName()); - buildString("}"); - - buildString("%s obj;", MessagePackObject.class.getName()); - - int i; - for(i=0; i < this.minimumArrayLength; i++) { - FieldEntry e = entries[i]; - if(!e.isAvailable()) { - continue; - } - - buildString("obj = array[%d];", i); - buildString("if(obj.isNil()) {"); - if(e.isRequired()) { - // Required + nil => exception - buildString("throw new %s();", MessageTypeException.class.getName()); - } else if(e.isOptional()) { - // Optional + nil => keep default value - } else { // Nullable - // Nullable + nil => set null - buildString("_$$_t.%s = null;", e.getName()); - } - buildString("} else {"); - Class<?> type = e.getType(); - if(type.isPrimitive()) { - buildString("_$$_t.%s = obj.%s();", e.getName(), primitiveConvertName(type)); - } else { - buildString("_$$_t.%s = (%s)this.templates[%d].convert(obj, _$$_t.%s);", e.getName(), e.getJavaTypeName(), i, e.getName()); - } - buildString("}"); - } - - for(; i < entries.length; i++) { - buildString("if(length <= %d) { return _$$_t; }", i); - - FieldEntry e = entries[i]; - if(!e.isAvailable()) { - continue; - } - - buildString("obj = array[%d];", i); - buildString("if(obj.isNil()) {"); - // this is Optional field becaue i >= minimumArrayLength - // Optional + nil => keep default value - buildString("} else {"); - Class<?> type = e.getType(); - if(type.isPrimitive()) { - buildString("_$$_t.%s = obj.%s();", e.getName(), primitiveConvertName(type)); - } else { - buildString("_$$_t.%s = (%s)this.templates[%d].convert(obj, _$$_t.%s);", e.getName(), e.getJavaTypeName(), i, e.getName()); - } - buildString("}"); - } - - // latter entries are all Optional + nil => keep default value - - buildString("return _$$_t;"); - - buildString("}"); - return getBuiltString(); - } - - protected String primitivePackName(Class<?> type) { - if(type == boolean.class) { - return "packBoolean"; - } else if(type == byte.class) { - return "packByte"; - } else if(type == short.class) { - return "packShort"; - } else if(type == int.class) { - return "packInt"; - } else if(type == long.class) { - return "packLong"; - } else if(type == float.class) { - return "packFloat"; - } else if(type == double.class) { - return "packDouble"; - } - return null; - } - - protected String primitiveUnpackName(Class<?> type) { - if(type == boolean.class) { - return "unpackBoolean"; - } else if(type == byte.class) { - return "unpackByte"; - } else if(type == short.class) { - return "unpackShort"; - } else if(type == int.class) { - return "unpackInt"; - } else if(type == long.class) { - return "unpackLong"; - } else if(type == float.class) { - return "unpackFloat"; - } else if(type == double.class) { - return "unpackDouble"; - } - return null; - } - - protected String primitiveConvertName(Class<?> type) { - if(type == boolean.class) { - return "asBoolean"; - } else if(type == byte.class) { - return "asByte"; - } else if(type == short.class) { - return "asShort"; - } else if(type == int.class) { - return "asInt"; - } else if(type == long.class) { - return "asLong"; - } else if(type == float.class) { - return "asFloat"; - } else if(type == double.class) { - return "asDouble"; - } - return null; - } - } - - public Template buildTemplate(Class<?> targetClass, FieldEntry[] entries) { + @Override + public Template buildTemplate(Class<?> targetClass, IFieldEntry[] entries) { // FIXME private / packagefields //for(FieldEntry e : entries) { // Field f = e.getField(); @@ -556,7 +150,7 @@ public class JavassistTemplateBuilder extends TemplateBuilder { Template[] tmpls = new Template[entries.length]; for(int i=0; i < entries.length; i++) { - FieldEntry e = entries[i]; + IFieldEntry e = entries[i]; if(!e.isAvailable()) { tmpls[i] = null; } else { @@ -565,10 +159,21 @@ public class JavassistTemplateBuilder extends TemplateBuilder { } } - BuildContext bc = new BuildContext(this); + BuildContextBase bc = getBuildContextFacotry().createBuildContext(this); return bc.buildTemplate(targetClass, entries, tmpls); } + @Override + public IFieldEntryReader getFieldEntryReader() { + return reader; + } + + public BuildContextFactory getBuildContextFacotry() { + return buildContextFactory; + } + + + /* static class JavassistOrdinalEnumTemplate extends ReflectionTemplateBuilder.ReflectionOrdinalEnumTemplate { JavassistOrdinalEnumTemplate(Enum<?>[] entries) { super(entries); @@ -610,6 +215,6 @@ public class JavassistTemplateBuilder extends TemplateBuilder { Class<?> componentClass = Array.newInstance(componentTemplate.getComponentClass(), 0).getClass(); return new ReflectionTemplateBuilder.ReflectionMultidimentionalArrayTemplate(componentClass, componentTemplate); } - } + }*/ } diff --git a/java/src/main/java/org/msgpack/template/ReflectionTemplateBuilder.java b/java/src/main/java/org/msgpack/template/ReflectionTemplateBuilder.java index 03ff2067..c85b69f9 100644 --- a/java/src/main/java/org/msgpack/template/ReflectionTemplateBuilder.java +++ b/java/src/main/java/org/msgpack/template/ReflectionTemplateBuilder.java @@ -22,17 +22,26 @@ import java.lang.reflect.*; import java.util.Map; import java.util.HashMap; import org.msgpack.*; +import org.msgpack.template.builder.CustomTemplateBuilder; +import org.msgpack.template.builder.TemplateBuilder; -public class ReflectionTemplateBuilder extends TemplateBuilder { - private static ReflectionTemplateBuilder instance; +public class ReflectionTemplateBuilder extends CustomTemplateBuilder { + /*private static ReflectionTemplateBuilder instance; public synchronized static ReflectionTemplateBuilder getInstance() { if(instance == null) { instance = new ReflectionTemplateBuilder(); } return instance; + }*/ + + IFieldEntryReader reader = new FieldEntryReader(); + + @Override + public IFieldEntryReader getFieldEntryReader(){ + return reader; } - private ReflectionTemplateBuilder() { + public ReflectionTemplateBuilder() { } static abstract class ReflectionFieldEntry extends FieldEntry { @@ -373,9 +382,10 @@ public class ReflectionTemplateBuilder extends TemplateBuilder { } } - public Template buildTemplate(Class<?> targetClass, FieldEntry[] entries) { - for(FieldEntry e : entries) { - Field f = e.getField(); + public Template buildTemplate(Class<?> targetClass, IFieldEntry[] entries) { + // TODO Now it is simply cast. + for(IFieldEntry e : entries) { + Field f = ((FieldEntry)e).getField(); int mod = f.getModifiers(); if(!Modifier.isPublic(mod)) { f.setAccessible(true); @@ -384,7 +394,7 @@ public class ReflectionTemplateBuilder extends TemplateBuilder { ReflectionFieldEntry[] res = new ReflectionFieldEntry[entries.length]; for(int i=0; i < entries.length; i++) { - FieldEntry e = entries[i]; + FieldEntry e = (FieldEntry)entries[i]; Class<?> type = e.getType(); if(!e.isAvailable()) { res[i] = new NullFieldEntry(e); @@ -411,159 +421,5 @@ public class ReflectionTemplateBuilder extends TemplateBuilder { return new ReflectionTemplate(targetClass, res); } - static class ReflectionOrdinalEnumTemplate extends AbstractTemplate { - protected Enum<?>[] entries; - protected Map<Enum<?>, Integer> reverse; - - ReflectionOrdinalEnumTemplate(Enum<?>[] entries) { - this.entries = entries; - this.reverse = new HashMap<Enum<?>, Integer>(); - for(int i=0; i < entries.length; i++) { - this.reverse.put(entries[i], i); - } - } - - public void pack(Packer pk, Object target) throws IOException { - Integer ord = reverse.get(target); - if(ord == null) { - throw new MessageTypeException(); - } - pk.pack((int)ord); - } - - public Object unpack(Unpacker pac, Object to) throws IOException, MessageTypeException { - int ord = pac.unpackInt(); - if(entries.length <= ord) { - throw new MessageTypeException(); - } - return entries[ord]; - } - - public Object convert(MessagePackObject from, Object to) throws MessageTypeException { - int ord = from.asInt(); - if(entries.length <= ord) { - throw new MessageTypeException(); - } - return entries[ord]; - } - } - - public Template buildOrdinalEnumTemplate(Class<?> targetClass, Enum<?>[] entries) { - return new ReflectionOrdinalEnumTemplate(entries); - } - - - static class ReflectionObjectArrayTemplate extends AbstractTemplate { - private Class<?> componentClass; - private Template elementTemplate; - - public ReflectionObjectArrayTemplate(Class<?> componentClass, Template elementTemplate) { - this.componentClass = componentClass; - this.elementTemplate = elementTemplate; - } - - public void pack(Packer pk, Object target) throws IOException { - if(!(target instanceof Object[]) || !componentClass.isAssignableFrom(target.getClass().getComponentType())) { - throw new MessageTypeException(); - } - Object[] array = (Object[])target; - int length = array.length; - pk.packArray(length); - for(int i=0; i < length; i++) { - elementTemplate.pack(pk, array[i]); - } - } - - public Object unpack(Unpacker pac, Object to) throws IOException { - int length = pac.unpackArray(); - Object[] array = (Object[])Array.newInstance(componentClass, length); - for(int i=0; i < length; i++) { - array[i] = elementTemplate.unpack(pac, null); - } - return array; - } - - public Object convert(MessagePackObject from, Object to) throws MessageTypeException { - MessagePackObject[] src = from.asArray(); - int length = src.length; - Object[] array = (Object[])Array.newInstance(componentClass, length); - for(int i=0; i < length; i++) { - array[i] = elementTemplate.convert(src[i], null); - } - return array; - } - } - - static class ReflectionMultidimentionalArrayTemplate extends AbstractTemplate { - private Class<?> componentClass; - private Template componentTemplate; - - public ReflectionMultidimentionalArrayTemplate(Class<?> componentClass, Template componentTemplate) { - this.componentClass = componentClass; - this.componentTemplate = componentTemplate; - } - - Class<?> getComponentClass() { - return componentClass; - } - - public void pack(Packer pk, Object target) throws IOException { - Object[] array = (Object[])target; - int length = array.length; - pk.packArray(length); - for(int i=0; i < length; i++) { - componentTemplate.pack(pk, array[i]); - } - } - - public Object unpack(Unpacker pac, Object to) throws IOException, MessageTypeException { - int length = pac.unpackArray(); - Object[] array = (Object[])Array.newInstance(componentClass, length); - for(int i=0; i < length; i++) { - array[i] = componentTemplate.unpack(pac, null); - } - return array; - } - - public Object convert(MessagePackObject from, Object to) throws MessageTypeException { - MessagePackObject[] src = from.asArray(); - int length = src.length; - Object[] array = (Object[])Array.newInstance(componentClass, length); - for(int i=0; i < length; i++) { - array[i] = componentTemplate.convert(src[i], null); - } - return array; - } - } - - public Template buildArrayTemplate(Type arrayType, Type genericBaseType, Class<?> baseClass, int dim) { - if(dim == 1) { - if(baseClass == boolean.class) { - return BooleanArrayTemplate.getInstance(); - } else if(baseClass == short.class) { - return ShortArrayTemplate.getInstance(); - } else if(baseClass == int.class) { - return IntArrayTemplate.getInstance(); - } else if(baseClass == long.class) { - return LongArrayTemplate.getInstance(); - } else if(baseClass == float.class) { - return FloatArrayTemplate.getInstance(); - } else if(baseClass == double.class) { - return DoubleArrayTemplate.getInstance(); - } else { - Template baseTemplate = TemplateRegistry.lookup(genericBaseType); - return new ReflectionObjectArrayTemplate(baseClass, baseTemplate); - } - } else if(dim == 2) { - Class<?> componentClass = Array.newInstance(baseClass, 0).getClass(); - Template componentTemplate = buildArrayTemplate(arrayType, genericBaseType, baseClass, dim-1); - return new ReflectionMultidimentionalArrayTemplate(componentClass, componentTemplate); - } else { - ReflectionMultidimentionalArrayTemplate componentTemplate = (ReflectionMultidimentionalArrayTemplate) - buildArrayTemplate(arrayType, genericBaseType, baseClass, dim-1); - Class<?> componentClass = Array.newInstance(componentTemplate.getComponentClass(), 0).getClass(); - return new ReflectionMultidimentionalArrayTemplate(componentClass, componentTemplate); - } - } } diff --git a/java/src/main/java/org/msgpack/template/TemplateRegistry.java b/java/src/main/java/org/msgpack/template/TemplateRegistry.java index 3f98fb46..9c447cc2 100644 --- a/java/src/main/java/org/msgpack/template/TemplateRegistry.java +++ b/java/src/main/java/org/msgpack/template/TemplateRegistry.java @@ -26,33 +26,55 @@ import java.lang.annotation.Annotation; import org.msgpack.annotation.MessagePackMessage; import org.msgpack.annotation.MessagePackDelegate; import org.msgpack.annotation.MessagePackOrdinalEnum; +import org.msgpack.template.builder.BuilderSelectorRegistry; +import org.msgpack.template.builder.CustomTemplateBuilder; +import org.msgpack.template.builder.TemplateBuilder; import org.msgpack.Template; import org.msgpack.Templates; public class TemplateRegistry { private static Map<Type, Template> map; private static Map<Type, GenericTemplate> genericMap; + + private static BuilderSelectorRegistry builderSelectorRegistry; static { map = new HashMap<Type, Template>(); genericMap = new HashMap<Type, GenericTemplate>(); BuiltInTemplateLoader.load(); + builderSelectorRegistry = BuilderSelectorRegistry.getInstance(); } public static void register(Class<?> target) { // auto-detect - if(target.isEnum()) { + TemplateBuilder builder = builderSelectorRegistry.select(target); + if(builder != null){ + register(target,builder.buildTemplate(target)); + }else{ + register(target,builderSelectorRegistry.getForceBuilder().buildTemplate(target)); + } + /*if(target.isEnum()) { register(target, TemplateBuilder.buildOrdinalEnum(target)); } else { register(target, TemplateBuilder.build(target)); - } + }*/ } public static void register(Class<?> target, FieldOption implicitOption) { - register(target, TemplateBuilder.build(target, implicitOption)); + TemplateBuilder builder = builderSelectorRegistry.select(target); + if(builder != null && builder instanceof CustomTemplateBuilder){ + register(target, ((CustomTemplateBuilder)builder).buildTemplate(target, implicitOption)); + }else{ + throw new TemplateBuildException("cannot build template with filed option"); + } } public static void register(Class<?> target, FieldList flist) throws NoSuchFieldException { - register(target, TemplateBuilder.build(target, flist)); + TemplateBuilder builder = builderSelectorRegistry.select(target); + if(builder != null && builder instanceof CustomTemplateBuilder){ + register(target, ((CustomTemplateBuilder)builder).buildTemplate(target, flist)); + }else{ + throw new TemplateBuildException("cannot build template with filed list"); + } } public static synchronized void register(Type rawType, Template tmpl) { @@ -102,7 +124,7 @@ public class TemplateRegistry { return tmpl; } - if(targetType instanceof GenericArrayType) { + /*if(targetType instanceof GenericArrayType) { // GenericArrayType is not a Class<?> tmpl = TemplateBuilder.buildArray(targetType); register(targetType, tmpl); @@ -129,7 +151,17 @@ public class TemplateRegistry { tmpl = TemplateBuilder.buildOrdinalEnum(target); register(target, tmpl); return tmpl; + }*/ + // find match TemplateBuilder + TemplateBuilder builder = BuilderSelectorRegistry.getInstance().select(targetType); + if(builder != null){ + tmpl = builder.buildTemplate(targetType); + register(targetType,tmpl); + return tmpl; } + + + Class<?> target = (Class<?>)targetType; for(Class<?> i : target.getInterfaces()) { tmpl = map.get(i); @@ -150,7 +182,7 @@ public class TemplateRegistry { } if(forceBuild) { - tmpl = TemplateBuilder.build(target); + tmpl = builderSelectorRegistry.getForceBuilder().buildTemplate(target); register(target, tmpl); return tmpl; } @@ -198,8 +230,5 @@ public class TemplateRegistry { return ao.getAnnotation(with) != null; } - public static void setTemplateBuilder(TemplateBuilder builder) { - TemplateBuilder.setInstance(builder); - } } diff --git a/java/src/main/java/org/msgpack/template/builder/ArrayTemplateBuilder.java b/java/src/main/java/org/msgpack/template/builder/ArrayTemplateBuilder.java new file mode 100644 index 00000000..93a8aba8 --- /dev/null +++ b/java/src/main/java/org/msgpack/template/builder/ArrayTemplateBuilder.java @@ -0,0 +1,173 @@ +package org.msgpack.template.builder; + +import java.io.IOException; +import java.lang.reflect.Array; +import java.lang.reflect.GenericArrayType; +import java.lang.reflect.ParameterizedType; +import java.lang.reflect.Type; +import java.util.HashMap; +import java.util.Map; + +import org.msgpack.AbstractTemplate; +import org.msgpack.MessagePackObject; +import org.msgpack.MessageTypeException; +import org.msgpack.Packer; +import org.msgpack.Template; +import org.msgpack.Unpacker; +import org.msgpack.template.BooleanArrayTemplate; +import org.msgpack.template.DoubleArrayTemplate; +import org.msgpack.template.FloatArrayTemplate; +import org.msgpack.template.IFieldEntry; +import org.msgpack.template.IFieldEntryReader; +import org.msgpack.template.IntArrayTemplate; +import org.msgpack.template.LongArrayTemplate; +import org.msgpack.template.ShortArrayTemplate; +import org.msgpack.template.TemplateRegistry; + +public class ArrayTemplateBuilder extends TemplateBuilder { + + + + + static class ReflectionObjectArrayTemplate extends AbstractTemplate { + private Class<?> componentClass; + private Template elementTemplate; + + public ReflectionObjectArrayTemplate(Class<?> componentClass, Template elementTemplate) { + this.componentClass = componentClass; + this.elementTemplate = elementTemplate; + } + + public void pack(Packer pk, Object target) throws IOException { + if(!(target instanceof Object[]) || !componentClass.isAssignableFrom(target.getClass().getComponentType())) { + throw new MessageTypeException(); + } + Object[] array = (Object[])target; + int length = array.length; + pk.packArray(length); + for(int i=0; i < length; i++) { + elementTemplate.pack(pk, array[i]); + } + } + + public Object unpack(Unpacker pac, Object to) throws IOException { + int length = pac.unpackArray(); + Object[] array = (Object[])Array.newInstance(componentClass, length); + for(int i=0; i < length; i++) { + array[i] = elementTemplate.unpack(pac, null); + } + return array; + } + + public Object convert(MessagePackObject from, Object to) throws MessageTypeException { + MessagePackObject[] src = from.asArray(); + int length = src.length; + Object[] array = (Object[])Array.newInstance(componentClass, length); + for(int i=0; i < length; i++) { + array[i] = elementTemplate.convert(src[i], null); + } + return array; + } + } + + static class ReflectionMultidimentionalArrayTemplate extends AbstractTemplate { + private Class<?> componentClass; + private Template componentTemplate; + + public ReflectionMultidimentionalArrayTemplate(Class<?> componentClass, Template componentTemplate) { + this.componentClass = componentClass; + this.componentTemplate = componentTemplate; + } + + Class<?> getComponentClass() { + return componentClass; + } + + public void pack(Packer pk, Object target) throws IOException { + Object[] array = (Object[])target; + int length = array.length; + pk.packArray(length); + for(int i=0; i < length; i++) { + componentTemplate.pack(pk, array[i]); + } + } + + public Object unpack(Unpacker pac, Object to) throws IOException, MessageTypeException { + int length = pac.unpackArray(); + Object[] array = (Object[])Array.newInstance(componentClass, length); + for(int i=0; i < length; i++) { + array[i] = componentTemplate.unpack(pac, null); + } + return array; + } + + public Object convert(MessagePackObject from, Object to) throws MessageTypeException { + MessagePackObject[] src = from.asArray(); + int length = src.length; + Object[] array = (Object[])Array.newInstance(componentClass, length); + for(int i=0; i < length; i++) { + array[i] = componentTemplate.convert(src[i], null); + } + return array; + } + } + @Override + public Template buildTemplate(Type arrayType) { + Type baseType; + Class<?> baseClass; + int dim = 1; + if(arrayType instanceof GenericArrayType) { + GenericArrayType type = (GenericArrayType)arrayType; + baseType = type.getGenericComponentType(); + while(baseType instanceof GenericArrayType) { + baseType = ((GenericArrayType)baseType).getGenericComponentType(); + dim += 1; + } + if(baseType instanceof ParameterizedType) { + baseClass = (Class<?>)((ParameterizedType)baseType).getRawType(); + } else { + baseClass = (Class<?>)baseType; + } + } else { + Class<?> type = (Class<?>)arrayType; + baseClass = type.getComponentType(); + while(baseClass.isArray()) { + baseClass = baseClass.getComponentType(); + dim += 1; + } + baseType = baseClass; + } + return toTemplate(arrayType, baseType, baseClass, dim); + + } + private Template toTemplate(Type arrayType, Type genericBaseType, Class<?> baseClass, int dim) { + if(dim == 1) { + if(baseClass == boolean.class) { + return BooleanArrayTemplate.getInstance(); + } else if(baseClass == short.class) { + return ShortArrayTemplate.getInstance(); + } else if(baseClass == int.class) { + return IntArrayTemplate.getInstance(); + } else if(baseClass == long.class) { + return LongArrayTemplate.getInstance(); + } else if(baseClass == float.class) { + return FloatArrayTemplate.getInstance(); + } else if(baseClass == double.class) { + return DoubleArrayTemplate.getInstance(); + } else { + Template baseTemplate = TemplateRegistry.lookup(genericBaseType); + return new ReflectionObjectArrayTemplate(baseClass, baseTemplate); + } + } else if(dim == 2) { + Class<?> componentClass = Array.newInstance(baseClass, 0).getClass(); + Template componentTemplate = toTemplate(arrayType, genericBaseType, baseClass, dim-1); + return new ReflectionMultidimentionalArrayTemplate(componentClass, componentTemplate); + } else { + ReflectionMultidimentionalArrayTemplate componentTemplate = (ReflectionMultidimentionalArrayTemplate) + toTemplate(arrayType, genericBaseType, baseClass, dim-1); + Class<?> componentClass = Array.newInstance(componentTemplate.getComponentClass(), 0).getClass(); + return new ReflectionMultidimentionalArrayTemplate(componentClass, componentTemplate); + } + } + +} diff --git a/java/src/main/java/org/msgpack/template/builder/ArrayTemplateBuilderSelector.java b/java/src/main/java/org/msgpack/template/builder/ArrayTemplateBuilderSelector.java new file mode 100644 index 00000000..30417dd0 --- /dev/null +++ b/java/src/main/java/org/msgpack/template/builder/ArrayTemplateBuilderSelector.java @@ -0,0 +1,35 @@ +package org.msgpack.template.builder; + +import java.lang.reflect.GenericArrayType; +import java.lang.reflect.Type; + +import org.msgpack.Template; + +public class ArrayTemplateBuilderSelector implements BuilderSelector { + + public static final String NAME = "ArrayTemplateBuilder"; + + @Override + public String getName(){ + return NAME; + } + + + @Override + public boolean matchType(Type targetType) { + if(targetType instanceof GenericArrayType){ + return true; + } + Class<?> targetClass = (Class<?>)targetType; + return targetClass.isArray(); + } + + ArrayTemplateBuilder templateBuilder = new ArrayTemplateBuilder(); + + @Override + public TemplateBuilder getTemplateBuilder(Type target) { + return templateBuilder; + } + + +} diff --git a/java/src/main/java/org/msgpack/template/builder/BuilderSelector.java b/java/src/main/java/org/msgpack/template/builder/BuilderSelector.java new file mode 100644 index 00000000..d30aa90b --- /dev/null +++ b/java/src/main/java/org/msgpack/template/builder/BuilderSelector.java @@ -0,0 +1,27 @@ +package org.msgpack.template.builder; + +import java.lang.reflect.Type; + +/** + * Match condition for TemplateBuilder. + * @author takeshita + * + */ +public interface BuilderSelector { + + + /** + * Name of this. + * @return + */ + public String getName(); + + + public abstract boolean matchType(Type targetType); + + + public abstract TemplateBuilder getTemplateBuilder(Type targetType); + + + +} diff --git a/java/src/main/java/org/msgpack/template/builder/BuilderSelectorRegistry.java b/java/src/main/java/org/msgpack/template/builder/BuilderSelectorRegistry.java new file mode 100644 index 00000000..329f882b --- /dev/null +++ b/java/src/main/java/org/msgpack/template/builder/BuilderSelectorRegistry.java @@ -0,0 +1,213 @@ +package org.msgpack.template.builder; + +import java.lang.reflect.Type; +import java.util.LinkedList; +import java.util.List; + +import org.msgpack.template.BeansFieldEntryReader; +import org.msgpack.template.BeansReflectionTemplateBuilder; +import org.msgpack.template.JavassistTemplateBuilder; +import org.msgpack.template.ReflectionTemplateBuilder; +import org.msgpack.template.javassist.BeansBuildContext; +import org.msgpack.template.javassist.BuildContext; +import org.msgpack.template.javassist.BuildContextBase; +import org.msgpack.template.javassist.BuildContextFactory; + +/** + * Registry for BuilderSelectors. + * You can modify BuilderSelector chain throw this class. + * + * @author takeshita + * + */ +public class BuilderSelectorRegistry { + + private static BuilderSelectorRegistry instance = new BuilderSelectorRegistry(); + static{ + initForJava(); + } + + public static BuilderSelectorRegistry getInstance(){ + return instance; + } + + TemplateBuilder forceBuilder; + + + List<BuilderSelector> builderSelectors = new LinkedList<BuilderSelector>(); + + private BuilderSelectorRegistry(){ + } + /** + * initialize BuilderSelectors for basic java enviroment. + */ + private static void initForJava(){ + + instance.append(new ArrayTemplateBuilderSelector()); + + if(isSupportJavassist()){ + instance.append( + new MessagePackMessageBuilderSelector( + new JavassistTemplateBuilder())); + instance.forceBuilder = new JavassistTemplateBuilder(); + + //Java beans + instance.append(new MessagePackBeansBuilderSelector( + new JavassistTemplateBuilder( + new BeansFieldEntryReader(), + new BuildContextFactory() { + @Override + public BuildContextBase createBuildContext(JavassistTemplateBuilder builder) { + return new BeansBuildContext(builder); + } + } + ))); + }else{ + instance.append( + new MessagePackMessageBuilderSelector( + new ReflectionTemplateBuilder())); + instance.forceBuilder = new ReflectionTemplateBuilder(); + + //Java beans + instance.append(new MessagePackBeansBuilderSelector( + new BeansReflectionTemplateBuilder())); + } + + instance.append(new MessagePackOrdinalEnumBuilderSelector()); + instance.append(new EnumBuilderSelector()); + } + public static boolean isSupportJavassist(){ + try { + return System.getProperty("java.vm.name").equals("Dalvik"); + } catch (Exception e) { + return true; + } + } + + /** + * Check whether same name BuilderSelector is registered. + * @param builderSelectorName + * @return + */ + public boolean contains(String builderSelectorName){ + for(BuilderSelector bs : builderSelectors){ + if(bs.getName().equals(builderSelectorName)){ + return true; + } + } + return false; + } + /** + * Append BuilderSelector to tail + * @param builderSelector + */ + public void append(BuilderSelector builderSelector){ + + if(contains(builderSelector.getName())){ + throw new RuntimeException("Duplicate BuilderSelector name:" + builderSelector.getName()); + } + this.builderSelectors.add(builderSelector); + } + /** + * Insert BuiderSelector to head + * @param builderSelector + */ + public void prepend(BuilderSelector builderSelector){ + if(contains(builderSelector.getName())){ + throw new RuntimeException("Duplicate BuilderSelector name:" + builderSelector.getName()); + } + if(builderSelectors.size() > 0){ + this.builderSelectors.add(0, builderSelector); + }else{ + this.builderSelectors.add(builderSelector); + } + } + + /** + * Insert BuilderSelector + * @param index + * @param builderSelector + */ + public void insert(int index,BuilderSelector builderSelector){ + if(contains(builderSelector.getName())){ + throw new RuntimeException("Duplicate BuilderSelector name:" + builderSelector.getName()); + } + if(builderSelectors.size() > 0){ + this.builderSelectors.add(index, builderSelector); + + }else{ + this.builderSelectors.add(builderSelector); + } + } + /** + * Replace same name BuilderSelector + * @param builderSelector + */ + public void replace(BuilderSelector builderSelector){ + String name = builderSelector.getName(); + int index = getIndex(name); + builderSelectors.add(index, builderSelector); + builderSelectors.remove(index + 1); + } + + /** + * Insert the BuilderSelector before BuilderSelector named "builderSelectorName". + * @param builderSelectorName + * @param builderSelector + */ + public void insertBefore(String builderSelectorName,BuilderSelector builderSelector){ + int index = getIndex(builderSelectorName); + + builderSelectors.add(index,builderSelector); + } + /** + * Insert the BuilderSelector after BuilderSelector named "builderSelectorName". + * @param builderSelectorName + * @param builderSelector + */ + public void insertAfter(String builderSelectorName,BuilderSelector builderSelector){ + int index = getIndex(builderSelectorName); + if(index + 1 == builderSelectors.size()){ + builderSelectors.add(builderSelector); + }else{ + builderSelectors.add(index + 1 , builderSelector); + } + } + private int getIndex(String builderSelectorName){ + int index = 0; + for(BuilderSelector bs : builderSelectors){ + if(bs.getName().equals(builderSelectorName)){ + break; + } + index++; + } + if(index >= builderSelectors.size()){ + throw new RuntimeException( + String.format("BuilderSelector named %s does not exist",builderSelectorName)); + } + return index; + } + + + public TemplateBuilder select(Type target){ + for(BuilderSelector selector : builderSelectors){ + if(selector.matchType(target)){ + return selector.getTemplateBuilder(target); + } + } + return null; + } + + public TemplateBuilder getForceBuilder() { + return forceBuilder; + } + + + public void setForceBuilder(TemplateBuilder forceBuilder) { + this.forceBuilder = forceBuilder; + } + + + + +} diff --git a/java/src/main/java/org/msgpack/template/builder/CustomTemplateBuilder.java b/java/src/main/java/org/msgpack/template/builder/CustomTemplateBuilder.java new file mode 100644 index 00000000..6f7f45cb --- /dev/null +++ b/java/src/main/java/org/msgpack/template/builder/CustomTemplateBuilder.java @@ -0,0 +1,53 @@ +package org.msgpack.template.builder; + +import java.lang.reflect.Type; + +import org.msgpack.Template; +import org.msgpack.template.FieldList; +import org.msgpack.template.FieldOption; +import org.msgpack.template.IFieldEntry; +import org.msgpack.template.IFieldEntryReader; +import org.msgpack.template.TemplateBuildException; +import org.msgpack.template.javassist.BuildContextFactory; + +public abstract class CustomTemplateBuilder extends TemplateBuilder { + + + public abstract IFieldEntryReader getFieldEntryReader(); + + + public abstract Template buildTemplate(Class<?> targetClass , IFieldEntry[] entries); + + public Template buildTemplate(Class<?> targetClass ,FieldOption implicitOption ){ + checkValidation(targetClass); + return buildTemplate(targetClass, + getFieldEntryReader().readFieldEntries(targetClass, implicitOption)); + } + public Template buildTemplate(Class<?> targetClass, FieldList flist) throws NoSuchFieldException { + checkValidation(targetClass); + return buildTemplate(targetClass, getFieldEntryReader().convertFieldEntries(targetClass, flist)); + } + + @Override + public Template buildTemplate(Type targetType) { + Class<?> targetClass = (Class<?>)targetType; + IFieldEntryReader reader = getFieldEntryReader(); + FieldOption implicitOption = reader.readImplicitFieldOption(targetClass); + checkValidation(targetClass); + + IFieldEntry[] entries = reader.readFieldEntries(targetClass, implicitOption); + + return buildTemplate(targetClass,entries); + } + private void checkValidation(Class<?> targetClass) { + if(targetClass.isInterface()) { + throw new TemplateBuildException("cannot build template of interface"); + } + if(targetClass.isArray()) { + throw new TemplateBuildException("cannot build template of array class"); + } + if(targetClass.isPrimitive()) { + throw new TemplateBuildException("cannot build template of primitive type"); + } + } +} \ No newline at end of file diff --git a/java/src/main/java/org/msgpack/template/builder/EnumBuilderSelector.java b/java/src/main/java/org/msgpack/template/builder/EnumBuilderSelector.java new file mode 100644 index 00000000..b8a2701c --- /dev/null +++ b/java/src/main/java/org/msgpack/template/builder/EnumBuilderSelector.java @@ -0,0 +1,26 @@ +package org.msgpack.template.builder; + +import java.lang.reflect.Type; + +public class EnumBuilderSelector implements BuilderSelector { + + public static final String NAME = "EnumTemplateBuilder"; + + public String getName(){ + return NAME; + } + + @Override + public boolean matchType(Type targetType) { + return ((Class<?>)targetType).isEnum(); + } + + + OrdinalEnumTemplateBuilder builder = new OrdinalEnumTemplateBuilder(); + + @Override + public TemplateBuilder getTemplateBuilder(Type targetType) { + return builder; + } + +} diff --git a/java/src/main/java/org/msgpack/template/builder/MessagePackBeansBuilderSelector.java b/java/src/main/java/org/msgpack/template/builder/MessagePackBeansBuilderSelector.java new file mode 100644 index 00000000..3b4a5903 --- /dev/null +++ b/java/src/main/java/org/msgpack/template/builder/MessagePackBeansBuilderSelector.java @@ -0,0 +1,40 @@ +package org.msgpack.template.builder; + +import java.lang.annotation.Annotation; +import java.lang.reflect.Type; + +import org.msgpack.annotation.MessagePackBeans; +import org.msgpack.annotation.MessagePackMessage; + +public class MessagePackBeansBuilderSelector implements BuilderSelector{ + + public static final String NAME = "MessagePackBeansTemplateBuilder"; + + + TemplateBuilder builder; + public MessagePackBeansBuilderSelector(TemplateBuilder builder){ + this.builder = builder; + } + + + public String getName(){ + return NAME; + } + + @Override + public boolean matchType(Type targetType) { + Class<?> target = (Class<?>)targetType; + return isAnnotated(target, MessagePackBeans.class); + } + + @Override + public TemplateBuilder getTemplateBuilder(Type targetType) { + return builder; + } + + + private boolean isAnnotated(Class<?> ao, Class<? extends Annotation> with) { + return ao.getAnnotation(with) != null; + } + +} diff --git a/java/src/main/java/org/msgpack/template/builder/MessagePackMessageBuilderSelector.java b/java/src/main/java/org/msgpack/template/builder/MessagePackMessageBuilderSelector.java new file mode 100644 index 00000000..008b8f06 --- /dev/null +++ b/java/src/main/java/org/msgpack/template/builder/MessagePackMessageBuilderSelector.java @@ -0,0 +1,38 @@ +package org.msgpack.template.builder; + +import java.lang.annotation.Annotation; +import java.lang.reflect.Type; + +import org.msgpack.annotation.MessagePackMessage; + +public class MessagePackMessageBuilderSelector implements BuilderSelector{ + + public static final String NAME = "MessagePackMessageTemplateBuilder"; + + + TemplateBuilder builder; + public MessagePackMessageBuilderSelector(TemplateBuilder builder){ + this.builder = builder; + } + + public String getName(){ + return NAME; + } + + @Override + public boolean matchType(Type targetType) { + Class<?> target = (Class<?>)targetType; + return isAnnotated(target, MessagePackMessage.class); + } + + @Override + public TemplateBuilder getTemplateBuilder(Type targetType) { + return builder; + } + + + private boolean isAnnotated(Class<?> ao, Class<? extends Annotation> with) { + return ao.getAnnotation(with) != null; + } + +} diff --git a/java/src/main/java/org/msgpack/template/builder/MessagePackOrdinalEnumBuilderSelector.java b/java/src/main/java/org/msgpack/template/builder/MessagePackOrdinalEnumBuilderSelector.java new file mode 100644 index 00000000..2d32cb47 --- /dev/null +++ b/java/src/main/java/org/msgpack/template/builder/MessagePackOrdinalEnumBuilderSelector.java @@ -0,0 +1,34 @@ +package org.msgpack.template.builder; + +import java.lang.annotation.Annotation; +import java.lang.reflect.Type; + +import org.msgpack.annotation.MessagePackOrdinalEnum; + +public class MessagePackOrdinalEnumBuilderSelector implements BuilderSelector { + + public static final String NAME = "MessagePackOrdinalEnumBuilderTemplate"; + + public String getName(){ + return NAME; + } + + @Override + public boolean matchType(Type targetType) { + Class<?> target = (Class<?>)targetType; + return isAnnotated(target, MessagePackOrdinalEnum.class); + } + + OrdinalEnumTemplateBuilder builder = new OrdinalEnumTemplateBuilder(); + + @Override + public TemplateBuilder getTemplateBuilder(Type targetType) { + return builder; + } + + + private boolean isAnnotated(Class<?> ao, Class<? extends Annotation> with) { + return ao.getAnnotation(with) != null; + } + +} diff --git a/java/src/main/java/org/msgpack/template/builder/OrdinalEnumTemplateBuilder.java b/java/src/main/java/org/msgpack/template/builder/OrdinalEnumTemplateBuilder.java new file mode 100644 index 00000000..1d4752fc --- /dev/null +++ b/java/src/main/java/org/msgpack/template/builder/OrdinalEnumTemplateBuilder.java @@ -0,0 +1,68 @@ +package org.msgpack.template.builder; + +import java.io.IOException; +import java.lang.reflect.Type; +import java.util.HashMap; +import java.util.Map; + +import org.msgpack.AbstractTemplate; +import org.msgpack.MessagePackObject; +import org.msgpack.MessageTypeException; +import org.msgpack.Packer; +import org.msgpack.Template; +import org.msgpack.Unpacker; +import org.msgpack.template.TemplateBuildException; + +public class OrdinalEnumTemplateBuilder extends TemplateBuilder{ + + static class ReflectionOrdinalEnumTemplate extends AbstractTemplate { + protected Enum<?>[] entries; + protected Map<Enum<?>, Integer> reverse; + + ReflectionOrdinalEnumTemplate(Enum<?>[] entries) { + this.entries = entries; + this.reverse = new HashMap<Enum<?>, Integer>(); + for(int i=0; i < entries.length; i++) { + this.reverse.put(entries[i], i); + } + } + + public void pack(Packer pk, Object target) throws IOException { + Integer ord = reverse.get(target); + if(ord == null) { + throw new MessageTypeException(); + } + pk.pack((int)ord); + } + + public Object unpack(Unpacker pac, Object to) throws IOException, MessageTypeException { + int ord = pac.unpackInt(); + if(entries.length <= ord) { + throw new MessageTypeException(); + } + return entries[ord]; + } + + public Object convert(MessagePackObject from, Object to) throws MessageTypeException { + int ord = from.asInt(); + if(entries.length <= ord) { + throw new MessageTypeException(); + } + return entries[ord]; + } + } + @Override + public Template buildTemplate(Type targetType) { + Class<?> targetClass = (Class<?>)targetType; + checkOrdinalEnumValidation(targetClass); + Enum<?>[] entries = (Enum<?>[])targetClass.getEnumConstants(); + + return new ReflectionOrdinalEnumTemplate(entries); + } + private void checkOrdinalEnumValidation(Class<?> targetClass) { + if(!targetClass.isEnum()) { + throw new TemplateBuildException("tried to build ordinal enum template of non-enum class"); + } + } + +} diff --git a/java/src/main/java/org/msgpack/template/builder/TemplateBuilder.java b/java/src/main/java/org/msgpack/template/builder/TemplateBuilder.java new file mode 100644 index 00000000..0dd36ffc --- /dev/null +++ b/java/src/main/java/org/msgpack/template/builder/TemplateBuilder.java @@ -0,0 +1,327 @@ +// +// 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.template.builder; + +import java.io.IOException; +import java.lang.reflect.*; +import java.lang.annotation.*; +import java.util.List; +import java.util.ArrayList; +import java.util.EnumSet; +import org.msgpack.*; +import org.msgpack.annotation.*; +import org.msgpack.template.FieldList; +import org.msgpack.template.FieldOption; +import org.msgpack.template.IFieldEntry; +import org.msgpack.template.IFieldEntryReader; +import org.msgpack.template.JavassistTemplateBuilder; +import org.msgpack.template.ReflectionTemplateBuilder; + +public abstract class TemplateBuilder { + + public abstract Template buildTemplate(Type targetType); + /* + // Override this method + public abstract Template buildTemplate(Class<?> targetClass, IFieldEntry[] entries); + + // Override this method + public abstract Template buildOrdinalEnumTemplate(Class<?> targetClass, Enum<?>[] entries); + + // Override this method + public abstract Template buildArrayTemplate(Type arrayType, Type genericBaseType, Class<?> baseClass, int dim); + + public abstract IFieldEntryReader getFieldEntryReader(); + + public Template buildTemplate(Class<?> targetClass, FieldList flist) throws NoSuchFieldException { + checkValidation(targetClass); + return buildTemplate(targetClass, getFieldEntryReader().convertFieldEntries(targetClass, flist)); + } + + public Template buildTemplate(Class<?> targetClass, FieldOption implicitOption) { + checkValidation(targetClass); + return buildTemplate(targetClass, getFieldEntryReader().readFieldEntries(targetClass, implicitOption)); + } + + public Template buildTemplate(Class<?> targetClass) { + FieldOption implicitOption = getFieldEntryReader().readImplicitFieldOption(targetClass); + return buildTemplate(targetClass, implicitOption); + } + + public Template buildOrdinalEnumTemplate(Class<?> targetClass) { + checkOrdinalEnumValidation(targetClass); + Enum<?>[] entries = (Enum<?>[])targetClass.getEnumConstants(); + return buildOrdinalEnumTemplate(targetClass, entries); + } + + public Template buildArrayTemplate(Type arrayType) { + Type baseType; + Class<?> baseClass; + int dim = 1; + if(arrayType instanceof GenericArrayType) { + GenericArrayType type = (GenericArrayType)arrayType; + baseType = type.getGenericComponentType(); + while(baseType instanceof GenericArrayType) { + baseType = ((GenericArrayType)baseType).getGenericComponentType(); + dim += 1; + } + if(baseType instanceof ParameterizedType) { + baseClass = (Class<?>)((ParameterizedType)baseType).getRawType(); + } else { + baseClass = (Class<?>)baseType; + } + } else { + Class<?> type = (Class<?>)arrayType; + baseClass = type.getComponentType(); + while(baseClass.isArray()) { + baseClass = baseClass.getComponentType(); + dim += 1; + } + baseType = baseClass; + } + return buildArrayTemplate(arrayType, baseType, baseClass, dim); + } + + private static Type getComponentType(Type arrayType) { + if(arrayType instanceof GenericArrayType) { + return ((GenericArrayType)arrayType).getGenericComponentType(); + } else { + return ((Class<?>)arrayType).getComponentType(); + } + } + private void checkValidation(Class<?> targetClass) { + if(targetClass.isInterface()) { + throw new TemplateBuildException("cannot build template of interface"); + } + if(targetClass.isArray()) { + throw new TemplateBuildException("cannot build template of array class"); + } + if(targetClass.isPrimitive()) { + throw new TemplateBuildException("cannot build template of primitive type"); + } + } + private void checkOrdinalEnumValidation(Class<?> targetClass) { + if(!targetClass.isEnum()) { + throw new TemplateBuildException("tried to build ordinal enum template of non-enum class"); + } + } + + + private static TemplateBuilder instance; + static { + instance = selectDefaultTemplateBuilder(); + } + + private static TemplateBuilder selectDefaultTemplateBuilder() { + try { + // FIXME JavassistTemplateBuilder doesn't work on DalvikVM + if(System.getProperty("java.vm.name").equals("Dalvik")) { + return ReflectionTemplateBuilder.getInstance(); + } + } catch (Exception e) { + } + return JavassistTemplateBuilder.getInstance(); + } + + public synchronized static void setInstance(TemplateBuilder builder) { + instance = builder; + } + + public static Template build(Class<?> targetClass) { + return instance.buildTemplate(targetClass); + } + + public static Template build(Class<?> targetClass, FieldOption implicitOption) { + return instance.buildTemplate(targetClass, implicitOption); + } + + public static Template build(Class<?> targetClass, FieldList flist) throws NoSuchFieldException { + return instance.buildTemplate(targetClass, flist); + } + + public static Template buildOrdinalEnum(Class<?> targetClass) { + return instance.buildOrdinalEnumTemplate(targetClass); + } + + public static Template buildArray(Type arrayType) { + return instance.buildArrayTemplate(arrayType); + }*/ + + /* + private static void checkValidation(Class<?> targetClass) { + if(targetClass.isInterface()) { + throw new TemplateBuildException("cannot build template of interface"); + } + if(targetClass.isArray()) { + throw new TemplateBuildException("cannot build template of array class"); + } + if(targetClass.isPrimitive()) { + throw new TemplateBuildException("cannot build template of primitive type"); + } + } + + private static void checkOrdinalEnumValidation(Class<?> targetClass) { + if(!targetClass.isEnum()) { + throw new TemplateBuildException("tried to build ordinal enum template of non-enum class"); + } + }*/ + + /* + static IFieldEntry[] convertFieldEntries(Class<?> targetClass, FieldList flist) throws NoSuchFieldException { + List<FieldList.Entry> src = flist.getList(); + FieldEntry[] result = new FieldEntry[src.size()]; + for(int i=0; i < src.size(); i++) { + FieldList.Entry s = src.get(i); + if(s.isAvailable()) { + result[i] = new FieldEntry(targetClass.getDeclaredField(s.getName()), s.getOption()); + } else { + result[i] = new FieldEntry(); + } + } + return result; + }*/ + + /*static IFieldEntry[] readFieldEntries(Class<?> targetClass, FieldOption implicitOption) { + Field[] allFields = readAllFields(targetClass); + + /* index: + * @Index(0) int field_a; // 0 + * int field_b; // 1 + * @Index(3) int field_c; // 3 + * int field_d; // 4 + * @Index(2) int field_e; // 2 + * int field_f; // 5 + *//* + List<FieldEntry> indexed = new ArrayList<FieldEntry>(); + int maxIndex = -1; + for(Field f : allFields) { + FieldOption opt = readFieldOption(f, implicitOption); + if(opt == FieldOption.IGNORE) { + // skip + continue; + } + + int index = readFieldIndex(f, maxIndex); + + if(indexed.size() > index && indexed.get(index) != null) { + throw new TemplateBuildException("duplicated index: "+index); + } + if(index < 0) { + throw new TemplateBuildException("invalid index: "+index); + } + + while(indexed.size() <= index) { + indexed.add(null); + } + indexed.set(index, new FieldEntry(f, opt)); + + if(maxIndex < index) { + maxIndex = index; + } + } + + FieldEntry[] result = new FieldEntry[maxIndex+1]; + for(int i=0; i < indexed.size(); i++) { + FieldEntry e = indexed.get(i); + if(e == null) { + result[i] = new FieldEntry(); + } else { + result[i] = e; + } + } + + return result; + }*/ + /* + private static Field[] readAllFields(Class<?> targetClass) { + // order: [fields of super class, ..., fields of this class] + List<Field[]> succ = new ArrayList<Field[]>(); + int total = 0; + for(Class<?> c = targetClass; c != Object.class; c = c.getSuperclass()) { + Field[] fields = c.getDeclaredFields(); + total += fields.length; + succ.add(fields); + } + Field[] result = new Field[total]; + int off = 0; + for(int i=succ.size()-1; i >= 0; i--) { + Field[] fields = succ.get(i); + System.arraycopy(fields, 0, result, off, fields.length); + off += fields.length; + } + return result; + } + + private static FieldOption readImplicitFieldOption(Class<?> targetClass) { + MessagePackMessage a = targetClass.getAnnotation(MessagePackMessage.class); + if(a == null) { + return FieldOption.DEFAULT; + } + return a.value(); + } + + private static FieldOption readFieldOption(Field field, FieldOption implicitOption) { + int mod = field.getModifiers(); + if(Modifier.isStatic(mod) || Modifier.isFinal(mod)) { + return FieldOption.IGNORE; + } + + if(isAnnotated(field, Ignore.class)) { + return FieldOption.IGNORE; + } else if(isAnnotated(field, Required.class)) { + return FieldOption.REQUIRED; + } else if(isAnnotated(field, Optional.class)) { + return FieldOption.OPTIONAL; + } else if(isAnnotated(field, Nullable.class)) { + if(field.getDeclaringClass().isPrimitive()) { + return FieldOption.REQUIRED; + } else { + return FieldOption.NULLABLE; + } + } + + if(implicitOption != FieldOption.DEFAULT) { + return implicitOption; + } + + // default mode: + // transient : Ignore + // public : Required + // others : Ignore + if(Modifier.isTransient(mod)) { + return FieldOption.IGNORE; + } else if(Modifier.isPublic(mod)) { + return FieldOption.REQUIRED; + } else { + return FieldOption.IGNORE; + } + } + + private static int readFieldIndex(Field field, int maxIndex) { + Index a = field.getAnnotation(Index.class); + if(a == null) { + return maxIndex + 1; + } else { + return a.value(); + } + } + + private static boolean isAnnotated(AccessibleObject ao, Class<? extends Annotation> with) { + return ao.getAnnotation(with) != null; + }*/ +} + diff --git a/java/src/main/java/org/msgpack/template/javassist/BeansBuildContext.java b/java/src/main/java/org/msgpack/template/javassist/BeansBuildContext.java new file mode 100644 index 00000000..74d477fd --- /dev/null +++ b/java/src/main/java/org/msgpack/template/javassist/BeansBuildContext.java @@ -0,0 +1,273 @@ + +package org.msgpack.template.javassist; + +import java.io.IOException; +import java.lang.reflect.Array; +import java.lang.reflect.Constructor; +import java.lang.reflect.InvocationTargetException; +import java.lang.reflect.Type; +import java.lang.Thread; + +import org.msgpack.*; +import org.msgpack.template.*; + +import javassist.CannotCompileException; +import javassist.ClassPool; +import javassist.CtClass; +import javassist.CtConstructor; +import javassist.CtMethod; +import javassist.CtNewConstructor; +import javassist.CtNewMethod; +import javassist.LoaderClassPath; +import javassist.NotFoundException; +import javassist.ClassClassPath; + +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + + + +public class BeansBuildContext extends BuildContextBase<BeansFieldEntry> { + protected BeansFieldEntry[] entries; + protected Class<?> origClass; + protected String origName; + protected Template[] templates; + protected int minimumArrayLength; + + public BeansBuildContext(JavassistTemplateBuilder director) { + super(director); + } + + public Template buildTemplate(Class<?> targetClass, BeansFieldEntry[] entries, Template[] templates) { + this.entries = entries; + this.templates = templates; + this.origClass = targetClass; + this.origName = this.origClass.getName(); + return build(this.origName); + } + + protected void setSuperClass() throws CannotCompileException, NotFoundException { + this.tmplCtClass.setSuperclass( + director.getCtClass(JavassistTemplate.class.getName())); + } + + protected void buildConstructor() throws CannotCompileException, NotFoundException { + // Constructor(Class targetClass, Template[] templates) + CtConstructor newCtCons = CtNewConstructor.make( + new CtClass[] { + director.getCtClass(Class.class.getName()), + director.getCtClass(Template.class.getName()+"[]") + }, + new CtClass[0], + this.tmplCtClass); + this.tmplCtClass.addConstructor(newCtCons); + } + + protected Template buildInstance(Class<?> c) throws NoSuchMethodException, InstantiationException, IllegalAccessException, InvocationTargetException { + Constructor<?> cons = c.getConstructor(new Class[] { + Class.class, + Template[].class + }); + Object tmpl = cons.newInstance(new Object[] { + this.origClass, + this.templates + }); + return (Template)tmpl; + } + + protected void buildMethodInit() { + this.minimumArrayLength = 0; + for(int i=0; i < entries.length; i++) { + IFieldEntry e = entries[i]; + if(e.isRequired() || e.isNullable()) { + this.minimumArrayLength = i+1; + } + } + } + + protected String buildPackMethodBody() { + resetStringBuilder(); + buildString("{"); + buildString("%s _$$_t = (%s)$2;", this.origName, this.origName); + buildString("$1.packArray(%d);", entries.length); + for(int i=0; i < entries.length; i++) { + BeansFieldEntry e = entries[i]; + if(!e.isAvailable()) { + buildString("$1.packNil();"); + continue; + } + Class<?> type = e.getType(); + if(type.isPrimitive()) { + buildString("$1.%s(_$$_t.%s());", primitivePackName(type), e.getGetterName()); + } else { + buildString("if(_$$_t.%s() == null) {", e.getGetterName()); + if(!e.isNullable() && !e.isOptional()) { + buildString("throw new %s();", MessageTypeException.class.getName()); + } else { + buildString("$1.packNil();"); + } + buildString("} else {"); + buildString(" this.templates[%d].pack($1, _$$_t.%s());", i, e.getGetterName()); + buildString("}"); + } + } + buildString("}"); + return getBuiltString(); + } + + protected String buildUnpackMethodBody() { + resetStringBuilder(); + buildString("{ "); + + buildString("%s _$$_t;", this.origName); + buildString("if($2 == null) {"); + buildString(" _$$_t = new %s();", this.origName); + buildString("} else {"); + buildString(" _$$_t = (%s)$2;", this.origName); + buildString("}"); + + buildString("int length = $1.unpackArray();"); + buildString("if(length < %d) {", this.minimumArrayLength); + buildString(" throw new %s();", MessageTypeException.class.getName()); + buildString("}"); + + int i; + for(i=0; i < this.minimumArrayLength; i++) { + BeansFieldEntry e = entries[i]; + if(!e.isAvailable()) { + buildString("$1.unpackObject();"); + continue; + } + + buildString("if($1.tryUnpackNull()) {"); + if(e.isRequired()) { + // Required + nil => exception + buildString("throw new %s();", MessageTypeException.class.getName()); + } else if(e.isOptional()) { + // Optional + nil => keep default value + } else { // Nullable + // Nullable + nil => set null + buildString("_$$_t.%s(null);", e.getSetterName()); + } + buildString("} else {"); + Class<?> type = e.getType(); + if(type.isPrimitive()) { + buildString("_$$_t.set%s( $1.%s() );", e.getName(), primitiveUnpackName(type)); + } else { + buildString("_$$_t.set%s( (%s)this.templates[%d].unpack($1, _$$_t.get%s()) );", e.getName(), e.getJavaTypeName(), i, e.getName()); + } + buildString("}"); + } + + for(; i < entries.length; i++) { + buildString("if(length <= %d) { return _$$_t; }", i); + + BeansFieldEntry e = entries[i]; + if(!e.isAvailable()) { + buildString("$1.unpackObject();"); + continue; + } + + buildString("if($1.tryUnpackNull()) {"); + // this is Optional field becaue i >= minimumArrayLength + // Optional + nil => keep default value + buildString("} else {"); + Class<?> type = e.getType(); + if(type.isPrimitive()) { + buildString("_$$_t.%s( $1.%s() );", e.getSetterName(), primitiveUnpackName(type)); + } else { + buildString("_$$_t.%s( (%s)this.templates[%d].unpack($1, _$$_t.%s()) );", e.getSetterName(), e.getJavaTypeName(), i, e.getGetterName()); + } + buildString("}"); + } + + // latter entries are all Optional + nil => keep default value + + buildString("for(int i=%d; i < length; i++) {", i); + buildString(" $1.unpackObject();"); + buildString("}"); + + buildString("return _$$_t;"); + + buildString("}"); + return getBuiltString(); + } + + protected String buildConvertMethodBody() { + resetStringBuilder(); + buildString("{ "); + + buildString("%s _$$_t;", this.origName); + buildString("if($2 == null) {"); + buildString(" _$$_t = new %s();", this.origName); + buildString("} else {"); + buildString(" _$$_t = (%s)$2;", this.origName); + buildString("}"); + + buildString("%s[] array = $1.asArray();", MessagePackObject.class.getName()); + buildString("int length = array.length;"); + buildString("if(length < %d) {", this.minimumArrayLength); + buildString(" throw new %s();", MessageTypeException.class.getName()); + buildString("}"); + + buildString("%s obj;", MessagePackObject.class.getName()); + + int i; + for(i=0; i < this.minimumArrayLength; i++) { + BeansFieldEntry e = entries[i]; + if(!e.isAvailable()) { + continue; + } + + buildString("obj = array[%d];", i); + buildString("if(obj.isNil()) {"); + if(e.isRequired()) { + // Required + nil => exception + buildString("throw new %s();", MessageTypeException.class.getName()); + } else if(e.isOptional()) { + // Optional + nil => keep default value + } else { // Nullable + // Nullable + nil => set null + buildString("_$$_t.%s( null );", e.getSetterName()); + } + buildString("} else {"); + Class<?> type = e.getType(); + if(type.isPrimitive()) { + buildString("_$$_t.%s( obj.%s() );", e.getSetterName(), primitiveConvertName(type)); + } else { + buildString("_$$_t.%s( (%s)this.templates[%d].convert(obj, _$$_t.%s()) );", e.getSetterName(), e.getJavaTypeName(), i, e.getGetterName()); + } + buildString("}"); + } + + for(; i < entries.length; i++) { + buildString("if(length <= %d) { return _$$_t; }", i); + + BeansFieldEntry e = entries[i]; + if(!e.isAvailable()) { + continue; + } + + buildString("obj = array[%d];", i); + buildString("if(obj.isNil()) {"); + // this is Optional field becaue i >= minimumArrayLength + // Optional + nil => keep default value + buildString("} else {"); + Class<?> type = e.getType(); + if(type.isPrimitive()) { + buildString("_$$_t.%s( obj.%s() );", e.getSetterName(), primitiveConvertName(type)); + } else { + buildString("_$$_t.%s( (%s)this.templates[%d].convert(obj, _$$_t.%s()) );", e.getSetterName(), e.getJavaTypeName(), i, e.getGetterName()); + } + buildString("}"); + } + + // latter entries are all Optional + nil => keep default value + + buildString("return _$$_t;"); + + buildString("}"); + return getBuiltString(); + } + +} \ No newline at end of file diff --git a/java/src/main/java/org/msgpack/template/javassist/BuildContext.java b/java/src/main/java/org/msgpack/template/javassist/BuildContext.java new file mode 100644 index 00000000..ff1c2fc2 --- /dev/null +++ b/java/src/main/java/org/msgpack/template/javassist/BuildContext.java @@ -0,0 +1,273 @@ + +package org.msgpack.template.javassist; + +import java.io.IOException; +import java.lang.reflect.Array; +import java.lang.reflect.Constructor; +import java.lang.reflect.InvocationTargetException; +import java.lang.reflect.Type; +import java.lang.Thread; + +import org.msgpack.*; +import org.msgpack.template.*; + +import javassist.CannotCompileException; +import javassist.ClassPool; +import javassist.CtClass; +import javassist.CtConstructor; +import javassist.CtMethod; +import javassist.CtNewConstructor; +import javassist.CtNewMethod; +import javassist.LoaderClassPath; +import javassist.NotFoundException; +import javassist.ClassClassPath; + +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + + + +public class BuildContext extends BuildContextBase<FieldEntry> { + protected IFieldEntry[] entries; + protected Class<?> origClass; + protected String origName; + protected Template[] templates; + protected int minimumArrayLength; + + public BuildContext(JavassistTemplateBuilder director) { + super(director); + } + + public Template buildTemplate(Class<?> targetClass, FieldEntry[] entries, Template[] templates) { + this.entries = entries; + this.templates = templates; + this.origClass = targetClass; + this.origName = this.origClass.getName(); + return build(this.origName); + } + + protected void setSuperClass() throws CannotCompileException, NotFoundException { + this.tmplCtClass.setSuperclass( + director.getCtClass(JavassistTemplate.class.getName())); + } + + protected void buildConstructor() throws CannotCompileException, NotFoundException { + // Constructor(Class targetClass, Template[] templates) + CtConstructor newCtCons = CtNewConstructor.make( + new CtClass[] { + director.getCtClass(Class.class.getName()), + director.getCtClass(Template.class.getName()+"[]") + }, + new CtClass[0], + this.tmplCtClass); + this.tmplCtClass.addConstructor(newCtCons); + } + + protected Template buildInstance(Class<?> c) throws NoSuchMethodException, InstantiationException, IllegalAccessException, InvocationTargetException { + Constructor<?> cons = c.getConstructor(new Class[] { + Class.class, + Template[].class + }); + Object tmpl = cons.newInstance(new Object[] { + this.origClass, + this.templates + }); + return (Template)tmpl; + } + + protected void buildMethodInit() { + this.minimumArrayLength = 0; + for(int i=0; i < entries.length; i++) { + IFieldEntry e = entries[i]; + if(e.isRequired() || e.isNullable()) { + this.minimumArrayLength = i+1; + } + } + } + + protected String buildPackMethodBody() { + resetStringBuilder(); + buildString("{"); + buildString("%s _$$_t = (%s)$2;", this.origName, this.origName); + buildString("$1.packArray(%d);", entries.length); + for(int i=0; i < entries.length; i++) { + IFieldEntry e = entries[i]; + if(!e.isAvailable()) { + buildString("$1.packNil();"); + continue; + } + Class<?> type = e.getType(); + if(type.isPrimitive()) { + buildString("$1.%s(_$$_t.%s);", primitivePackName(type), e.getName()); + } else { + buildString("if(_$$_t.%s == null) {", e.getName()); + if(!e.isNullable() && !e.isOptional()) { + buildString("throw new %s();", MessageTypeException.class.getName()); + } else { + buildString("$1.packNil();"); + } + buildString("} else {"); + buildString(" this.templates[%d].pack($1, _$$_t.%s);", i, e.getName()); + buildString("}"); + } + } + buildString("}"); + return getBuiltString(); + } + + protected String buildUnpackMethodBody() { + resetStringBuilder(); + buildString("{ "); + + buildString("%s _$$_t;", this.origName); + buildString("if($2 == null) {"); + buildString(" _$$_t = new %s();", this.origName); + buildString("} else {"); + buildString(" _$$_t = (%s)$2;", this.origName); + buildString("}"); + + buildString("int length = $1.unpackArray();"); + buildString("if(length < %d) {", this.minimumArrayLength); + buildString(" throw new %s();", MessageTypeException.class.getName()); + buildString("}"); + + int i; + for(i=0; i < this.minimumArrayLength; i++) { + IFieldEntry e = entries[i]; + if(!e.isAvailable()) { + buildString("$1.unpackObject();"); + continue; + } + + buildString("if($1.tryUnpackNull()) {"); + if(e.isRequired()) { + // Required + nil => exception + buildString("throw new %s();", MessageTypeException.class.getName()); + } else if(e.isOptional()) { + // Optional + nil => keep default value + } else { // Nullable + // Nullable + nil => set null + buildString("_$$_t.%s = null;", e.getName()); + } + buildString("} else {"); + Class<?> type = e.getType(); + if(type.isPrimitive()) { + buildString("_$$_t.%s = $1.%s();", e.getName(), primitiveUnpackName(type)); + } else { + buildString("_$$_t.%s = (%s)this.templates[%d].unpack($1, _$$_t.%s);", e.getName(), e.getJavaTypeName(), i, e.getName()); + } + buildString("}"); + } + + for(; i < entries.length; i++) { + buildString("if(length <= %d) { return _$$_t; }", i); + + IFieldEntry e = entries[i]; + if(!e.isAvailable()) { + buildString("$1.unpackObject();"); + continue; + } + + buildString("if($1.tryUnpackNull()) {"); + // this is Optional field becaue i >= minimumArrayLength + // Optional + nil => keep default value + buildString("} else {"); + Class<?> type = e.getType(); + if(type.isPrimitive()) { + buildString("_$$_t.%s = $1.%s();", e.getName(), primitiveUnpackName(type)); + } else { + buildString("_$$_t.%s = (%s)this.templates[%d].unpack($1, _$$_t.%s);", e.getName(), e.getJavaTypeName(), i, e.getName()); + } + buildString("}"); + } + + // latter entries are all Optional + nil => keep default value + + buildString("for(int i=%d; i < length; i++) {", i); + buildString(" $1.unpackObject();"); + buildString("}"); + + buildString("return _$$_t;"); + + buildString("}"); + return getBuiltString(); + } + + protected String buildConvertMethodBody() { + resetStringBuilder(); + buildString("{ "); + + buildString("%s _$$_t;", this.origName); + buildString("if($2 == null) {"); + buildString(" _$$_t = new %s();", this.origName); + buildString("} else {"); + buildString(" _$$_t = (%s)$2;", this.origName); + buildString("}"); + + buildString("%s[] array = $1.asArray();", MessagePackObject.class.getName()); + buildString("int length = array.length;"); + buildString("if(length < %d) {", this.minimumArrayLength); + buildString(" throw new %s();", MessageTypeException.class.getName()); + buildString("}"); + + buildString("%s obj;", MessagePackObject.class.getName()); + + int i; + for(i=0; i < this.minimumArrayLength; i++) { + IFieldEntry e = entries[i]; + if(!e.isAvailable()) { + continue; + } + + buildString("obj = array[%d];", i); + buildString("if(obj.isNil()) {"); + if(e.isRequired()) { + // Required + nil => exception + buildString("throw new %s();", MessageTypeException.class.getName()); + } else if(e.isOptional()) { + // Optional + nil => keep default value + } else { // Nullable + // Nullable + nil => set null + buildString("_$$_t.%s = null;", e.getName()); + } + buildString("} else {"); + Class<?> type = e.getType(); + if(type.isPrimitive()) { + buildString("_$$_t.%s = obj.%s();", e.getName(), primitiveConvertName(type)); + } else { + buildString("_$$_t.%s = (%s)this.templates[%d].convert(obj, _$$_t.%s);", e.getName(), e.getJavaTypeName(), i, e.getName()); + } + buildString("}"); + } + + for(; i < entries.length; i++) { + buildString("if(length <= %d) { return _$$_t; }", i); + + IFieldEntry e = entries[i]; + if(!e.isAvailable()) { + continue; + } + + buildString("obj = array[%d];", i); + buildString("if(obj.isNil()) {"); + // this is Optional field becaue i >= minimumArrayLength + // Optional + nil => keep default value + buildString("} else {"); + Class<?> type = e.getType(); + if(type.isPrimitive()) { + buildString("_$$_t.%s = obj.%s();", e.getName(), primitiveConvertName(type)); + } else { + buildString("_$$_t.%s = (%s)this.templates[%d].convert(obj, _$$_t.%s);", e.getName(), e.getJavaTypeName(), i, e.getName()); + } + buildString("}"); + } + + // latter entries are all Optional + nil => keep default value + + buildString("return _$$_t;"); + + buildString("}"); + return getBuiltString(); + } + +} \ No newline at end of file diff --git a/java/src/main/java/org/msgpack/template/javassist/BuildContextBase.java b/java/src/main/java/org/msgpack/template/javassist/BuildContextBase.java new file mode 100644 index 00000000..635dc47c --- /dev/null +++ b/java/src/main/java/org/msgpack/template/javassist/BuildContextBase.java @@ -0,0 +1,244 @@ +// +// 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.template.javassist; + +import java.io.IOException; +import java.lang.reflect.Array; +import java.lang.reflect.Constructor; +import java.lang.reflect.InvocationTargetException; +import java.lang.reflect.Type; +import java.lang.Thread; + +import org.msgpack.*; +import org.msgpack.template.*; + +import javassist.CannotCompileException; +import javassist.ClassPool; +import javassist.CtClass; +import javassist.CtConstructor; +import javassist.CtMethod; +import javassist.CtNewConstructor; +import javassist.CtNewMethod; +import javassist.LoaderClassPath; +import javassist.NotFoundException; +import javassist.ClassClassPath; + +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + + +public abstract class BuildContextBase<T extends IFieldEntry> { + + private static Logger LOG = LoggerFactory.getLogger(JavassistTemplateBuilder.class); + + + protected JavassistTemplateBuilder director; + + protected String tmplName; + + protected CtClass tmplCtClass; + + protected abstract void setSuperClass() throws CannotCompileException, NotFoundException; + + protected abstract void buildConstructor() throws CannotCompileException, NotFoundException; + + protected void buildMethodInit() { } + + protected abstract String buildPackMethodBody(); + + protected abstract String buildUnpackMethodBody(); + + protected abstract String buildConvertMethodBody(); + + protected abstract Template buildInstance(Class<?> c) throws NoSuchMethodException, InstantiationException, IllegalAccessException, InvocationTargetException; + + public BuildContextBase(JavassistTemplateBuilder director) { + this.director = director; + } + + + public abstract Template buildTemplate(Class<?> targetClass, T[] entries, Template[] templates); + + + protected Template build(final String className) { + try { + reset(className); + buildClass(); + buildConstructor(); + buildMethodInit(); + buildPackMethod(); + buildUnpackMethod(); + buildConvertMethod(); + return buildInstance(createClass()); + } catch (Exception e) { + String code = getBuiltString(); + if(code != null) { + LOG.error("builder: " + code, e); + throw new TemplateBuildException("cannot compile: " + code, e); + } else { + throw new TemplateBuildException(e); + } + } + } + + protected void reset(String className) { + tmplName = className + "_$$_Template" + director.nextSeqId(); + tmplCtClass = director.makeCtClass(tmplName); + } + + protected void buildClass() throws CannotCompileException, NotFoundException { + setSuperClass(); + tmplCtClass.addInterface(director.getCtClass(Template.class.getName())); + } + + protected void buildPackMethod() throws CannotCompileException, NotFoundException { + String mbody = buildPackMethodBody(); + int mod = javassist.Modifier.PUBLIC; + CtClass returnType = CtClass.voidType; + String mname = "pack"; + CtClass[] paramTypes = new CtClass[] { + director.getCtClass(Packer.class.getName()), + director.getCtClass(Object.class.getName()) + }; + CtClass[] exceptTypes = new CtClass[] { + director.getCtClass(IOException.class.getName()) + }; + CtMethod newCtMethod = CtNewMethod.make( + mod, returnType, mname, + paramTypes, exceptTypes, mbody, tmplCtClass); + tmplCtClass.addMethod(newCtMethod); + } + + protected void buildUnpackMethod() throws CannotCompileException, NotFoundException { + String mbody = buildUnpackMethodBody(); + int mod = javassist.Modifier.PUBLIC; + CtClass returnType = director.getCtClass(Object.class.getName()); + String mname = "unpack"; + CtClass[] paramTypes = new CtClass[] { + director.getCtClass(Unpacker.class.getName()), + director.getCtClass(Object.class.getName()) + }; + CtClass[] exceptTypes = new CtClass[] { + director.getCtClass(MessageTypeException.class.getName()) + }; + CtMethod newCtMethod = CtNewMethod.make( + mod, returnType, mname, + paramTypes, exceptTypes, mbody, tmplCtClass); + tmplCtClass.addMethod(newCtMethod); + } + + protected void buildConvertMethod() throws CannotCompileException, NotFoundException { + String mbody = buildConvertMethodBody(); + int mod = javassist.Modifier.PUBLIC; + CtClass returnType = director.getCtClass(Object.class.getName()); + String mname = "convert"; + CtClass[] paramTypes = new CtClass[] { + director.getCtClass(MessagePackObject.class.getName()), + director.getCtClass(Object.class.getName()) + }; + CtClass[] exceptTypes = new CtClass[] { + director.getCtClass(MessageTypeException.class.getName()) + }; + CtMethod newCtMethod = CtNewMethod.make( + mod, returnType, mname, + paramTypes, exceptTypes, mbody, tmplCtClass); + tmplCtClass.addMethod(newCtMethod); + } + + protected Class<?> createClass() throws CannotCompileException { + return (Class<?>) tmplCtClass.toClass(null, null); + } + + protected StringBuilder stringBuilder = null; + + protected void resetStringBuilder() { + stringBuilder = new StringBuilder(); + } + + protected void buildString(String str) { + stringBuilder.append(str); + } + + protected void buildString(String format, Object... args) { + stringBuilder.append(String.format(format, args)); + } + + protected String getBuiltString() { + if(stringBuilder == null) { + return null; + } + return stringBuilder.toString(); + } + + protected String primitivePackName(Class<?> type) { + if(type == boolean.class) { + return "packBoolean"; + } else if(type == byte.class) { + return "packByte"; + } else if(type == short.class) { + return "packShort"; + } else if(type == int.class) { + return "packInt"; + } else if(type == long.class) { + return "packLong"; + } else if(type == float.class) { + return "packFloat"; + } else if(type == double.class) { + return "packDouble"; + } + return null; + } + + protected String primitiveUnpackName(Class<?> type) { + if(type == boolean.class) { + return "unpackBoolean"; + } else if(type == byte.class) { + return "unpackByte"; + } else if(type == short.class) { + return "unpackShort"; + } else if(type == int.class) { + return "unpackInt"; + } else if(type == long.class) { + return "unpackLong"; + } else if(type == float.class) { + return "unpackFloat"; + } else if(type == double.class) { + return "unpackDouble"; + } + return null; + } + + protected String primitiveConvertName(Class<?> type) { + if(type == boolean.class) { + return "asBoolean"; + } else if(type == byte.class) { + return "asByte"; + } else if(type == short.class) { + return "asShort"; + } else if(type == int.class) { + return "asInt"; + } else if(type == long.class) { + return "asLong"; + } else if(type == float.class) { + return "asFloat"; + } else if(type == double.class) { + return "asDouble"; + } + return null; + } +} \ No newline at end of file diff --git a/java/src/main/java/org/msgpack/template/javassist/BuildContextFactory.java b/java/src/main/java/org/msgpack/template/javassist/BuildContextFactory.java new file mode 100644 index 00000000..d44ed090 --- /dev/null +++ b/java/src/main/java/org/msgpack/template/javassist/BuildContextFactory.java @@ -0,0 +1,9 @@ +package org.msgpack.template.javassist; + +import org.msgpack.template.JavassistTemplateBuilder; + +public interface BuildContextFactory { + + public BuildContextBase createBuildContext(JavassistTemplateBuilder builder); + +} diff --git a/java/src/main/java/org/msgpack/template/javassist/JavassistTemplate.java b/java/src/main/java/org/msgpack/template/javassist/JavassistTemplate.java new file mode 100644 index 00000000..24e7082d --- /dev/null +++ b/java/src/main/java/org/msgpack/template/javassist/JavassistTemplate.java @@ -0,0 +1,36 @@ + +package org.msgpack.template.javassist; + +import java.io.IOException; +import java.lang.reflect.Array; +import java.lang.reflect.Constructor; +import java.lang.reflect.InvocationTargetException; +import java.lang.reflect.Type; +import java.lang.Thread; + +import org.msgpack.*; +import org.msgpack.template.*; + +import javassist.CannotCompileException; +import javassist.ClassPool; +import javassist.CtClass; +import javassist.CtConstructor; +import javassist.CtMethod; +import javassist.CtNewConstructor; +import javassist.CtNewMethod; +import javassist.LoaderClassPath; +import javassist.NotFoundException; +import javassist.ClassClassPath; + +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +public abstract class JavassistTemplate extends AbstractTemplate { + public Class<?> targetClass; + public Template[] templates; + + public JavassistTemplate(Class<?> targetClass, Template[] templates) { + this.targetClass = targetClass; + this.templates = templates; + } +} \ No newline at end of file diff --git a/java/src/test/java/org/msgpack/TestArrays.java b/java/src/test/java/org/msgpack/TestArrays.java index 92bb44c2..40fa5d69 100644 --- a/java/src/test/java/org/msgpack/TestArrays.java +++ b/java/src/test/java/org/msgpack/TestArrays.java @@ -13,6 +13,10 @@ import org.junit.Test; import junit.framework.TestCase; public class TestArrays extends TestCase { + + + + @MessagePackMessage public static class PrimitiveTest { public PrimitiveTest() { } diff --git a/java/src/test/java/org/msgpack/template/BeansEntryReaderTest.java b/java/src/test/java/org/msgpack/template/BeansEntryReaderTest.java new file mode 100644 index 00000000..78880582 --- /dev/null +++ b/java/src/test/java/org/msgpack/template/BeansEntryReaderTest.java @@ -0,0 +1,133 @@ +package org.msgpack.template; + +import java.beans.BeanDescriptor; +import java.beans.BeanInfo; +import java.beans.IntrospectionException; +import java.beans.Introspector; +import java.beans.PropertyDescriptor; + +import org.junit.Assert; +import org.junit.Before; +import org.junit.Test; +import org.msgpack.template.BeansFieldEntryReader; + +import static org.junit.Assert.assertThat; +import static org.hamcrest.CoreMatchers.*; + +/** + * + * @author takeshita + * + */ +public class BeansEntryReaderTest { + + public static class VariableProps{ + + public int getCollect(){ + return 0; + } + public void setCollect(int v){} + + public int getOnlyGetter(){ + return 0; + } + + public void setOnlySetter(int v){} + + public boolean isBoolean(){ + return true; + } + public void setBoolean(boolean b){} + + + private int getPrivateBoth(){return 1;} + private void setPrivateBoth(int v){} + + private int getPrivateGetter(){return 1;} + public void setPrivateGetter(int v){} + + public int getPrivateSetter(){return 1;} + private void setPrivateSetter(int v){} + + protected int getProtected(){return 1;} + protected void setProtected(int v){} + + int getInternal(){return 1;} + void setInternal(int v){} + + public int getWrongGetter(int v){return 1;} + public void setWrongGetter(int v){} + + public void getWrongGetter2(){} + public void setWrongGetter2(int v){} + + public int isWrongGetter3(){return 1;} + public void setWrongGetter3(int v){} + + public int getWrongSetter(){return 1;} + public int setWrongSetter(int v){return 1;} + + public int getWrongSetter2(){return 1;} + public void setWrongSetter2(){} + } + + @Before + public void before(){ + reader = new BeansFieldEntryReader(); + + try { + info = Introspector.getBeanInfo(VariableProps.class); + } catch (IntrospectionException e) { + e.printStackTrace(); + Assert.fail(); + } + } + BeansFieldEntryReader reader; + BeanInfo info; + @Test + public void testIgnorePropertyDesc(){ + BeanDescriptor desc = info.getBeanDescriptor(); + + assertThat(reader.isIgnoreProp(getProp(info,"collect")),is(false)); + assertThat(reader.isIgnoreProp(getProp(info,"boolean")),is(false)); + + + assertThat(reader.isIgnoreProp(getProp(info,"onlyGetter")),is(true)); + assertThat(reader.isIgnoreProp(getProp(info,"onlySetter")),is(true)); + assertThat(reader.isIgnoreProp(getProp(info,"privateBoth")),is(true)); + assertThat(reader.isIgnoreProp(getProp(info,"privateGetter")),is(true)); + assertThat(reader.isIgnoreProp(getProp(info,"privateSetter")),is(true)); + assertThat(reader.isIgnoreProp(getProp(info,"protected")),is(true)); + assertThat(reader.isIgnoreProp(getProp(info,"internal")),is(true)); + assertThat(reader.isIgnoreProp(getProp(info,"wrongGetter")),is(true)); + assertThat(reader.isIgnoreProp(getProp(info,"wrongGetter2")),is(true)); + assertThat(reader.isIgnoreProp(getProp(info,"wrongGetter3")),is(true)); + assertThat(reader.isIgnoreProp(getProp(info,"wrongSetter")),is(true)); + assertThat(reader.isIgnoreProp(getProp(info,"wrongSetter2")),is(true)); + + } + @Test + public void testReadEntries(){ + + IFieldEntry[] entries = reader.readFieldEntries(VariableProps.class, FieldOption.DEFAULT); + + assertThat(entries.length, is(2)); + + + } + + + public PropertyDescriptor getProp(BeanInfo info , String name){ + PropertyDescriptor[] props = info.getPropertyDescriptors(); + for(int i = 0;i < props.length;i++){ + PropertyDescriptor d = props[i]; + if(d.getDisplayName().equalsIgnoreCase(name)){ + return d; + } + } + return null; + } + + + +} diff --git a/java/src/test/java/org/msgpack/template/BeansEquals.java b/java/src/test/java/org/msgpack/template/BeansEquals.java new file mode 100644 index 00000000..e07a224d --- /dev/null +++ b/java/src/test/java/org/msgpack/template/BeansEquals.java @@ -0,0 +1,83 @@ +package org.msgpack.template; + +import java.lang.reflect.InvocationTargetException; +import java.lang.reflect.Method; +import java.util.HashSet; + +import org.hamcrest.BaseMatcher; +import org.hamcrest.CoreMatchers; +import org.hamcrest.Description; +import org.junit.Assert; + +/** + * This matcher compares all get***() methods(except getClass) + * @author takeshita + * + */ +public class BeansEquals extends BaseMatcher<Object>{ + + Object expected; + + HashSet<String> ignoreNames = new HashSet<String>(); + + public BeansEquals(Object expected){ + this.expected = expected; + } + public BeansEquals(Object expected,String[] ignoreNames){ + this.expected = expected; + for(int i = 0;i < ignoreNames.length;i++){ + this.ignoreNames.add(ignoreNames[i]); + } + } + + static String errorMessage = "hoge"; + + @Override + public boolean matches(Object actual) { + if(expected == actual){ + return true; + } + if(!actual.getClass().equals(expected.getClass())){ + errorMessage = String.format("Expected class is %s but actual %s", + expected.getClass().getName(), + actual.getClass().getName()); + return false; + } + + for(Method m : expected.getClass().getMethods()){ + String n = m.getName(); + if(n.startsWith("get") && + !n.equals("getClass") && + !ignoreNames.contains(n)){ + + if(m.getParameterTypes().length == 0 && + !m.getReturnType().equals(void.class)){ + try { + Object exp = m.invoke(expected); + Object act = m.invoke(actual); + + Assert.assertThat("@" + n,act, CoreMatchers.is(exp)); + + } catch (Exception e) { + throw new RuntimeException(String.format( + "Exception occured while comparing %s",n), e); + } + + } + + } + + } + + return true; + } + + + @Override + public void describeTo(Description desc) { + + desc.appendText(errorMessage); + } + + +} diff --git a/java/src/test/java/org/msgpack/template/TestReflectionTemplateBuilderJavaBeansPackUnpack.java b/java/src/test/java/org/msgpack/template/TestReflectionTemplateBuilderJavaBeansPackUnpack.java new file mode 100644 index 00000000..951b401c --- /dev/null +++ b/java/src/test/java/org/msgpack/template/TestReflectionTemplateBuilderJavaBeansPackUnpack.java @@ -0,0 +1,2207 @@ +package org.msgpack.template; + +import java.io.ByteArrayInputStream; +import java.io.ByteArrayOutputStream; +import java.io.IOException; +import java.math.BigInteger; +import java.nio.ByteBuffer; +import java.util.ArrayList; +import java.util.HashMap; +import java.util.Iterator; +import java.util.LinkedList; +import java.util.List; +import java.util.Map; + +import org.hamcrest.CoreMatchers; +import org.hamcrest.Matcher; +import org.junit.Ignore; +import org.junit.Test; + +import org.msgpack.MessagePack; +import org.msgpack.MessagePackable; +import org.msgpack.MessagePacker; +import org.msgpack.MessageTypeException; +import org.msgpack.MessageUnpackable; +import org.msgpack.Packer; +import org.msgpack.Template; +import org.msgpack.Unpacker; +import org.msgpack.annotation.MessagePackBeans; +import org.msgpack.annotation.MessagePackMessage; +import org.msgpack.annotation.MessagePackOrdinalEnum; +import org.msgpack.annotation.Optional; +import org.msgpack.template.TestTemplateBuilderPackConvert.SampleInterface; +import org.msgpack.template.builder.BuilderSelectorRegistry; +import org.msgpack.template.builder.MessagePackBeansBuilderSelector; +import org.msgpack.template.builder.MessagePackMessageBuilderSelector; +import org.msgpack.template.builder.TemplateBuilder; + +import org.junit.Assert; +import junit.framework.TestCase; +import static org.hamcrest.CoreMatchers.*; +import static org.junit.Assert.assertThat; + +public class TestReflectionTemplateBuilderJavaBeansPackUnpack extends TestCase { + static { + //Replace template selectors from javassist to reflection. + BuilderSelectorRegistry instance = BuilderSelectorRegistry.getInstance(); + + instance.replace( + new MessagePackMessageBuilderSelector( + new ReflectionTemplateBuilder())); + instance.setForceBuilder( new ReflectionTemplateBuilder()); + instance.replace(new MessagePackBeansBuilderSelector( + new BeansReflectionTemplateBuilder())); + + MessagePack.register(PrimitiveTypeFieldsClass.class); + MessagePack.register(OptionalPrimitiveTypeFieldsClass.class); + MessagePack.register(GeneralReferenceTypeFieldsClass.class); + MessagePack.register(GeneralOptionalReferenceTypeFieldsClass.class); + MessagePack.register(SampleListTypes.class); + MessagePack.register(SampleOptionalListTypes.class); + MessagePack.register(SampleMapTypes.class); + MessagePack.register(SampleOptionalMapTypes.class); + MessagePack.register(SampleEnumFieldClass.class); + MessagePack.register(SampleOptionalEnumFieldClass.class); + MessagePack.register(FieldModifiersClass.class); + MessagePack.register(OptionalFieldModifiersClass.class); + MessagePack.register(BaseClass.class); + MessagePack.register(NestedClass.class); + MessagePack.register(BaseClass2.class); + MessagePack.register(OptionalBaseClass.class); + MessagePack.register(OptionalNestedClass.class); + MessagePack.register(OptionalBaseClass2.class); + MessagePack.register(SampleSubClass.class); + MessagePack.register(SampleSuperClass.class); + MessagePack.register(SampleOptionalSubClass.class); + MessagePack.register(SampleOptionalSuperClass.class); + MessagePack.register(BaseMessagePackableUnpackableClass.class); + MessagePack.register(MessagePackableUnpackableClass.class); + MessagePack.register(OptionalBaseMessagePackableUnpackableClass.class); + MessagePack.register(OptionalMessagePackableUnpackableClass.class); + } + + Matcher<Object> beansEquals(Object actual){ + return new BeansEquals(actual); + } + Matcher<Object> beansEquals(Object actual,String[] ignoreNames){ + return new BeansEquals(actual,ignoreNames); + } + String[] ignoring(String ... strings){ + return strings; + } + + @Test + public void testPrimitiveTypeFields00() throws Exception { + PrimitiveTypeFieldsClass src = new PrimitiveTypeFieldsClass(); + src.f0 = (byte) 0; + src.f1 = 1; + src.f2 = 2; + src.f3 = 3; + src.f4 = 4; + src.f5 = 5; + src.f6 = false; + + byte[] raw = MessagePack.pack(src); + + PrimitiveTypeFieldsClass dst = + MessagePack.unpack(raw, PrimitiveTypeFieldsClass.class); + + + assertThat(dst,beansEquals(src)); + } + + @Test + public void testPrimitiveTypeFields01() throws Exception { + PrimitiveTypeFieldsClass src = new PrimitiveTypeFieldsClass(); + + byte[] raw = MessagePack.pack(src); + + PrimitiveTypeFieldsClass dst = + MessagePack.unpack(raw, PrimitiveTypeFieldsClass.class); + + assertThat(dst,beansEquals(src)); + } + + @Test + public void testPrimitiveTypeFields02() throws Exception { + PrimitiveTypeFieldsClass src = null; + + byte[] raw = MessagePack.pack(src); + + PrimitiveTypeFieldsClass dst = + MessagePack.unpack(raw, PrimitiveTypeFieldsClass.class); + + assertThat(dst,beansEquals(src)); + } + + @MessagePackBeans + public static class PrimitiveTypeFieldsClass { + byte f0; + short f1; + int f2; + long f3; + float f4; + double f5; + boolean f6; + + public byte getF0() { + return f0; + } + + public void setF0(byte f0) { + this.f0 = f0; + } + + public short getF1() { + return f1; + } + + public void setF1(short f1) { + this.f1 = f1; + } + + public int getF2() { + return f2; + } + + public void setF2(int f2) { + this.f2 = f2; + } + + public long getF3() { + return f3; + } + + public void setF3(long f3) { + this.f3 = f3; + } + + public float getF4() { + return f4; + } + + public void setF4(float f4) { + this.f4 = f4; + } + + public double getF5() { + return f5; + } + + public void setF5(double f5) { + this.f5 = f5; + } + + public boolean isF6() { + return f6; + } + + public void setF6(boolean f6) { + this.f6 = f6; + } + + public PrimitiveTypeFieldsClass() { + } + } + + @Test + public void testOptionalPrimitiveTypeFields00() throws Exception { + OptionalPrimitiveTypeFieldsClass src = new OptionalPrimitiveTypeFieldsClass(); + src.f0 = (byte) 0; + src.f1 = 1; + src.f2 = 2; + src.f3 = 3; + src.f4 = 4; + src.f5 = 5; + src.f6 = false; + + byte[] raw = MessagePack.pack(src); + + PrimitiveTypeFieldsClass dst = + MessagePack.unpack(raw, PrimitiveTypeFieldsClass.class); + + + assertEquals(src.f0, dst.f0); + assertEquals(src.f1, dst.f1); + assertEquals(src.f2, dst.f2); + assertEquals(src.f3, dst.f3); + assertEquals(src.f4, dst.f4); + assertEquals(src.f5, dst.f5); + assertEquals(src.f6, dst.f6); + } + + @Test + public void testOptionalPrimitiveTypeFields01() throws Exception { + OptionalPrimitiveTypeFieldsClass src = new OptionalPrimitiveTypeFieldsClass(); + + byte[] raw = MessagePack.pack(src); + + OptionalPrimitiveTypeFieldsClass dst = + MessagePack.unpack(raw, OptionalPrimitiveTypeFieldsClass.class); + + + assertThat(dst,beansEquals(src)); + } + + @Test + public void testOptionalPrimitiveTypeFields02() throws Exception { + OptionalPrimitiveTypeFieldsClass src = null; + + byte[] raw = MessagePack.pack(src); + + OptionalPrimitiveTypeFieldsClass dst = + MessagePack.unpack(raw, OptionalPrimitiveTypeFieldsClass.class); + assertEquals(src, dst); + } + + @MessagePackBeans + public static class OptionalPrimitiveTypeFieldsClass { + @Optional + public byte f0; + @Optional + public short f1; + @Optional + public int f2; + @Optional + public long f3; + @Optional + public float f4; + @Optional + public double f5; + @Optional + public boolean f6; + + @Optional + public byte getF0() { + return f0; + } + + @Optional + public void setF0(byte f0) { + this.f0 = f0; + } + + @Optional + public short getF1() { + return f1; + } + + public void setF1(short f1) { + this.f1 = f1; + } + + public int getF2() { + return f2; + } + + @Optional + public void setF2(int f2) { + this.f2 = f2; + } + + @Optional + public long getF3() { + return f3; + } + + public void setF3(long f3) { + this.f3 = f3; + } + + @Optional + public float getF4() { + return f4; + } + + public void setF4(float f4) { + this.f4 = f4; + } + + @Optional + public double getF5() { + return f5; + } + + public void setF5(double f5) { + this.f5 = f5; + } + + @Optional + public boolean isF6() { + return f6; + } + + public void setF6(boolean f6) { + this.f6 = f6; + } + + public OptionalPrimitiveTypeFieldsClass() { + } + } + + @Test + public void testGeneralReferenceTypeFieldsClass00() throws Exception { + GeneralReferenceTypeFieldsClass src = new GeneralReferenceTypeFieldsClass(); + src.f0 = 0; + src.f1 = 1; + src.f2 = 2; + src.f3 = (long) 3; + src.f4 = (float) 4; + src.f5 = (double) 5; + src.f6 = false; + src.f7 = new BigInteger("7"); + src.f8 = "8"; + src.f9 = new byte[] { 0x01, 0x02 }; + src.f10 = ByteBuffer.wrap("muga".getBytes()); + + byte[] raw = MessagePack.pack(src); + + GeneralReferenceTypeFieldsClass dst = + MessagePack.unpack(raw, GeneralReferenceTypeFieldsClass.class); + + + assertThat(dst,beansEquals(src)); + + } + + @Test + public void testGeneralReferenceTypeFieldsClass01() throws Exception { + GeneralReferenceTypeFieldsClass src = null; + + byte[] raw = MessagePack.pack(src); + + GeneralReferenceTypeFieldsClass dst = + MessagePack.unpack(raw, GeneralReferenceTypeFieldsClass.class); + assertEquals(src, dst); + } + + @MessagePackBeans + public static class GeneralReferenceTypeFieldsClass { + public Byte f0; + public Short f1; + public Integer f2; + public Long f3; + public Float f4; + public Double f5; + public Boolean f6; + public BigInteger f7; + public String f8; + public byte[] f9; + public ByteBuffer f10; + + public Byte getF0() { + return f0; + } + + public void setF0(Byte f0) { + this.f0 = f0; + } + + public Short getF1() { + return f1; + } + + public void setF1(Short f1) { + this.f1 = f1; + } + + public Integer getF2() { + return f2; + } + + public void setF2(Integer f2) { + this.f2 = f2; + } + + public Long getF3() { + return f3; + } + + public void setF3(Long f3) { + this.f3 = f3; + } + + public Float getF4() { + return f4; + } + + public void setF4(Float f4) { + this.f4 = f4; + } + + public Double getF5() { + return f5; + } + + public void setF5(Double f5) { + this.f5 = f5; + } + + public Boolean getF6() { + return f6; + } + + public void setF6(Boolean f6) { + this.f6 = f6; + } + + public BigInteger getF7() { + return f7; + } + + public void setF7(BigInteger f7) { + this.f7 = f7; + } + + public String getF8() { + return f8; + } + + public void setF8(String f8) { + this.f8 = f8; + } + + public byte[] getF9() { + return f9; + } + + public void setF9(byte[] f9) { + this.f9 = f9; + } + + public ByteBuffer getF10() { + return f10; + } + + public void setF10(ByteBuffer f10) { + this.f10 = f10; + } + + public GeneralReferenceTypeFieldsClass() { + } + } + + @Test + public void testGeneralOptionalReferenceTypeFieldsClass00() + throws Exception { + GeneralOptionalReferenceTypeFieldsClass src = new GeneralOptionalReferenceTypeFieldsClass(); + src.f0 = 0; + src.f1 = 1; + src.f2 = 2; + src.f3 = (long) 3; + src.f4 = (float) 4; + src.f5 = (double) 5; + src.f6 = false; + src.f7 = new BigInteger("7"); + src.f8 = "8"; + src.f9 = new byte[] { 0x01, 0x02 }; + src.f10 = ByteBuffer.wrap("muga".getBytes()); + + byte[] raw = MessagePack.pack(src); + + GeneralOptionalReferenceTypeFieldsClass dst = + MessagePack.unpack(raw, GeneralOptionalReferenceTypeFieldsClass.class); + + + assertThat(dst,beansEquals(src)); + } + + @Test + public void testGeneralOptionalReferenceTypeFieldsClass01() + throws Exception { + GeneralOptionalReferenceTypeFieldsClass src = new GeneralOptionalReferenceTypeFieldsClass(); + src.f0 = null; + src.f1 = null; + src.f2 = null; + src.f3 = null; + src.f4 = null; + src.f5 = null; + src.f6 = null; + src.f7 = null; + src.f8 = null; + src.f9 = null; + src.f10 = null; + + byte[] raw = MessagePack.pack(src); + + GeneralOptionalReferenceTypeFieldsClass dst = + MessagePack.unpack(raw, GeneralOptionalReferenceTypeFieldsClass.class); + + + assertThat(dst,beansEquals(src)); + } + + @Test + public void testGeneralOptionalReferenceTypeFieldsClass02() + throws Exception { + GeneralOptionalReferenceTypeFieldsClass src = null; + + byte[] raw = MessagePack.pack(src); + + GeneralOptionalReferenceTypeFieldsClass dst = + MessagePack.unpack(raw, GeneralOptionalReferenceTypeFieldsClass.class); + assertEquals(src, dst); + } + + @MessagePackBeans + public static class GeneralOptionalReferenceTypeFieldsClass { + @Optional + public Byte f0; + @Optional + public Short f1; + @Optional + public Integer f2; + @Optional + public Long f3; + @Optional + public Float f4; + @Optional + public Double f5; + @Optional + public Boolean f6; + @Optional + public BigInteger f7; + @Optional + public String f8; + @Optional + public byte[] f9; + @Optional + public ByteBuffer f10; + + @Optional + public Byte getF0() { + return f0; + } + + @Optional + public void setF0(Byte f0) { + this.f0 = f0; + } + + @Optional + public Short getF1() { + return f1; + } + + public void setF1(Short f1) { + this.f1 = f1; + } + + public Integer getF2() { + return f2; + } + + @Optional + public void setF2(Integer f2) { + this.f2 = f2; + } + + @Optional + public Long getF3() { + return f3; + } + + public void setF3(Long f3) { + this.f3 = f3; + } + + @Optional + public Float getF4() { + return f4; + } + + public void setF4(Float f4) { + this.f4 = f4; + } + + @Optional + public Double getF5() { + return f5; + } + + public void setF5(Double f5) { + this.f5 = f5; + } + + @Optional + public Boolean getF6() { + return f6; + } + + public void setF6(Boolean f6) { + this.f6 = f6; + } + + @Optional + public BigInteger getF7() { + return f7; + } + + public void setF7(BigInteger f7) { + this.f7 = f7; + } + + @Optional + public String getF8() { + return f8; + } + + public void setF8(String f8) { + this.f8 = f8; + } + + @Optional + public byte[] getF9() { + return f9; + } + + public void setF9(byte[] f9) { + this.f9 = f9; + } + + @Optional + public ByteBuffer getF10() { + return f10; + } + + public void setF10(ByteBuffer f10) { + this.f10 = f10; + } + + public GeneralOptionalReferenceTypeFieldsClass() { + } + } + + @Test + public void testListTypes00() throws Exception { + SampleListTypes src = new SampleListTypes(); + src.integerListSize0 = new ArrayList<Integer>(); + src.integerList = new ArrayList<Integer>(); + src.integerList.add(1); + src.integerList.add(2); + src.integerList.add(3); + src.stringList = new ArrayList<String>(); + src.stringList.add("e1"); + src.stringList.add("e2"); + src.stringList.add("e3"); + src.stringListList = new ArrayList<List<String>>(); + src.stringListList.add(src.stringList); + src.sampleListNestedTypeList = new ArrayList<SampleListNestedType>(); + SampleListNestedType slnt = new SampleListNestedType(); + slnt.f0 = new byte[] { 0x01, 0x02 }; + slnt.f1 = "muga"; + src.sampleListNestedTypeList.add(slnt); + src.byteBufferList = new ArrayList<ByteBuffer>(); + src.byteBufferList.add(ByteBuffer.wrap("e1".getBytes())); + src.byteBufferList.add(ByteBuffer.wrap("e2".getBytes())); + src.byteBufferList.add(ByteBuffer.wrap("e3".getBytes())); + + byte[] raw = MessagePack.pack(src); + + SampleListTypes dst = + MessagePack.unpack(raw, SampleListTypes.class); + + //ignore sampleListNestedTypeList, + //because SampleListNestedType is not implemented equals() correctly. + assertThat(dst,beansEquals(src, ignoring("getF4"))); + + assertEquals(src.sampleListNestedTypeList.size(), dst.sampleListNestedTypeList.size()); + for (int i = 0; i < src.sampleListNestedTypeList.size(); ++i) { + SampleListNestedType s = src.sampleListNestedTypeList.get(i); + SampleListNestedType d = dst.sampleListNestedTypeList.get(i); + assertEquals(s.f0[0], d.f0[0]); + assertEquals(s.f0[1], d.f0[1]); + assertEquals(s.f1, d.f1); + } + } + + @Test + public void testListTypes01() throws Exception { + SampleListTypes src = null; + + byte[] raw = MessagePack.pack(src); + + SampleListTypes dst = + MessagePack.unpack(raw, SampleListTypes.class); + assertEquals(src, dst); + } + + @MessagePackBeans + public static class SampleListTypes { + public List<Integer> integerListSize0; + public List<Integer> integerList; + public List<String> stringList; + public List<List<String>> stringListList; + public List<SampleListNestedType> sampleListNestedTypeList; + public List<ByteBuffer> byteBufferList; + + public List<Integer> getF0() { + return integerListSize0; + } + + public void setF0(List<Integer> f0) { + this.integerListSize0 = f0; + } + + public List<Integer> getF1() { + return integerList; + } + + public void setF1(List<Integer> f1) { + this.integerList = f1; + } + + public List<String> getF2() { + return stringList; + } + + public void setF2(List<String> f2) { + this.stringList = f2; + } + + public List<List<String>> getF3() { + return stringListList; + } + + public void setF3(List<List<String>> f3) { + this.stringListList = f3; + } + + public List<SampleListNestedType> getF4() { + return sampleListNestedTypeList; + } + + public void setF4(List<SampleListNestedType> f4) { + this.sampleListNestedTypeList = f4; + } + + public List<ByteBuffer> getF5() { + return byteBufferList; + } + + public void setF5(List<ByteBuffer> f5) { + this.byteBufferList = f5; + } + + public SampleListTypes() { + } + } + + @MessagePackMessage + public static class SampleListNestedType { + public byte[] f0; + public String f1; + + public SampleListNestedType() { + } + } + + @Test + public void testOptionalListTypes00() throws Exception { + SampleOptionalListTypes src = new SampleOptionalListTypes(); + src.f0 = new ArrayList<Integer>(); + src.f1 = new ArrayList<Integer>(); + src.f1.add(1); + src.f1.add(2); + src.f1.add(3); + src.f2 = new ArrayList<String>(); + src.f2.add("e1"); + src.f2.add("e2"); + src.f2.add("e3"); + src.f3 = new ArrayList<List<String>>(); + src.f3.add(src.f2); + src.f4 = new ArrayList<SampleOptionalListNestedType>(); + SampleOptionalListNestedType slnt = new SampleOptionalListNestedType(); + slnt.f0 = new byte[] { 0x01, 0x02 }; + slnt.f1 = "muga"; + src.f4.add(slnt); + src.f5 = new ArrayList<ByteBuffer>(); + src.f5.add(ByteBuffer.wrap("e1".getBytes())); + src.f5.add(ByteBuffer.wrap("e2".getBytes())); + src.f5.add(ByteBuffer.wrap("e3".getBytes())); + + byte[] raw = MessagePack.pack(src); + + SampleOptionalListTypes dst = + MessagePack.unpack(raw, SampleOptionalListTypes.class); + assertEquals(src.f0.size(), dst.f0.size()); + assertEquals(src.f1.size(), dst.f1.size()); + for (int i = 0; i < src.f1.size(); ++i) { + assertEquals(src.f1.get(i), dst.f1.get(i)); + } + assertEquals(src.f2.size(), dst.f2.size()); + for (int i = 0; i < src.f2.size(); ++i) { + assertEquals(src.f2.get(i), dst.f2.get(i)); + } + assertEquals(src.f3.size(), dst.f3.size()); + for (int i = 0; i < src.f3.size(); ++i) { + List<String> srclist = src.f3.get(i); + List<String> dstlist = dst.f3.get(i); + assertEquals(srclist.size(), dstlist.size()); + for (int j = 0; j < srclist.size(); ++j) { + assertEquals(srclist.get(j), dstlist.get(j)); + } + } + assertEquals(src.f4.size(), dst.f4.size()); + for (int i = 0; i < src.f4.size(); ++i) { + SampleOptionalListNestedType s = src.f4.get(i); + SampleOptionalListNestedType d = dst.f4.get(i); + assertEquals(s.f0[0], d.f0[0]); + assertEquals(s.f0[1], d.f0[1]); + assertEquals(s.f1, d.f1); + } + assertEquals(src.f5.size(), dst.f5.size()); + for (int i = 0; i < src.f5.size(); ++i) { + ByteBuffer s = src.f5.get(i); + ByteBuffer d = dst.f5.get(i); + assertEquals(s, d); + } + } + + @Test + public void testOptionalListTypes01() throws Exception { + SampleOptionalListTypes src = new SampleOptionalListTypes(); + src.f0 = new ArrayList<Integer>(); + src.f1 = null; + src.f2 = new ArrayList<String>(); + src.f3 = new ArrayList<List<String>>(); + src.f4 = null; + src.f5 = new ArrayList<ByteBuffer>(); + + byte[] raw = MessagePack.pack(src); + + SampleOptionalListTypes dst = + MessagePack.unpack(raw, SampleOptionalListTypes.class); + assertEquals(src.f0.size(), dst.f0.size()); + assertEquals(src.f1, dst.f1); + assertEquals(src.f2.size(), dst.f2.size()); + assertEquals(src.f3.size(), dst.f3.size()); + assertEquals(src.f4, dst.f4); + assertEquals(src.f5.size(), dst.f5.size()); + } + + @Test + public void testOptionalListTypes02() throws Exception { + SampleListTypes src = null; + + byte[] raw = MessagePack.pack(src); + + SampleListTypes dst = + MessagePack.unpack(raw, SampleListTypes.class); + assertEquals(src, dst); + } + + @MessagePackBeans + public static class SampleOptionalListTypes { + @Optional + public List<Integer> f0; + @Optional + public List<Integer> f1; + @Optional + public List<String> f2; + @Optional + public List<List<String>> f3; + @Optional + public List<SampleOptionalListNestedType> f4; + @Optional + public List<ByteBuffer> f5; + + @Optional + public List<Integer> getF0() { + return f0; + } + + @Optional + public void setF0(List<Integer> f0) { + this.f0 = f0; + } + + @Optional + public List<Integer> getF1() { + return f1; + } + + public void setF1(List<Integer> f1) { + this.f1 = f1; + } + + public List<String> getF2() { + return f2; + } + + @Optional + public void setF2(List<String> f2) { + this.f2 = f2; + } + + @Optional + public List<List<String>> getF3() { + return f3; + } + + public void setF3(List<List<String>> f3) { + this.f3 = f3; + } + + @Optional + public List<SampleOptionalListNestedType> getF4() { + return f4; + } + + public void setF4(List<SampleOptionalListNestedType> f4) { + this.f4 = f4; + } + + @Optional + public List<ByteBuffer> getF5() { + return f5; + } + + public void setF5(List<ByteBuffer> f5) { + this.f5 = f5; + } + + public SampleOptionalListTypes() { + } + } + + @MessagePackBeans + public static class SampleOptionalListNestedType { + @Optional + public byte[] f0; + @Optional + public String f1; + + @Optional + public byte[] getF0() { + return f0; + } + + public void setF0(byte[] f0) { + this.f0 = f0; + } + + @Optional + public String getF1() { + return f1; + } + + public void setF1(String f1) { + this.f1 = f1; + } + + public SampleOptionalListNestedType() { + } + } + + @Test + public void testMapTypes00() throws Exception { + SampleMapTypes src = new SampleMapTypes(); + src.f0 = new HashMap<Integer, Integer>(); + src.f1 = new HashMap<Integer, Integer>(); + src.f1.put(1, 1); + src.f1.put(2, 2); + src.f1.put(3, 3); + src.f2 = new HashMap<String, Integer>(); + src.f2.put("k1", 1); + src.f2.put("k2", 2); + src.f2.put("k3", 3); + + byte[] raw = MessagePack.pack(src); + + SampleMapTypes dst = + MessagePack.unpack(raw, SampleMapTypes.class); + Iterator<Integer> srcf1 = src.f1.keySet().iterator(); + Iterator<Integer> dstf1 = dst.f1.keySet().iterator(); + while (srcf1.hasNext()) { + Integer s1 = srcf1.next(); + Integer d1 = dstf1.next(); + assertEquals(s1, d1); + assertEquals(src.f1.get(s1), dst.f1.get(d1)); + } + assertEquals(src.f2.size(), dst.f2.size()); + Iterator<String> srcf2 = src.f2.keySet().iterator(); + Iterator<String> dstf2 = dst.f2.keySet().iterator(); + while (srcf2.hasNext()) { + String s2 = srcf2.next(); + String d2 = dstf2.next(); + assertEquals(s2, d2); + assertEquals(src.f2.get(s2), dst.f2.get(d2)); + } + } + + @Test + public void testMapTypes01() throws Exception { + SampleMapTypes src = null; + + byte[] raw = MessagePack.pack(src); + + SampleMapTypes dst = + MessagePack.unpack(raw, SampleMapTypes.class); + assertEquals(src, dst); + } + + @MessagePackBeans + public static class SampleMapTypes { + public Map<Integer, Integer> f0; + public Map<Integer, Integer> f1; + public Map<String, Integer> f2; + + public Map<Integer, Integer> getF0() { + return f0; + } + + public void setF0(Map<Integer, Integer> f0) { + this.f0 = f0; + } + + public Map<Integer, Integer> getF1() { + return f1; + } + + public void setF1(Map<Integer, Integer> f1) { + this.f1 = f1; + } + + public Map<String, Integer> getF2() { + return f2; + } + + public void setF2(Map<String, Integer> f2) { + this.f2 = f2; + } + + public SampleMapTypes() { + } + } + + @Test + public void testOptionalMapTypes00() throws Exception { + SampleOptionalMapTypes src = new SampleOptionalMapTypes(); + src.f0 = new HashMap<Integer, Integer>(); + src.f1 = new HashMap<Integer, Integer>(); + src.f1.put(1, 1); + src.f1.put(2, 2); + src.f1.put(3, 3); + src.f2 = new HashMap<String, Integer>(); + src.f2.put("k1", 1); + src.f2.put("k2", 2); + src.f2.put("k3", 3); + + byte[] raw = MessagePack.pack(src); + + SampleOptionalMapTypes dst = + MessagePack.unpack(raw, SampleOptionalMapTypes.class); + assertEquals(src.f0.size(), dst.f0.size()); + assertEquals(src.f1.size(), dst.f1.size()); + Iterator<Integer> srcf1 = src.f1.keySet().iterator(); + Iterator<Integer> dstf1 = dst.f1.keySet().iterator(); + while (srcf1.hasNext()) { + Integer s1 = srcf1.next(); + Integer d1 = dstf1.next(); + assertEquals(s1, d1); + assertEquals(src.f1.get(s1), dst.f1.get(d1)); + } + assertEquals(src.f2.size(), dst.f2.size()); + Iterator<String> srcf2 = src.f2.keySet().iterator(); + Iterator<String> dstf2 = dst.f2.keySet().iterator(); + while (srcf2.hasNext()) { + String s2 = srcf2.next(); + String d2 = dstf2.next(); + assertEquals(s2, d2); + assertEquals(src.f2.get(s2), dst.f2.get(d2)); + } + } + + @Test + public void testOptionalMapTypes01() throws Exception { + SampleOptionalMapTypes src = new SampleOptionalMapTypes(); + src.f0 = new HashMap<Integer, Integer>(); + src.f1 = null; + src.f2 = new HashMap<String, Integer>(); + + byte[] raw = MessagePack.pack(src); + + SampleOptionalMapTypes dst = + MessagePack.unpack(raw, SampleOptionalMapTypes.class); + assertEquals(src.f0.size(), dst.f0.size()); + assertEquals(src.f1, dst.f1); + assertEquals(src.f2.size(), dst.f2.size()); + } + + @Test + public void testOptionalMapTypes02() throws Exception { + SampleOptionalMapTypes src = null; + + byte[] raw = MessagePack.pack(src); + + SampleOptionalMapTypes dst = + MessagePack.unpack(raw, SampleOptionalMapTypes.class); + assertEquals(src, dst); + } + + @MessagePackBeans + public static class SampleOptionalMapTypes { + @Optional + public Map<Integer, Integer> f0; + @Optional + public Map<Integer, Integer> f1; + @Optional + public Map<String, Integer> f2; + + @Optional + public Map<Integer, Integer> getF0() { + return f0; + } + + public void setF0(Map<Integer, Integer> f0) { + this.f0 = f0; + } + + @Optional + public Map<Integer, Integer> getF1() { + return f1; + } + + public void setF1(Map<Integer, Integer> f1) { + this.f1 = f1; + } + + @Optional + public Map<String, Integer> getF2() { + return f2; + } + + public void setF2(Map<String, Integer> f2) { + this.f2 = f2; + } + + public SampleOptionalMapTypes() { + } + } + + + @MessagePackBeans + public abstract static class AbstractModifierClass { + } + + @Test + public void testInterfaceType00() throws Exception { + try { + TemplateBuilder builder = BuilderSelectorRegistry.getInstance().select(SampleInterface.class); + Assert.assertNull(builder); + BuilderSelectorRegistry.getInstance().getForceBuilder().buildTemplate(SampleInterface.class); + fail(); + } catch (TemplateBuildException e) { + assertTrue(true); + } + assertTrue(true); + } + + @Test + public void testInterfaceType01() throws Exception { + try { + TemplateBuilder builder = BuilderSelectorRegistry.getInstance().select(SampleInterface.class); + Assert.assertNull(builder); + BuilderSelectorRegistry.getInstance().getForceBuilder().buildTemplate(SampleInterface.class); + fail(); + } catch (TemplateBuildException e) { + assertTrue(true); + } + assertTrue(true); + } + + public interface SampleInterface { + } + + @Test + public void testEnumTypeForOrdinal00() throws Exception { + SampleEnumFieldClass src = new SampleEnumFieldClass(); + src.f0 = 23; + src.f1 = SampleEnum.ONE; + + byte[] raw = MessagePack.pack(src); + + SampleEnumFieldClass dst = + MessagePack.unpack(raw, SampleEnumFieldClass.class); + Assert.assertThat(dst.f0, is(src.f0)); + Assert.assertThat(dst.f1, is(src.f1)); + } + + @Test + public void testEnumTypeForOrdinal01() throws Exception { + SampleEnumFieldClass src = null; + + byte[] raw = MessagePack.pack(src); + + SampleEnumFieldClass dst = + MessagePack.unpack(raw, SampleEnumFieldClass.class); + Assert.assertThat(dst,is(src)); + } + + @MessagePackBeans + public static class SampleEnumFieldClass { + public int f0; + + public SampleEnum f1; + + public int getF0() { + return f0; + } + + public void setF0(int f0) { + this.f0 = f0; + } + + public SampleEnum getF1() { + return f1; + } + + public void setF1(SampleEnum f1) { + this.f1 = f1; + } + + public SampleEnumFieldClass() { + } + } + + @MessagePackOrdinalEnum + public enum SampleEnum { + ONE, TWO, THREE; + } + + @Test + public void testOptionalEnumTypeForOrdinal00() throws Exception { + SampleOptionalEnumFieldClass src = new SampleOptionalEnumFieldClass(); + src.f0 = 0; + src.f1 = SampleOptionalEnum.ONE; + + byte[] raw = MessagePack.pack(src); + + SampleOptionalEnumFieldClass dst = + MessagePack.unpack(raw, SampleOptionalEnumFieldClass.class); + assertTrue(src.f0 == dst.f0); + assertTrue(src.f1 == dst.f1); + } + + @Test + public void testOptionalEnumTypeForOrdinal01() throws Exception { + SampleOptionalEnumFieldClass src = new SampleOptionalEnumFieldClass(); + src.f1 = null; + + byte[] raw = MessagePack.pack(src); + + SampleOptionalEnumFieldClass dst = + MessagePack.unpack(raw, SampleOptionalEnumFieldClass.class); + assertTrue(src.f0 == dst.f0); + assertEquals(src.f1, dst.f1); + } + + @Test + public void testOptionalEnumTypeForOrdinal02() throws Exception { + SampleEnumFieldClass src = null; + + byte[] raw = MessagePack.pack(src); + + SampleEnumFieldClass dst = + MessagePack.unpack(raw, SampleEnumFieldClass.class); + assertEquals(src, dst); + } + + @MessagePackBeans + public static class SampleOptionalEnumFieldClass { + @Optional + public int f0; + + @Optional + public SampleOptionalEnum f1; + + @Optional + public int getF0() { + return f0; + } + + public void setF0(int f0) { + this.f0 = f0; + } + + @Optional + public SampleOptionalEnum getF1() { + return f1; + } + + public void setF1(SampleOptionalEnum f1) { + this.f1 = f1; + } + + public SampleOptionalEnumFieldClass() { + } + } + + @MessagePackOrdinalEnum + public enum SampleOptionalEnum { + ONE, TWO, THREE; + } + + @Test + public void testFieldModifiers() throws Exception { + FieldModifiersClass src = new FieldModifiersClass(); + src.f0 = 0; + src.f2 = 2; + src.f3 = 3; + src.f4 = 4; + + byte[] raw = MessagePack.pack(src); + + FieldModifiersClass dst = + MessagePack.unpack(raw, FieldModifiersClass.class); + Assert.assertEquals(src.f1,dst.f1); + Assert.assertThat(dst.f2, is( not(src.f2))); + Assert.assertThat(dst.f3, is( not(src.f3))); + Assert.assertThat(dst.f4, is( not(src.f4))); + } + + @MessagePackBeans + public static class FieldModifiersClass { + public int f0; + public final int f1 = 1; + private int f2; + protected int f3; + int f4; + + public int getF0() { + return f0; + } + + public void setF0(int f0) { + this.f0 = f0; + } + + private int getF2() { + return f2; + } + + private void setF2(int f2) { + this.f2 = f2; + } + + public int getF3() { + return f3; + } + + protected void setF3(int f3) { + this.f3 = f3; + } + + public int getF4() { + return f4; + } + + void setF4(int f4) { + this.f4 = f4; + } + + public int getF1() { + return f1; + } + + public FieldModifiersClass() { + } + } + + @Test + public void testOptionalFieldModifiers() throws Exception { + OptionalFieldModifiersClass src = new OptionalFieldModifiersClass(); + src.f0 = 0; + src.f2 = 2; + src.f3 = 3; + src.f4 = 4; + + byte[] raw = MessagePack.pack(src); + + OptionalFieldModifiersClass dst = + MessagePack.unpack(raw, OptionalFieldModifiersClass.class); + Assert.assertThat(dst.f0, is(src.f0)); + Assert.assertThat(dst.f1, is(src.f1)); + Assert.assertThat(dst.f2, is(not(src.f2))); + Assert.assertThat(dst.f3, is(not(src.f3))); + Assert.assertThat(dst.f4, is(not(src.f4))); + } + + @MessagePackBeans + public static class OptionalFieldModifiersClass { + @Optional + public int f0; + @Optional + public final int f1 = 1; + private int f2; + protected int f3; + int f4; + + @Optional + public int getF0() { + return f0; + } + + public void setF0(int f0) { + this.f0 = f0; + } + + private int getF2() { + return f2; + } + + public void setF2(int f2) { + this.f2 = f2; + } + + protected int getF3() { + return f3; + } + + protected void setF3(int f3) { + this.f3 = f3; + } + + public int getF4() { + return f4; + } + + void setF4(int f4) { + this.f4 = f4; + } + + public int getF1() { + return f1; + } + + public OptionalFieldModifiersClass() { + } + } + + @Test + public void testNestedFieldClass00() throws Exception { + BaseClass src = new BaseClass(); + NestedClass src2 = new NestedClass(); + src.f0 = 0; + src2.f2 = 2; + src.f1 = src2; + + byte[] raw = MessagePack.pack(src); + + BaseClass dst = + MessagePack.unpack(raw, BaseClass.class); + assertTrue(src.f0 == dst.f0); + assertTrue(src.f1.f2 == dst.f1.f2); + } + + @Test + public void testNestedFieldClass01() throws Exception { + BaseClass src = null; + + byte[] raw = MessagePack.pack(src); + + BaseClass dst = + MessagePack.unpack(raw, BaseClass.class); + assertEquals(src, dst); + } + + @MessagePackBeans + public static class BaseClass { + public int f0; + public NestedClass f1; + + public int getF0() { + return f0; + } + + public void setF0(int f0) { + this.f0 = f0; + } + + public NestedClass getF1() { + return f1; + } + + public void setF1(NestedClass f1) { + this.f1 = f1; + } + + public BaseClass() { + } + } + + @MessagePackBeans + public static class NestedClass { + public int f2; + + public int getF2() { + return f2; + } + + public void setF2(int f2) { + this.f2 = f2; + } + + public NestedClass() { + } + } + + @Test + public void testOptionalNestedFieldClass00() throws Exception { + OptionalBaseClass src = new OptionalBaseClass(); + OptionalNestedClass src2 = new OptionalNestedClass(); + src.f0 = 0; + src2.f2 = 2; + src.f1 = src2; + + byte[] raw = MessagePack.pack(src); + + OptionalBaseClass dst = + MessagePack.unpack(raw, OptionalBaseClass.class); + assertTrue(src.f0 == dst.f0); + assertTrue(src.f1.f2 == dst.f1.f2); + } + + @Test + public void testOptionalNestedFieldClass01() throws Exception { + OptionalBaseClass src = new OptionalBaseClass(); + src.f1 = null; + + byte[] raw = MessagePack.pack(src); + + OptionalBaseClass dst = + MessagePack.unpack(raw, OptionalBaseClass.class); + assertTrue(src.f0 == dst.f0); + assertTrue(src.f1 == dst.f1); + } + + @Test + public void testOptionalNestedFieldClass02() throws Exception { + OptionalBaseClass src = null; + + byte[] raw = MessagePack.pack(src); + + OptionalBaseClass dst = + MessagePack.unpack(raw, OptionalBaseClass.class); + assertEquals(src, dst); + } + + @MessagePackBeans + public static class OptionalBaseClass { + @Optional + public int f0; + @Optional + public OptionalNestedClass f1; + + @Optional + public int getF0() { + return f0; + } + + public void setF0(int f0) { + this.f0 = f0; + } + + @Optional + public OptionalNestedClass getF1() { + return f1; + } + + public void setF1(OptionalNestedClass f1) { + this.f1 = f1; + } + + public OptionalBaseClass() { + } + } + + @MessagePackBeans + public static class OptionalNestedClass { + @Optional + public int f2; + + @Optional + public int getF2() { + return f2; + } + + public void setF2(int f2) { + this.f2 = f2; + } + + public OptionalNestedClass() { + } + } + + @Test + public void testMessagePackMessageFieldClass00() throws Exception { + BaseClass2 src = new BaseClass2(); + MessagePackMessageClass2 src2 = new MessagePackMessageClass2(); + src.f0 = 0; + src2.f2 = 2; + src.f1 = src2; + + byte[] raw = MessagePack.pack(src); + + BaseClass2 dst = + MessagePack.unpack(raw, BaseClass2.class); + assertTrue(src.f0 == dst.f0); + assertTrue(src.f1.f2 == dst.f1.f2); + } + + @Test + public void testMessagePackMessageFieldClass01() throws Exception { + BaseClass2 src = null; + + byte[] raw = MessagePack.pack(src); + + BaseClass2 dst = + MessagePack.unpack(raw, BaseClass2.class); + assertEquals(src, dst); + } + + @MessagePackBeans + public static class BaseClass2 { + public int f0; + public MessagePackMessageClass2 f1; + + public int getF0() { + return f0; + } + + public void setF0(int f0) { + this.f0 = f0; + } + + public MessagePackMessageClass2 getF1() { + return f1; + } + + public void setF1(MessagePackMessageClass2 f1) { + this.f1 = f1; + } + + public BaseClass2() { + } + } + + @MessagePackBeans + public static class MessagePackMessageClass2 { + public int getF2() { + return f2; + } + + public void setF2(int f2) { + this.f2 = f2; + } + + public int f2; + + public MessagePackMessageClass2() { + } + } + + @Test + public void testOptionalMessagePackMessageFieldClass00() throws Exception { + OptionalBaseClass2 src = new OptionalBaseClass2(); + OptionalMessagePackMessageClass2 src2 = new OptionalMessagePackMessageClass2(); + src.f0 = 0; + src2.f2 = 2; + src.f1 = src2; + + byte[] raw = MessagePack.pack(src); + + OptionalBaseClass2 dst = + MessagePack.unpack(raw, OptionalBaseClass2.class); + assertTrue(src.f0 == dst.f0); + assertTrue(src.f1.f2 == dst.f1.f2); + } + + @Test + public void testOptionalMessagePackMessageFieldClass01() throws Exception { + OptionalBaseClass2 src = new OptionalBaseClass2(); + src.f1 = null; + + byte[] raw = MessagePack.pack(src); + + OptionalBaseClass2 dst = + MessagePack.unpack(raw, OptionalBaseClass2.class); + assertTrue(src.f0 == dst.f0); + assertEquals(src.f1, dst.f1); + } + + @Test + public void testOptionalMessagePackMessageFieldClass02() throws Exception { + OptionalBaseClass2 src = null; + + byte[] raw = MessagePack.pack(src); + + OptionalBaseClass2 dst = + MessagePack.unpack(raw, OptionalBaseClass2.class); + assertEquals(src, dst); + } + + @MessagePackBeans + public static class OptionalBaseClass2 { + @Optional + public int f0; + @Optional + public OptionalMessagePackMessageClass2 f1; + + @Optional + public int getF0() { + return f0; + } + + public void setF0(int f0) { + this.f0 = f0; + } + + @Optional + public OptionalMessagePackMessageClass2 getF1() { + return f1; + } + + public void setF1(OptionalMessagePackMessageClass2 f1) { + this.f1 = f1; + } + + public OptionalBaseClass2() { + } + } + + @MessagePackBeans + public static class OptionalMessagePackMessageClass2 { + @Optional + public int f2; + + @Optional + public int getF2() { + return f2; + } + + public void setF2(int f2) { + this.f2 = f2; + } + + public OptionalMessagePackMessageClass2() { + } + } + + @Test + public void testExtendedClass00() throws Exception { + SampleSubClass src = new SampleSubClass(); + src.f0 = 0; + src.f2 = 2; + src.f3 = 3; + src.f4 = 4; + src.f5 = 5; + src.f8 = 8; + src.f9 = 9; + + byte[] raw = MessagePack.pack(src); + + SampleSubClass dst = + MessagePack.unpack(raw, SampleSubClass.class); + assertTrue(src.f0 == dst.f0); + assertTrue(src.f1 == dst.f1); + assertTrue(src.f2 != dst.f2); + assertTrue(src.f3 != dst.f3); + assertTrue(src.f4 != dst.f4); + assertTrue(src.f5 == dst.f5); + assertTrue(src.f6 == dst.f6); + assertTrue(src.f8 != dst.f8); + assertTrue(src.f9 != dst.f9); + } + + @Test + public void testExtendedClass01() throws Exception { + SampleSubClass src = null; + + byte[] raw = MessagePack.pack(src); + + SampleSubClass dst = + MessagePack.unpack(raw, SampleSubClass.class); + assertEquals(src, dst); + } + + @MessagePackBeans + public static class SampleSubClass extends SampleSuperClass { + public int f0; + public final int f1 = 1; + private int f2; + protected int f3; + int f4; + + public int getF0() { + return f0; + } + + public void setF0(int f0) { + this.f0 = f0; + } + + public int getF1() { + return f1; + } + + public SampleSubClass() { + } + } + + @MessagePackBeans + public static class SampleSuperClass { + public int f5; + public final int f6 = 2; + @SuppressWarnings("unused") + private int f7; + protected int f8; + int f9; + + public int getF5() { + return f5; + } + + public void setF5(int f5) { + this.f5 = f5; + } + + public SampleSuperClass() { + } + } + + @Test + public void testOptionalExtendedClass00() throws Exception { + SampleOptionalSubClass src = new SampleOptionalSubClass(); + src.f0 = 0; + src.f2 = 2; + src.f3 = 3; + src.f4 = 4; + src.f5 = 5; + src.f8 = 8; + src.f9 = 9; + + byte[] raw = MessagePack.pack(src); + + SampleOptionalSubClass dst = + MessagePack.unpack(raw, SampleOptionalSubClass.class); + assertTrue(src.f0 == dst.f0); + assertTrue(src.f1 == dst.f1); + assertTrue(src.f2 != dst.f2); + assertTrue(src.f3 != dst.f3); + assertTrue(src.f4 != dst.f4); + assertTrue(src.f5 == dst.f5); + assertTrue(src.f6 == dst.f6); + assertTrue(src.f8 != dst.f8); + assertTrue(src.f9 != dst.f9); + } + + @Test + public void testOptionalExtendedClass01() throws Exception { + SampleOptionalSubClass src = null; + + byte[] raw = MessagePack.pack(src); + + SampleOptionalSubClass dst = + MessagePack.unpack(raw, SampleOptionalSubClass.class); + assertEquals(src, dst); + } + + @MessagePackBeans + public static class SampleOptionalSubClass extends SampleOptionalSuperClass { + @Optional + public int f0; + public final int f1 = 1; + private int f2; + protected int f3; + int f4; + @Optional + public int getF0() { + return f0; + } + + public void setF0(int f0) { + this.f0 = f0; + } + + public SampleOptionalSubClass() { + } + } + + @MessagePackBeans + public static class SampleOptionalSuperClass { + @Optional + public int getF5() { + return f5; + } + + public void setF5(int f5) { + this.f5 = f5; + } + + @Optional + public int f5; + public final int f6 = 2; + @SuppressWarnings("unused") + private int f7; + protected int f8; + int f9; + + public SampleOptionalSuperClass() { + } + } + + @Test + public void testMessagePackableUnpackableClass00() throws Exception { + BaseMessagePackableUnpackableClass src = new BaseMessagePackableUnpackableClass(); + MessagePackableUnpackableClass src1 = new MessagePackableUnpackableClass(); + List<MessagePackableUnpackableClass> src2 = new ArrayList<MessagePackableUnpackableClass>(); + src1.f0 = 0; + src1.f1 = 1; + src.f0 = src1; + src.f1 = 1; + src2.add(src1); + src.f2 = src2; + + byte[] raw = MessagePack.pack(src); + + BaseMessagePackableUnpackableClass dst = + MessagePack.unpack(raw, BaseMessagePackableUnpackableClass.class); + assertEquals(src.f0.f0, dst.f0.f0); + assertEquals(src.f0.f1, dst.f0.f1); + assertEquals(src.f1, dst.f1); + assertEquals(src.f2.size(), dst.f2.size()); + assertEquals(src.f2.get(0).f0, dst.f2.get(0).f0); + assertEquals(src.f2.get(0).f1, dst.f2.get(0).f1); + } + + @Test + public void testMessagePackableUnpackableClass01() throws Exception { + BaseMessagePackableUnpackableClass src = null; + + byte[] raw = MessagePack.pack(src); + + BaseMessagePackableUnpackableClass dst = + MessagePack.unpack(raw, BaseMessagePackableUnpackableClass.class); + assertEquals(src, dst); + } + + @MessagePackBeans + public static class BaseMessagePackableUnpackableClass { + public MessagePackableUnpackableClass f0; + public int f1; + public List<MessagePackableUnpackableClass> f2; + + public MessagePackableUnpackableClass getF0() { + return f0; + } + + public void setF0(MessagePackableUnpackableClass f0) { + this.f0 = f0; + } + + public int getF1() { + return f1; + } + + public void setF1(int f1) { + this.f1 = f1; + } + + public List<MessagePackableUnpackableClass> getF2() { + return f2; + } + + public void setF2(List<MessagePackableUnpackableClass> f2) { + this.f2 = f2; + } + + public BaseMessagePackableUnpackableClass() { + } + } + + @MessagePackBeans + public static class MessagePackableUnpackableClass implements + MessagePackable, MessageUnpackable { + public int getF0() { + return f0; + } + + public void setF0(int f0) { + this.f0 = f0; + } + + public int getF1() { + return f1; + } + + public void setF1(int f1) { + this.f1 = f1; + } + + public int f0; + public int f1; + + public MessagePackableUnpackableClass() { + } + + @Override + public void messagePack(Packer packer) throws IOException { + packer.packArray(2); + packer.pack(f0); + packer.pack(f1); + } + + @Override + public void messageUnpack(Unpacker unpacker) throws IOException, + MessageTypeException { + if (unpacker.tryUnpackNull()) { + return; + } + unpacker.unpackArray(); + f0 = unpacker.unpackInt(); + f1 = unpacker.unpackInt(); + } + } + + @Test + public void testOptionalMessagePackableUnpackableClass00() throws Exception { + OptionalBaseMessagePackableUnpackableClass src = new OptionalBaseMessagePackableUnpackableClass(); + OptionalMessagePackableUnpackableClass src1 = new OptionalMessagePackableUnpackableClass(); + List<OptionalMessagePackableUnpackableClass> src2 = new ArrayList<OptionalMessagePackableUnpackableClass>(); + src1.f0 = 0; + src1.f1 = 1; + src.f0 = src1; + src.f1 = 1; + src2.add(src1); + src.f2 = src2; + + byte[] raw = MessagePack.pack(src); + + OptionalBaseMessagePackableUnpackableClass dst = + MessagePack.unpack(raw, OptionalBaseMessagePackableUnpackableClass.class); + assertEquals(src.f0.f0, dst.f0.f0); + assertEquals(src.f0.f1, dst.f0.f1); + assertEquals(src.f1, dst.f1); + assertEquals(src.f2.size(), dst.f2.size()); + assertEquals(src.f2.get(0).f0, dst.f2.get(0).f0); + assertEquals(src.f2.get(0).f1, dst.f2.get(0).f1); + } + + @Test + public void testOptionalMessagePackableUnpackableClass01() throws Exception { + OptionalBaseMessagePackableUnpackableClass src = new OptionalBaseMessagePackableUnpackableClass(); + src.f0 = null; + src.f1 = 1; + src.f2 = null; + + byte[] raw = MessagePack.pack(src); + + OptionalBaseMessagePackableUnpackableClass dst = + MessagePack.unpack(raw, OptionalBaseMessagePackableUnpackableClass.class); + assertEquals(src.f0, dst.f0); + assertEquals(src.f1, dst.f1); + assertEquals(src.f2, dst.f2); + } + + @Test + public void testOptionalMessagePackableUnpackableClass02() throws Exception { + OptionalBaseMessagePackableUnpackableClass src = null; + + byte[] raw = MessagePack.pack(src); + + OptionalBaseMessagePackableUnpackableClass dst = + MessagePack.unpack(raw, OptionalBaseMessagePackableUnpackableClass.class); + assertEquals(src, dst); + } + + @MessagePackBeans + public static class OptionalBaseMessagePackableUnpackableClass { + @Optional + public OptionalMessagePackableUnpackableClass f0; + @Optional + public int f1; + @Optional + public List<OptionalMessagePackableUnpackableClass> f2; + + @Optional + public OptionalMessagePackableUnpackableClass getF0() { + return f0; + } + + public void setF0(OptionalMessagePackableUnpackableClass f0) { + this.f0 = f0; + } + + @Optional + public int getF1() { + return f1; + } + + public void setF1(int f1) { + this.f1 = f1; + } + + @Optional + public List<OptionalMessagePackableUnpackableClass> getF2() { + return f2; + } + + public void setF2(List<OptionalMessagePackableUnpackableClass> f2) { + this.f2 = f2; + } + + public OptionalBaseMessagePackableUnpackableClass() { + } + } + + @MessagePackBeans + public static class OptionalMessagePackableUnpackableClass implements + MessagePackable, MessageUnpackable { + @Optional + public int getF0() { + return f0; + } + + public void setF0(int f0) { + this.f0 = f0; + } + + @Optional + public int getF1() { + return f1; + } + + public void setF1(int f1) { + this.f1 = f1; + } + + @Optional + public int f0; + @Optional + public int f1; + + public OptionalMessagePackableUnpackableClass() { + } + + @Override + public void messagePack(Packer packer) throws IOException { + packer.packArray(2); + packer.pack(f0); + packer.pack(f1); + } + + @Override + public void messageUnpack(Unpacker unpacker) throws IOException, + MessageTypeException { + if (unpacker.tryUnpackNull()) { + return; + } + unpacker.unpackArray(); + f0 = unpacker.unpackInt(); + f1 = unpacker.unpackInt(); + } + } +} + diff --git a/java/src/test/java/org/msgpack/template/TestReflectionTemplateBuilderPackConvert.java b/java/src/test/java/org/msgpack/template/TestReflectionTemplateBuilderPackConvert.java new file mode 100644 index 00000000..dcb039f7 --- /dev/null +++ b/java/src/test/java/org/msgpack/template/TestReflectionTemplateBuilderPackConvert.java @@ -0,0 +1,1417 @@ +package org.msgpack.template; + +import java.io.ByteArrayInputStream; +import java.io.ByteArrayOutputStream; +import java.io.IOException; +import java.math.BigInteger; +import java.nio.ByteBuffer; +import java.util.ArrayList; +import java.util.HashMap; +import java.util.Iterator; +import java.util.List; +import java.util.Map; + +import org.junit.Test; + +import org.msgpack.MessagePack; +import org.msgpack.MessagePackable; +import org.msgpack.MessagePacker; +import org.msgpack.MessageTypeException; +import org.msgpack.MessageUnpackable; +import org.msgpack.Packer; +import org.msgpack.Template; +import org.msgpack.Unpacker; +import org.msgpack.annotation.MessagePackMessage; +import org.msgpack.annotation.MessagePackOrdinalEnum; +import org.msgpack.annotation.Optional; +import org.msgpack.template.builder.BuilderSelectorRegistry; +import org.msgpack.template.builder.MessagePackBeansBuilderSelector; +import org.msgpack.template.builder.MessagePackMessageBuilderSelector; +import org.msgpack.template.builder.TemplateBuilder; + +import junit.framework.Assert; +import junit.framework.TestCase; + +public class TestReflectionTemplateBuilderPackConvert extends TestCase { + static { + //Replace template selectors from javassist to reflection. + BuilderSelectorRegistry instance = BuilderSelectorRegistry.getInstance(); + + instance.replace( + new MessagePackMessageBuilderSelector( + new ReflectionTemplateBuilder())); + instance.setForceBuilder( new ReflectionTemplateBuilder()); + instance.replace(new MessagePackBeansBuilderSelector( + new BeansReflectionTemplateBuilder())); + + MessagePack.register(PrimitiveTypeFieldsClass.class); + MessagePack.register(OptionalPrimitiveTypeFieldsClass.class); + MessagePack.register(GeneralReferenceTypeFieldsClass.class); + MessagePack.register(GeneralOptionalReferenceTypeFieldsClass.class); + MessagePack.register(SampleListTypes.class); + MessagePack.register(SampleOptionalListTypes.class); + MessagePack.register(SampleMapTypes.class); + MessagePack.register(SampleOptionalMapTypes.class); + MessagePack.register(SampleEnumFieldClass.class); + MessagePack.register(SampleOptionalEnumFieldClass.class); + MessagePack.register(FieldModifiersClass.class); + MessagePack.register(OptionalFieldModifiersClass.class); + MessagePack.register(BaseClass.class); + MessagePack.register(NestedClass.class); + MessagePack.register(BaseClass2.class); + MessagePack.register(OptionalBaseClass.class); + MessagePack.register(OptionalNestedClass.class); + MessagePack.register(OptionalBaseClass2.class); + MessagePack.register(SampleSubClass.class); + MessagePack.register(SampleSuperClass.class); + MessagePack.register(SampleOptionalSubClass.class); + MessagePack.register(SampleOptionalSuperClass.class); + MessagePack.register(BaseMessagePackableUnpackableClass.class); + MessagePack.register(MessagePackableUnpackableClass.class); + MessagePack.register(OptionalBaseMessagePackableUnpackableClass.class); + MessagePack.register(OptionalMessagePackableUnpackableClass.class); + } + + @Test + public void testPrimitiveTypeFields00() throws Exception { + PrimitiveTypeFieldsClass src = new PrimitiveTypeFieldsClass(); + src.f0 = (byte) 0; + src.f1 = 1; + src.f2 = 2; + src.f3 = 3; + src.f4 = 4; + src.f5 = 5; + src.f6 = false; + + byte[] raw = MessagePack.pack(src); + + PrimitiveTypeFieldsClass dst = + MessagePack.unpack(raw).convert(PrimitiveTypeFieldsClass.class); + assertEquals(src.f0, dst.f0); + assertEquals(src.f1, dst.f1); + assertEquals(src.f2, dst.f2); + assertEquals(src.f3, dst.f3); + assertEquals(src.f4, dst.f4); + assertEquals(src.f5, dst.f5); + assertEquals(src.f6, dst.f6); + } + + @Test + public void testPrimitiveTypeFields01() throws Exception { + PrimitiveTypeFieldsClass src = new PrimitiveTypeFieldsClass(); + + byte[] raw = MessagePack.pack(src); + + PrimitiveTypeFieldsClass dst = + MessagePack.unpack(raw).convert(PrimitiveTypeFieldsClass.class); + assertEquals(src.f0, dst.f0); + assertEquals(src.f1, dst.f1); + assertEquals(src.f2, dst.f2); + assertEquals(src.f3, dst.f3); + assertEquals(src.f4, dst.f4); + assertEquals(src.f5, dst.f5); + assertEquals(src.f6, dst.f6); + } + + @Test + public void testPrimitiveTypeFields02() throws Exception { + PrimitiveTypeFieldsClass src = null; + + byte[] raw = MessagePack.pack(src); + + PrimitiveTypeFieldsClass dst = + MessagePack.unpack(raw).convert(PrimitiveTypeFieldsClass.class); + assertEquals(src, dst); + } + + public static class PrimitiveTypeFieldsClass { + public byte f0; + public short f1; + public int f2; + public long f3; + public float f4; + public double f5; + public boolean f6; + + public PrimitiveTypeFieldsClass() { + } + } + + @Test + public void testOptionalPrimitiveTypeFields00() throws Exception { + OptionalPrimitiveTypeFieldsClass src = new OptionalPrimitiveTypeFieldsClass(); + src.f0 = (byte) 0; + src.f1 = 1; + src.f2 = 2; + src.f3 = 3; + src.f4 = 4; + src.f5 = 5; + src.f6 = false; + + byte[] raw = MessagePack.pack(src); + + PrimitiveTypeFieldsClass dst = + MessagePack.unpack(raw).convert(PrimitiveTypeFieldsClass.class); + assertEquals(src.f0, dst.f0); + assertEquals(src.f1, dst.f1); + assertEquals(src.f2, dst.f2); + assertEquals(src.f3, dst.f3); + assertEquals(src.f4, dst.f4); + assertEquals(src.f5, dst.f5); + assertEquals(src.f6, dst.f6); + } + + @Test + public void testOptionalPrimitiveTypeFields01() throws Exception { + OptionalPrimitiveTypeFieldsClass src = new OptionalPrimitiveTypeFieldsClass(); + + byte[] raw = MessagePack.pack(src); + + OptionalPrimitiveTypeFieldsClass dst = + MessagePack.unpack(raw).convert(OptionalPrimitiveTypeFieldsClass.class); + assertEquals(src.f0, dst.f0); + assertEquals(src.f1, dst.f1); + assertEquals(src.f2, dst.f2); + assertEquals(src.f3, dst.f3); + assertEquals(src.f4, dst.f4); + assertEquals(src.f5, dst.f5); + assertEquals(src.f6, dst.f6); + } + + @Test + public void testOptionalPrimitiveTypeFields02() throws Exception { + OptionalPrimitiveTypeFieldsClass src = null; + + byte[] raw = MessagePack.pack(src); + + OptionalPrimitiveTypeFieldsClass dst = + MessagePack.unpack(raw).convert(OptionalPrimitiveTypeFieldsClass.class); + assertEquals(src, dst); + } + + public static class OptionalPrimitiveTypeFieldsClass { + @Optional + public byte f0; + @Optional + public short f1; + @Optional + public int f2; + @Optional + public long f3; + @Optional + public float f4; + @Optional + public double f5; + @Optional + public boolean f6; + + public OptionalPrimitiveTypeFieldsClass() { + } + } + + @Test + public void testGeneralReferenceTypeFieldsClass00() throws Exception { + GeneralReferenceTypeFieldsClass src = new GeneralReferenceTypeFieldsClass(); + src.f0 = 0; + src.f1 = 1; + src.f2 = 2; + src.f3 = (long) 3; + src.f4 = (float) 4; + src.f5 = (double) 5; + src.f6 = false; + src.f7 = new BigInteger("7"); + src.f8 = "8"; + src.f9 = new byte[] { 0x01, 0x02 }; + src.f10 = ByteBuffer.wrap("muga".getBytes()); + + byte[] raw = MessagePack.pack(src); + + GeneralReferenceTypeFieldsClass dst = + MessagePack.unpack(raw).convert(GeneralReferenceTypeFieldsClass.class); + assertEquals(src.f0, dst.f0); + assertEquals(src.f1, dst.f1); + assertEquals(src.f2, dst.f2); + assertEquals(src.f3, dst.f3); + assertEquals(src.f4, dst.f4); + assertEquals(src.f5, dst.f5); + assertEquals(src.f6, dst.f6); + assertEquals(src.f7, dst.f7); + assertEquals(src.f8, dst.f8); + assertEquals(src.f9[0], dst.f9[0]); + assertEquals(src.f9[1], dst.f9[1]); + assertEquals(src.f10, dst.f10); + } + + @Test + public void testGeneralReferenceTypeFieldsClass01() throws Exception { + GeneralReferenceTypeFieldsClass src = null; + + byte[] raw = MessagePack.pack(src); + + GeneralReferenceTypeFieldsClass dst = + MessagePack.unpack(raw).convert(GeneralReferenceTypeFieldsClass.class); + assertEquals(src, dst); + } + + public static class GeneralReferenceTypeFieldsClass { + public Byte f0; + public Short f1; + public Integer f2; + public Long f3; + public Float f4; + public Double f5; + public Boolean f6; + public BigInteger f7; + public String f8; + public byte[] f9; + public ByteBuffer f10; + + public GeneralReferenceTypeFieldsClass() { + } + } + + @Test + public void testGeneralOptionalReferenceTypeFieldsClass00() + throws Exception { + GeneralOptionalReferenceTypeFieldsClass src = new GeneralOptionalReferenceTypeFieldsClass(); + src.f0 = 0; + src.f1 = 1; + src.f2 = 2; + src.f3 = (long) 3; + src.f4 = (float) 4; + src.f5 = (double) 5; + src.f6 = false; + src.f7 = new BigInteger("7"); + src.f8 = "8"; + src.f9 = new byte[] { 0x01, 0x02 }; + src.f10 = ByteBuffer.wrap("muga".getBytes()); + + byte[] raw = MessagePack.pack(src); + + GeneralOptionalReferenceTypeFieldsClass dst = + MessagePack.unpack(raw).convert(GeneralOptionalReferenceTypeFieldsClass.class); + assertEquals(src.f0, dst.f0); + assertEquals(src.f1, dst.f1); + assertEquals(src.f2, dst.f2); + assertEquals(src.f3, dst.f3); + assertEquals(src.f4, dst.f4); + assertEquals(src.f5, dst.f5); + assertEquals(src.f6, dst.f6); + assertEquals(src.f7, dst.f7); + assertEquals(src.f8, dst.f8); + assertEquals(src.f9[0], dst.f9[0]); + assertEquals(src.f9[1], dst.f9[1]); + assertEquals(src.f10, dst.f10); + } + + @Test + public void testGeneralOptionalReferenceTypeFieldsClass01() + throws Exception { + GeneralOptionalReferenceTypeFieldsClass src = new GeneralOptionalReferenceTypeFieldsClass(); + src.f0 = null; + src.f1 = null; + src.f2 = null; + src.f3 = null; + src.f4 = null; + src.f5 = null; + src.f6 = null; + src.f7 = null; + src.f8 = null; + src.f9 = null; + src.f10 = null; + + byte[] raw = MessagePack.pack(src); + + GeneralOptionalReferenceTypeFieldsClass dst = + MessagePack.unpack(raw).convert(GeneralOptionalReferenceTypeFieldsClass.class); + assertEquals(src.f0, dst.f0); + assertEquals(src.f1, dst.f1); + assertEquals(src.f2, dst.f2); + assertEquals(src.f3, dst.f3); + assertEquals(src.f4, dst.f4); + assertEquals(src.f5, dst.f5); + assertEquals(src.f6, dst.f6); + assertEquals(src.f7, dst.f7); + assertEquals(src.f8, dst.f8); + assertEquals(src.f9, dst.f9); + assertEquals(src.f10, dst.f10); + } + + @Test + public void testGeneralOptionalReferenceTypeFieldsClass02() + throws Exception { + GeneralOptionalReferenceTypeFieldsClass src = null; + + byte[] raw = MessagePack.pack(src); + + GeneralOptionalReferenceTypeFieldsClass dst = + MessagePack.unpack(raw).convert(GeneralOptionalReferenceTypeFieldsClass.class); + assertEquals(src, dst); + } + + public static class GeneralOptionalReferenceTypeFieldsClass { + @Optional + public Byte f0; + @Optional + public Short f1; + @Optional + public Integer f2; + @Optional + public Long f3; + @Optional + public Float f4; + @Optional + public Double f5; + @Optional + public Boolean f6; + @Optional + public BigInteger f7; + @Optional + public String f8; + @Optional + public byte[] f9; + @Optional + public ByteBuffer f10; + + public GeneralOptionalReferenceTypeFieldsClass() { + } + } + + @Test + public void testListTypes00() throws Exception { + SampleListTypes src = new SampleListTypes(); + src.f0 = new ArrayList<Integer>(); + src.f1 = new ArrayList<Integer>(); + src.f1.add(1); + src.f1.add(2); + src.f1.add(3); + src.f2 = new ArrayList<String>(); + src.f2.add("e1"); + src.f2.add("e2"); + src.f2.add("e3"); + src.f3 = new ArrayList<List<String>>(); + src.f3.add(src.f2); + src.f4 = new ArrayList<SampleListNestedType>(); + SampleListNestedType slnt = new SampleListNestedType(); + slnt.f0 = new byte[] { 0x01, 0x02 }; + slnt.f1 = "muga"; + src.f4.add(slnt); + src.f5 = new ArrayList<ByteBuffer>(); + src.f5.add(ByteBuffer.wrap("e1".getBytes())); + src.f5.add(ByteBuffer.wrap("e2".getBytes())); + src.f5.add(ByteBuffer.wrap("e3".getBytes())); + + byte[] raw = MessagePack.pack(src); + + SampleListTypes dst = + MessagePack.unpack(raw).convert(SampleListTypes.class); + for (int i = 0; i < src.f1.size(); ++i) { + assertEquals(src.f1.get(i), dst.f1.get(i)); + } + assertEquals(src.f2.size(), dst.f2.size()); + for (int i = 0; i < src.f2.size(); ++i) { + assertEquals(src.f2.get(i), dst.f2.get(i)); + } + assertEquals(src.f3.size(), dst.f3.size()); + for (int i = 0; i < src.f3.size(); ++i) { + List<String> srclist = src.f3.get(i); + List<String> dstlist = dst.f3.get(i); + assertEquals(srclist.size(), dstlist.size()); + for (int j = 0; j < srclist.size(); ++j) { + assertEquals(srclist.get(j), dstlist.get(j)); + } + } + assertEquals(src.f4.size(), dst.f4.size()); + for (int i = 0; i < src.f4.size(); ++i) { + SampleListNestedType s = src.f4.get(i); + SampleListNestedType d = dst.f4.get(i); + assertEquals(s.f0[0], d.f0[0]); + assertEquals(s.f0[1], d.f0[1]); + assertEquals(s.f1, d.f1); + } + assertEquals(src.f5.size(), dst.f5.size()); + for (int i = 0; i < src.f5.size(); ++i) { + ByteBuffer s = src.f5.get(i); + ByteBuffer d = dst.f5.get(i); + assertEquals(s, d); + } + } + + @Test + public void testListTypes01() throws Exception { + SampleListTypes src = null; + + byte[] raw = MessagePack.pack(src); + + SampleListTypes dst = + MessagePack.unpack(raw).convert(SampleListTypes.class); + assertEquals(src, dst); + } + + public static class SampleListTypes { + public List<Integer> f0; + public List<Integer> f1; + public List<String> f2; + public List<List<String>> f3; + public List<SampleListNestedType> f4; + public List<ByteBuffer> f5; + + public SampleListTypes() { + } + } + + @MessagePackMessage + public static class SampleListNestedType { + public byte[] f0; + public String f1; + + public SampleListNestedType() { + } + } + + @Test + public void testOptionalListTypes00() throws Exception { + SampleOptionalListTypes src = new SampleOptionalListTypes(); + src.f0 = new ArrayList<Integer>(); + src.f1 = new ArrayList<Integer>(); + src.f1.add(1); + src.f1.add(2); + src.f1.add(3); + src.f2 = new ArrayList<String>(); + src.f2.add("e1"); + src.f2.add("e2"); + src.f2.add("e3"); + src.f3 = new ArrayList<List<String>>(); + src.f3.add(src.f2); + src.f4 = new ArrayList<SampleOptionalListNestedType>(); + SampleOptionalListNestedType slnt = new SampleOptionalListNestedType(); + slnt.f0 = new byte[] { 0x01, 0x02 }; + slnt.f1 = "muga"; + src.f4.add(slnt); + src.f5 = new ArrayList<ByteBuffer>(); + src.f5.add(ByteBuffer.wrap("e1".getBytes())); + src.f5.add(ByteBuffer.wrap("e2".getBytes())); + src.f5.add(ByteBuffer.wrap("e3".getBytes())); + + byte[] raw = MessagePack.pack(src); + + SampleOptionalListTypes dst = + MessagePack.unpack(raw).convert(SampleOptionalListTypes.class); + assertEquals(src.f0.size(), dst.f0.size()); + assertEquals(src.f1.size(), dst.f1.size()); + for (int i = 0; i < src.f1.size(); ++i) { + assertEquals(src.f1.get(i), dst.f1.get(i)); + } + assertEquals(src.f2.size(), dst.f2.size()); + for (int i = 0; i < src.f2.size(); ++i) { + assertEquals(src.f2.get(i), dst.f2.get(i)); + } + assertEquals(src.f3.size(), dst.f3.size()); + for (int i = 0; i < src.f3.size(); ++i) { + List<String> srclist = src.f3.get(i); + List<String> dstlist = dst.f3.get(i); + assertEquals(srclist.size(), dstlist.size()); + for (int j = 0; j < srclist.size(); ++j) { + assertEquals(srclist.get(j), dstlist.get(j)); + } + } + assertEquals(src.f4.size(), dst.f4.size()); + for (int i = 0; i < src.f4.size(); ++i) { + SampleOptionalListNestedType s = src.f4.get(i); + SampleOptionalListNestedType d = dst.f4.get(i); + assertEquals(s.f0[0], d.f0[0]); + assertEquals(s.f0[1], d.f0[1]); + assertEquals(s.f1, d.f1); + } + assertEquals(src.f5.size(), dst.f5.size()); + for (int i = 0; i < src.f5.size(); ++i) { + ByteBuffer s = src.f5.get(i); + ByteBuffer d = dst.f5.get(i); + assertEquals(s, d); + } + } + + @Test + public void testOptionalListTypes01() throws Exception { + SampleOptionalListTypes src = new SampleOptionalListTypes(); + src.f0 = new ArrayList<Integer>(); + src.f1 = null; + src.f2 = new ArrayList<String>(); + src.f3 = new ArrayList<List<String>>(); + src.f4 = null; + src.f5 = new ArrayList<ByteBuffer>(); + + byte[] raw = MessagePack.pack(src); + + SampleOptionalListTypes dst = + MessagePack.unpack(raw).convert(SampleOptionalListTypes.class); + assertEquals(src.f0.size(), dst.f0.size()); + assertEquals(src.f1, dst.f1); + assertEquals(src.f2.size(), dst.f2.size()); + assertEquals(src.f3.size(), dst.f3.size()); + assertEquals(src.f4, dst.f4); + assertEquals(src.f5.size(), dst.f5.size()); + } + + @Test + public void testOptionalListTypes02() throws Exception { + SampleListTypes src = null; + + byte[] raw = MessagePack.pack(src); + + SampleListTypes dst = + MessagePack.unpack(raw).convert(SampleListTypes.class); + assertEquals(src, dst); + } + + public static class SampleOptionalListTypes { + @Optional + public List<Integer> f0; + @Optional + public List<Integer> f1; + @Optional + public List<String> f2; + @Optional + public List<List<String>> f3; + @Optional + public List<SampleOptionalListNestedType> f4; + @Optional + public List<ByteBuffer> f5; + + public SampleOptionalListTypes() { + } + } + + @MessagePackMessage + public static class SampleOptionalListNestedType { + @Optional + public byte[] f0; + @Optional + public String f1; + + public SampleOptionalListNestedType() { + } + } + + @Test + public void testMapTypes00() throws Exception { + SampleMapTypes src = new SampleMapTypes(); + src.f0 = new HashMap<Integer, Integer>(); + src.f1 = new HashMap<Integer, Integer>(); + src.f1.put(1, 1); + src.f1.put(2, 2); + src.f1.put(3, 3); + src.f2 = new HashMap<String, Integer>(); + src.f2.put("k1", 1); + src.f2.put("k2", 2); + src.f2.put("k3", 3); + + byte[] raw = MessagePack.pack(src); + + SampleMapTypes dst = + MessagePack.unpack(raw).convert(SampleMapTypes.class); + Iterator<Integer> srcf1 = src.f1.keySet().iterator(); + Iterator<Integer> dstf1 = dst.f1.keySet().iterator(); + while (srcf1.hasNext()) { + Integer s1 = srcf1.next(); + Integer d1 = dstf1.next(); + assertEquals(s1, d1); + assertEquals(src.f1.get(s1), dst.f1.get(d1)); + } + assertEquals(src.f2.size(), dst.f2.size()); + Iterator<String> srcf2 = src.f2.keySet().iterator(); + Iterator<String> dstf2 = dst.f2.keySet().iterator(); + while (srcf2.hasNext()) { + String s2 = srcf2.next(); + String d2 = dstf2.next(); + assertEquals(s2, d2); + assertEquals(src.f2.get(s2), dst.f2.get(d2)); + } + } + + @Test + public void testMapTypes01() throws Exception { + SampleMapTypes src = null; + + byte[] raw = MessagePack.pack(src); + + SampleMapTypes dst = + MessagePack.unpack(raw).convert(SampleMapTypes.class); + assertEquals(src, dst); + } + + public static class SampleMapTypes { + public Map<Integer, Integer> f0; + public Map<Integer, Integer> f1; + public Map<String, Integer> f2; + + public SampleMapTypes() { + } + } + + @Test + public void testOptionalMapTypes00() throws Exception { + SampleOptionalMapTypes src = new SampleOptionalMapTypes(); + src.f0 = new HashMap<Integer, Integer>(); + src.f1 = new HashMap<Integer, Integer>(); + src.f1.put(1, 1); + src.f1.put(2, 2); + src.f1.put(3, 3); + src.f2 = new HashMap<String, Integer>(); + src.f2.put("k1", 1); + src.f2.put("k2", 2); + src.f2.put("k3", 3); + + byte[] raw = MessagePack.pack(src); + + SampleOptionalMapTypes dst = + MessagePack.unpack(raw).convert(SampleOptionalMapTypes.class); + assertEquals(src.f0.size(), dst.f0.size()); + assertEquals(src.f1.size(), dst.f1.size()); + Iterator<Integer> srcf1 = src.f1.keySet().iterator(); + Iterator<Integer> dstf1 = dst.f1.keySet().iterator(); + while (srcf1.hasNext()) { + Integer s1 = srcf1.next(); + Integer d1 = dstf1.next(); + assertEquals(s1, d1); + assertEquals(src.f1.get(s1), dst.f1.get(d1)); + } + assertEquals(src.f2.size(), dst.f2.size()); + Iterator<String> srcf2 = src.f2.keySet().iterator(); + Iterator<String> dstf2 = dst.f2.keySet().iterator(); + while (srcf2.hasNext()) { + String s2 = srcf2.next(); + String d2 = dstf2.next(); + assertEquals(s2, d2); + assertEquals(src.f2.get(s2), dst.f2.get(d2)); + } + } + + @Test + public void testOptionalMapTypes01() throws Exception { + SampleOptionalMapTypes src = new SampleOptionalMapTypes(); + src.f0 = new HashMap<Integer, Integer>(); + src.f1 = null; + src.f2 = new HashMap<String, Integer>(); + + byte[] raw = MessagePack.pack(src); + + SampleOptionalMapTypes dst = + MessagePack.unpack(raw).convert(SampleOptionalMapTypes.class); + assertEquals(src.f0.size(), dst.f0.size()); + assertEquals(src.f1, dst.f1); + assertEquals(src.f2.size(), dst.f2.size()); + } + + @Test + public void testOptionalMapTypes02() throws Exception { + SampleOptionalMapTypes src = null; + + byte[] raw = MessagePack.pack(src); + + SampleOptionalMapTypes dst = + MessagePack.unpack(raw).convert(SampleOptionalMapTypes.class); + assertEquals(src, dst); + } + + public static class SampleOptionalMapTypes { + @Optional + public Map<Integer, Integer> f0; + @Optional + public Map<Integer, Integer> f1; + @Optional + public Map<String, Integer> f2; + + public SampleOptionalMapTypes() { + } + } + + @Test + public void testFinalClass() throws Exception { + try { + TemplateBuilder builder = BuilderSelectorRegistry.getInstance().select(FinalModifierClass.class); + Assert.assertNull(builder);// no available builder + BuilderSelectorRegistry.getInstance().getForceBuilder().buildTemplate(FinalModifierClass.class); + assertTrue(true); + } catch (TemplateBuildException e) { + fail(); + } + assertTrue(true); + } + + public final static class FinalModifierClass { + } + + public abstract static class AbstractModifierClass { + } + + @Test + public void testInterfaceType00() throws Exception { + try { + TemplateBuilder builder = BuilderSelectorRegistry.getInstance().select(SampleInterface.class); + Assert.assertNull(builder);// no available builder + BuilderSelectorRegistry.getInstance().getForceBuilder().buildTemplate(SampleInterface.class); + fail(); + } catch (TemplateBuildException e) { + assertTrue(true); + } + assertTrue(true); + } + + @Test + public void testInterfaceType01() throws Exception { + try { + TemplateBuilder builder = BuilderSelectorRegistry.getInstance().select(SampleInterface.class); + Assert.assertNull(builder);// no available builder + BuilderSelectorRegistry.getInstance().getForceBuilder().buildTemplate(SampleInterface.class); + fail(); + } catch (TemplateBuildException e) { + assertTrue(true); + } + assertTrue(true); + } + + public interface SampleInterface { + } + + @Test + public void testEnumTypeForOrdinal00() throws Exception { + SampleEnumFieldClass src = new SampleEnumFieldClass(); + src.f0 = 0; + src.f1 = SampleEnum.ONE; + + byte[] raw = MessagePack.pack(src); + + SampleEnumFieldClass dst = + MessagePack.unpack(raw).convert(SampleEnumFieldClass.class); + assertTrue(src.f1 == dst.f1); + } + + @Test + public void testEnumTypeForOrdinal01() throws Exception { + SampleEnumFieldClass src = null; + + byte[] raw = MessagePack.pack(src); + + SampleEnumFieldClass dst = + MessagePack.unpack(raw).convert(SampleEnumFieldClass.class); + assertEquals(src, dst); + } + + public static class SampleEnumFieldClass { + public int f0; + + public SampleEnum f1; + + public SampleEnumFieldClass() { + } + } + + @MessagePackOrdinalEnum + public enum SampleEnum { + ONE, TWO, THREE; + } + + @Test + public void testOptionalEnumTypeForOrdinal00() throws Exception { + SampleOptionalEnumFieldClass src = new SampleOptionalEnumFieldClass(); + src.f0 = 0; + src.f1 = SampleOptionalEnum.ONE; + + byte[] raw = MessagePack.pack(src); + + SampleOptionalEnumFieldClass dst = + MessagePack.unpack(raw).convert(SampleOptionalEnumFieldClass.class); + assertTrue(src.f0 == dst.f0); + assertTrue(src.f1 == dst.f1); + } + + @Test + public void testOptionalEnumTypeForOrdinal01() throws Exception { + SampleOptionalEnumFieldClass src = new SampleOptionalEnumFieldClass(); + src.f1 = null; + + byte[] raw = MessagePack.pack(src); + + SampleOptionalEnumFieldClass dst = + MessagePack.unpack(raw).convert(SampleOptionalEnumFieldClass.class); + assertTrue(src.f0 == dst.f0); + assertEquals(src.f1, dst.f1); + } + + @Test + public void testOptionalEnumTypeForOrdinal02() throws Exception { + SampleEnumFieldClass src = null; + + byte[] raw = MessagePack.pack(src); + + SampleEnumFieldClass dst = + MessagePack.unpack(raw).convert(SampleEnumFieldClass.class); + assertEquals(src, dst); + } + + public static class SampleOptionalEnumFieldClass { + @Optional + public int f0; + + @Optional + public SampleOptionalEnum f1; + + public SampleOptionalEnumFieldClass() { + } + } + + @MessagePackOrdinalEnum + public enum SampleOptionalEnum { + ONE, TWO, THREE; + } + + @Test + public void testFieldModifiers() throws Exception { + FieldModifiersClass src = new FieldModifiersClass(); + src.f0 = 0; + src.f2 = 2; + src.f3 = 3; + src.f4 = 4; + + byte[] raw = MessagePack.pack(src); + + FieldModifiersClass dst = + MessagePack.unpack(raw).convert(FieldModifiersClass.class); + assertTrue(src.f1 == dst.f1); + assertTrue(src.f2 != dst.f2); + assertTrue(src.f3 != dst.f3); + assertTrue(src.f4 != dst.f4); + } + + public static class FieldModifiersClass { + public int f0; + public final int f1 = 1; + private int f2; + protected int f3; + int f4; + + public FieldModifiersClass() { + } + } + + @Test + public void testOptionalFieldModifiers() throws Exception { + OptionalFieldModifiersClass src = new OptionalFieldModifiersClass(); + src.f0 = 0; + src.f2 = 2; + src.f3 = 3; + src.f4 = 4; + + byte[] raw = MessagePack.pack(src); + + OptionalFieldModifiersClass dst = + MessagePack.unpack(raw).convert(OptionalFieldModifiersClass.class); + assertTrue(src.f0 == dst.f0); + assertTrue(src.f1 == dst.f1); + assertTrue(src.f2 != dst.f2); + assertTrue(src.f3 != dst.f3); + assertTrue(src.f4 != dst.f4); + } + + public static class OptionalFieldModifiersClass { + @Optional + public int f0; + @Optional + public final int f1 = 1; + private int f2; + protected int f3; + int f4; + + public OptionalFieldModifiersClass() { + } + } + + @Test + public void testNestedFieldClass00() throws Exception { + BaseClass src = new BaseClass(); + NestedClass src2 = new NestedClass(); + src.f0 = 0; + src2.f2 = 2; + src.f1 = src2; + + byte[] raw = MessagePack.pack(src); + + BaseClass dst = + MessagePack.unpack(raw).convert(BaseClass.class); + assertTrue(src.f0 == dst.f0); + assertTrue(src.f1.f2 == dst.f1.f2); + } + + @Test + public void testNestedFieldClass01() throws Exception { + BaseClass src = null; + + byte[] raw = MessagePack.pack(src); + + BaseClass dst = + MessagePack.unpack(raw).convert(BaseClass.class); + assertEquals(src, dst); + } + + public static class BaseClass { + public int f0; + public NestedClass f1; + + public BaseClass() { + } + } + + public static class NestedClass { + public int f2; + + public NestedClass() { + } + } + + @Test + public void testOptionalNestedFieldClass00() throws Exception { + OptionalBaseClass src = new OptionalBaseClass(); + OptionalNestedClass src2 = new OptionalNestedClass(); + src.f0 = 0; + src2.f2 = 2; + src.f1 = src2; + + byte[] raw = MessagePack.pack(src); + + OptionalBaseClass dst = + MessagePack.unpack(raw).convert(OptionalBaseClass.class); + assertTrue(src.f0 == dst.f0); + assertTrue(src.f1.f2 == dst.f1.f2); + } + + @Test + public void testOptionalNestedFieldClass01() throws Exception { + OptionalBaseClass src = new OptionalBaseClass(); + src.f1 = null; + + byte[] raw = MessagePack.pack(src); + + OptionalBaseClass dst = + MessagePack.unpack(raw).convert(OptionalBaseClass.class); + assertTrue(src.f0 == dst.f0); + assertTrue(src.f1 == dst.f1); + } + + @Test + public void testOptionalNestedFieldClass02() throws Exception { + OptionalBaseClass src = null; + + byte[] raw = MessagePack.pack(src); + + OptionalBaseClass dst = + MessagePack.unpack(raw).convert(OptionalBaseClass.class); + assertEquals(src, dst); + } + + public static class OptionalBaseClass { + @Optional + public int f0; + @Optional + public OptionalNestedClass f1; + + public OptionalBaseClass() { + } + } + + public static class OptionalNestedClass { + @Optional + public int f2; + + public OptionalNestedClass() { + } + } + + @Test + public void testMessagePackMessageFieldClass00() throws Exception { + BaseClass2 src = new BaseClass2(); + MessagePackMessageClass2 src2 = new MessagePackMessageClass2(); + src.f0 = 0; + src2.f2 = 2; + src.f1 = src2; + + byte[] raw = MessagePack.pack(src); + + BaseClass2 dst = + MessagePack.unpack(raw).convert(BaseClass2.class); + assertTrue(src.f0 == dst.f0); + assertTrue(src.f1.f2 == dst.f1.f2); + } + + @Test + public void testMessagePackMessageFieldClass01() throws Exception { + BaseClass2 src = null; + + byte[] raw = MessagePack.pack(src); + + BaseClass2 dst = + MessagePack.unpack(raw).convert(BaseClass2.class); + assertEquals(src, dst); + } + + public static class BaseClass2 { + public int f0; + public MessagePackMessageClass2 f1; + + public BaseClass2() { + } + } + + @MessagePackMessage + public static class MessagePackMessageClass2 { + public int f2; + + public MessagePackMessageClass2() { + } + } + + @Test + public void testOptionalMessagePackMessageFieldClass00() throws Exception { + OptionalBaseClass2 src = new OptionalBaseClass2(); + OptionalMessagePackMessageClass2 src2 = new OptionalMessagePackMessageClass2(); + src.f0 = 0; + src2.f2 = 2; + src.f1 = src2; + + byte[] raw = MessagePack.pack(src); + + OptionalBaseClass2 dst = + MessagePack.unpack(raw).convert(OptionalBaseClass2.class); + assertTrue(src.f0 == dst.f0); + assertTrue(src.f1.f2 == dst.f1.f2); + } + + @Test + public void testOptionalMessagePackMessageFieldClass01() throws Exception { + OptionalBaseClass2 src = new OptionalBaseClass2(); + src.f1 = null; + + byte[] raw = MessagePack.pack(src); + + OptionalBaseClass2 dst = + MessagePack.unpack(raw).convert(OptionalBaseClass2.class); + assertTrue(src.f0 == dst.f0); + assertEquals(src.f1, dst.f1); + } + + @Test + public void testOptionalMessagePackMessageFieldClass02() throws Exception { + OptionalBaseClass2 src = null; + + byte[] raw = MessagePack.pack(src); + + OptionalBaseClass2 dst = + MessagePack.unpack(raw).convert(OptionalBaseClass2.class); + assertEquals(src, dst); + } + + public static class OptionalBaseClass2 { + @Optional + public int f0; + @Optional + public OptionalMessagePackMessageClass2 f1; + + public OptionalBaseClass2() { + } + } + + @MessagePackMessage + public static class OptionalMessagePackMessageClass2 { + @Optional + public int f2; + + public OptionalMessagePackMessageClass2() { + } + } + + @Test + public void testExtendedClass00() throws Exception { + SampleSubClass src = new SampleSubClass(); + src.f0 = 0; + src.f2 = 2; + src.f3 = 3; + src.f4 = 4; + src.f5 = 5; + src.f8 = 8; + src.f9 = 9; + + byte[] raw = MessagePack.pack(src); + + SampleSubClass dst = + MessagePack.unpack(raw).convert(SampleSubClass.class); + assertTrue(src.f0 == dst.f0); + assertTrue(src.f1 == dst.f1); + assertTrue(src.f2 != dst.f2); + assertTrue(src.f3 != dst.f3); + assertTrue(src.f4 != dst.f4); + assertTrue(src.f5 == dst.f5); + assertTrue(src.f6 == dst.f6); + assertTrue(src.f8 != dst.f8); + assertTrue(src.f9 != dst.f9); + } + + @Test + public void testExtendedClass01() throws Exception { + SampleSubClass src = null; + + byte[] raw = MessagePack.pack(src); + + SampleSubClass dst = + MessagePack.unpack(raw).convert(SampleSubClass.class); + assertEquals(src, dst); + } + + public static class SampleSubClass extends SampleSuperClass { + public int f0; + public final int f1 = 1; + private int f2; + protected int f3; + int f4; + + public SampleSubClass() { + } + } + + public static class SampleSuperClass { + public int f5; + public final int f6 = 2; + @SuppressWarnings("unused") + private int f7; + protected int f8; + int f9; + + public SampleSuperClass() { + } + } + + @Test + public void testOptionalExtendedClass00() throws Exception { + SampleOptionalSubClass src = new SampleOptionalSubClass(); + src.f0 = 0; + src.f2 = 2; + src.f3 = 3; + src.f4 = 4; + src.f5 = 5; + src.f8 = 8; + src.f9 = 9; + + byte[] raw = MessagePack.pack(src); + + SampleOptionalSubClass dst = + MessagePack.unpack(raw).convert(SampleOptionalSubClass.class); + assertTrue(src.f0 == dst.f0); + assertTrue(src.f1 == dst.f1); + assertTrue(src.f2 != dst.f2); + assertTrue(src.f3 != dst.f3); + assertTrue(src.f4 != dst.f4); + assertTrue(src.f5 == dst.f5); + assertTrue(src.f6 == dst.f6); + assertTrue(src.f8 != dst.f8); + assertTrue(src.f9 != dst.f9); + } + + @Test + public void testOptionalExtendedClass01() throws Exception { + SampleOptionalSubClass src = null; + + byte[] raw = MessagePack.pack(src); + + SampleOptionalSubClass dst = + MessagePack.unpack(raw).convert(SampleOptionalSubClass.class); + assertEquals(src, dst); + } + + public static class SampleOptionalSubClass extends SampleOptionalSuperClass { + @Optional + public int f0; + public final int f1 = 1; + private int f2; + protected int f3; + int f4; + + public SampleOptionalSubClass() { + } + } + + public static class SampleOptionalSuperClass { + @Optional + public int f5; + public final int f6 = 2; + @SuppressWarnings("unused") + private int f7; + protected int f8; + int f9; + + public SampleOptionalSuperClass() { + } + } + + @Test + public void testMessagePackableUnpackableClass00() throws Exception { + BaseMessagePackableUnpackableClass src = new BaseMessagePackableUnpackableClass(); + MessagePackableUnpackableClass src1 = new MessagePackableUnpackableClass(); + List<MessagePackableUnpackableClass> src2 = new ArrayList<MessagePackableUnpackableClass>(); + src1.f0 = 0; + src1.f1 = 1; + src.f0 = src1; + src.f1 = 1; + src2.add(src1); + src.f2 = src2; + + byte[] raw = MessagePack.pack(src); + + BaseMessagePackableUnpackableClass dst = + MessagePack.unpack(raw).convert(BaseMessagePackableUnpackableClass.class); + assertEquals(src.f0.f0, dst.f0.f0); + assertEquals(src.f0.f1, dst.f0.f1); + assertEquals(src.f1, dst.f1); + assertEquals(src.f2.size(), dst.f2.size()); + assertEquals(src.f2.get(0).f0, dst.f2.get(0).f0); + assertEquals(src.f2.get(0).f1, dst.f2.get(0).f1); + } + + @Test + public void testMessagePackableUnpackableClass01() throws Exception { + BaseMessagePackableUnpackableClass src = null; + + byte[] raw = MessagePack.pack(src); + + BaseMessagePackableUnpackableClass dst = + MessagePack.unpack(raw).convert(BaseMessagePackableUnpackableClass.class); + assertEquals(src, dst); + } + + public static class BaseMessagePackableUnpackableClass { + public MessagePackableUnpackableClass f0; + public int f1; + public List<MessagePackableUnpackableClass> f2; + + public BaseMessagePackableUnpackableClass() { + } + } + + public static class MessagePackableUnpackableClass implements + MessagePackable, MessageUnpackable { + public int f0; + public int f1; + + public MessagePackableUnpackableClass() { + } + + @Override + public void messagePack(Packer packer) throws IOException { + packer.packArray(2); + packer.pack(f0); + packer.pack(f1); + } + + @Override + public void messageUnpack(Unpacker unpacker) throws IOException, + MessageTypeException { + if (unpacker.tryUnpackNull()) { + return; + } + unpacker.unpackArray(); + f0 = unpacker.unpackInt(); + f1 = unpacker.unpackInt(); + } + } + + @Test + public void testOptionalMessagePackableUnpackableClass00() throws Exception { + OptionalBaseMessagePackableUnpackableClass src = new OptionalBaseMessagePackableUnpackableClass(); + OptionalMessagePackableUnpackableClass src1 = new OptionalMessagePackableUnpackableClass(); + List<OptionalMessagePackableUnpackableClass> src2 = new ArrayList<OptionalMessagePackableUnpackableClass>(); + src1.f0 = 0; + src1.f1 = 1; + src.f0 = src1; + src.f1 = 1; + src2.add(src1); + src.f2 = src2; + + byte[] raw = MessagePack.pack(src); + + OptionalBaseMessagePackableUnpackableClass dst = + MessagePack.unpack(raw).convert(OptionalBaseMessagePackableUnpackableClass.class); + assertEquals(src.f0.f0, dst.f0.f0); + assertEquals(src.f0.f1, dst.f0.f1); + assertEquals(src.f1, dst.f1); + assertEquals(src.f2.size(), dst.f2.size()); + assertEquals(src.f2.get(0).f0, dst.f2.get(0).f0); + assertEquals(src.f2.get(0).f1, dst.f2.get(0).f1); + } + + @Test + public void testOptionalMessagePackableUnpackableClass01() throws Exception { + OptionalBaseMessagePackableUnpackableClass src = new OptionalBaseMessagePackableUnpackableClass(); + src.f0 = null; + src.f1 = 1; + src.f2 = null; + + byte[] raw = MessagePack.pack(src); + + OptionalBaseMessagePackableUnpackableClass dst = + MessagePack.unpack(raw).convert(OptionalBaseMessagePackableUnpackableClass.class); + assertEquals(src.f0, dst.f0); + assertEquals(src.f1, dst.f1); + assertEquals(src.f2, dst.f2); + } + + @Test + public void testOptionalMessagePackableUnpackableClass02() throws Exception { + OptionalBaseMessagePackableUnpackableClass src = null; + + byte[] raw = MessagePack.pack(src); + + OptionalBaseMessagePackableUnpackableClass dst = + MessagePack.unpack(raw).convert(OptionalBaseMessagePackableUnpackableClass.class); + assertEquals(src, dst); + } + + public static class OptionalBaseMessagePackableUnpackableClass { + @Optional + public OptionalMessagePackableUnpackableClass f0; + @Optional + public int f1; + @Optional + public List<OptionalMessagePackableUnpackableClass> f2; + + public OptionalBaseMessagePackableUnpackableClass() { + } + } + + public static class OptionalMessagePackableUnpackableClass implements + MessagePackable, MessageUnpackable { + @Optional + public int f0; + @Optional + public int f1; + + public OptionalMessagePackableUnpackableClass() { + } + + @Override + public void messagePack(Packer packer) throws IOException { + packer.packArray(2); + packer.pack(f0); + packer.pack(f1); + } + + @Override + public void messageUnpack(Unpacker unpacker) throws IOException, + MessageTypeException { + if (unpacker.tryUnpackNull()) { + return; + } + unpacker.unpackArray(); + f0 = unpacker.unpackInt(); + f1 = unpacker.unpackInt(); + } + } +} + diff --git a/java/src/test/java/org/msgpack/template/TestReflectionTemplateBuilderPackUnpack.java b/java/src/test/java/org/msgpack/template/TestReflectionTemplateBuilderPackUnpack.java new file mode 100644 index 00000000..6080df6e --- /dev/null +++ b/java/src/test/java/org/msgpack/template/TestReflectionTemplateBuilderPackUnpack.java @@ -0,0 +1,1422 @@ +package org.msgpack.template; + +import java.io.ByteArrayInputStream; +import java.io.ByteArrayOutputStream; +import java.io.IOException; +import java.math.BigInteger; +import java.nio.ByteBuffer; +import java.util.ArrayList; +import java.util.HashMap; +import java.util.Iterator; +import java.util.List; +import java.util.Map; + +import org.junit.Test; + +import org.msgpack.MessagePack; +import org.msgpack.MessagePackable; +import org.msgpack.MessagePacker; +import org.msgpack.MessageTypeException; +import org.msgpack.MessageUnpackable; +import org.msgpack.Packer; +import org.msgpack.Template; +import org.msgpack.Unpacker; +import org.msgpack.annotation.MessagePackMessage; +import org.msgpack.annotation.MessagePackOrdinalEnum; +import org.msgpack.annotation.Optional; +import org.msgpack.template.TestTemplateBuilderPackConvert.SampleInterface; +import org.msgpack.template.builder.BuilderSelectorRegistry; +import org.msgpack.template.builder.MessagePackBeansBuilderSelector; +import org.msgpack.template.builder.MessagePackMessageBuilderSelector; +import org.msgpack.template.builder.TemplateBuilder; + +import junit.framework.Assert; +import junit.framework.TestCase; + +import static org.junit.Assert.assertThat; + +public class TestReflectionTemplateBuilderPackUnpack extends TestCase { + static { + //Replace template selectors from javassist to reflection. + BuilderSelectorRegistry instance = BuilderSelectorRegistry.getInstance(); + + instance.replace( + new MessagePackMessageBuilderSelector( + new ReflectionTemplateBuilder())); + instance.setForceBuilder( new ReflectionTemplateBuilder()); + instance.replace(new MessagePackBeansBuilderSelector( + new BeansReflectionTemplateBuilder())); + + + MessagePack.register(PrimitiveTypeFieldsClass.class); + MessagePack.register(OptionalPrimitiveTypeFieldsClass.class); + MessagePack.register(GeneralReferenceTypeFieldsClass.class); + MessagePack.register(GeneralOptionalReferenceTypeFieldsClass.class); + MessagePack.register(SampleListTypes.class); + MessagePack.register(SampleOptionalListTypes.class); + MessagePack.register(SampleMapTypes.class); + MessagePack.register(SampleOptionalMapTypes.class); + MessagePack.register(SampleEnumFieldClass.class); + MessagePack.register(SampleOptionalEnumFieldClass.class); + MessagePack.register(FieldModifiersClass.class); + MessagePack.register(OptionalFieldModifiersClass.class); + MessagePack.register(BaseClass.class); + MessagePack.register(NestedClass.class); + MessagePack.register(BaseClass2.class); + MessagePack.register(OptionalBaseClass.class); + MessagePack.register(OptionalNestedClass.class); + MessagePack.register(OptionalBaseClass2.class); + MessagePack.register(SampleSubClass.class); + MessagePack.register(SampleSuperClass.class); + MessagePack.register(SampleOptionalSubClass.class); + MessagePack.register(SampleOptionalSuperClass.class); + MessagePack.register(BaseMessagePackableUnpackableClass.class); + MessagePack.register(MessagePackableUnpackableClass.class); + MessagePack.register(OptionalBaseMessagePackableUnpackableClass.class); + MessagePack.register(OptionalMessagePackableUnpackableClass.class); + } + + @Test + public void testPrimitiveTypeFields00() throws Exception { + PrimitiveTypeFieldsClass src = new PrimitiveTypeFieldsClass(); + src.f0 = (byte) 0; + src.f1 = 1; + src.f2 = 2; + src.f3 = 3; + src.f4 = 4; + src.f5 = 5; + src.f6 = false; + + byte[] raw = MessagePack.pack(src); + + PrimitiveTypeFieldsClass dst = + MessagePack.unpack(raw, PrimitiveTypeFieldsClass.class); + + assertEquals(src.f0, dst.f0); + assertEquals(src.f1, dst.f1); + assertEquals(src.f2, dst.f2); + assertEquals(src.f3, dst.f3); + assertEquals(src.f4, dst.f4); + assertEquals(src.f5, dst.f5); + assertEquals(src.f6, dst.f6); + } + + @Test + public void testPrimitiveTypeFields01() throws Exception { + PrimitiveTypeFieldsClass src = new PrimitiveTypeFieldsClass(); + + byte[] raw = MessagePack.pack(src); + + PrimitiveTypeFieldsClass dst = + MessagePack.unpack(raw, PrimitiveTypeFieldsClass.class); + assertEquals(src.f0, dst.f0); + assertEquals(src.f1, dst.f1); + assertEquals(src.f2, dst.f2); + assertEquals(src.f3, dst.f3); + assertEquals(src.f4, dst.f4); + assertEquals(src.f5, dst.f5); + assertEquals(src.f6, dst.f6); + } + + @Test + public void testPrimitiveTypeFields02() throws Exception { + PrimitiveTypeFieldsClass src = null; + + byte[] raw = MessagePack.pack(src); + + PrimitiveTypeFieldsClass dst = + MessagePack.unpack(raw, PrimitiveTypeFieldsClass.class); + assertEquals(src, dst); + } + + public static class PrimitiveTypeFieldsClass { + public byte f0; + public short f1; + public int f2; + public long f3; + public float f4; + public double f5; + public boolean f6; + + public PrimitiveTypeFieldsClass() { + } + } + + @Test + public void testOptionalPrimitiveTypeFields00() throws Exception { + OptionalPrimitiveTypeFieldsClass src = new OptionalPrimitiveTypeFieldsClass(); + src.f0 = (byte) 0; + src.f1 = 1; + src.f2 = 2; + src.f3 = 3; + src.f4 = 4; + src.f5 = 5; + src.f6 = false; + + byte[] raw = MessagePack.pack(src); + + PrimitiveTypeFieldsClass dst = + MessagePack.unpack(raw, PrimitiveTypeFieldsClass.class); + assertEquals(src.f0, dst.f0); + assertEquals(src.f1, dst.f1); + assertEquals(src.f2, dst.f2); + assertEquals(src.f3, dst.f3); + assertEquals(src.f4, dst.f4); + assertEquals(src.f5, dst.f5); + assertEquals(src.f6, dst.f6); + } + + @Test + public void testOptionalPrimitiveTypeFields01() throws Exception { + OptionalPrimitiveTypeFieldsClass src = new OptionalPrimitiveTypeFieldsClass(); + + byte[] raw = MessagePack.pack(src); + + OptionalPrimitiveTypeFieldsClass dst = + MessagePack.unpack(raw, OptionalPrimitiveTypeFieldsClass.class); + assertEquals(src.f0, dst.f0); + assertEquals(src.f1, dst.f1); + assertEquals(src.f2, dst.f2); + assertEquals(src.f3, dst.f3); + assertEquals(src.f4, dst.f4); + assertEquals(src.f5, dst.f5); + assertEquals(src.f6, dst.f6); + } + + @Test + public void testOptionalPrimitiveTypeFields02() throws Exception { + OptionalPrimitiveTypeFieldsClass src = null; + + byte[] raw = MessagePack.pack(src); + + OptionalPrimitiveTypeFieldsClass dst = + MessagePack.unpack(raw, OptionalPrimitiveTypeFieldsClass.class); + assertEquals(src, dst); + } + + public static class OptionalPrimitiveTypeFieldsClass { + @Optional + public byte f0; + @Optional + public short f1; + @Optional + public int f2; + @Optional + public long f3; + @Optional + public float f4; + @Optional + public double f5; + @Optional + public boolean f6; + + public OptionalPrimitiveTypeFieldsClass() { + } + } + + @Test + public void testGeneralReferenceTypeFieldsClass00() throws Exception { + GeneralReferenceTypeFieldsClass src = new GeneralReferenceTypeFieldsClass(); + src.f0 = 0; + src.f1 = 1; + src.f2 = 2; + src.f3 = (long) 3; + src.f4 = (float) 4; + src.f5 = (double) 5; + src.f6 = false; + src.f7 = new BigInteger("7"); + src.f8 = "8"; + src.f9 = new byte[] { 0x01, 0x02 }; + src.f10 = ByteBuffer.wrap("muga".getBytes()); + + byte[] raw = MessagePack.pack(src); + + GeneralReferenceTypeFieldsClass dst = + MessagePack.unpack(raw, GeneralReferenceTypeFieldsClass.class); + assertEquals(src.f0, dst.f0); + assertEquals(src.f1, dst.f1); + assertEquals(src.f2, dst.f2); + assertEquals(src.f3, dst.f3); + assertEquals(src.f4, dst.f4); + assertEquals(src.f5, dst.f5); + assertEquals(src.f6, dst.f6); + assertEquals(src.f7, dst.f7); + assertEquals(src.f8, dst.f8); + assertEquals(src.f9[0], dst.f9[0]); + assertEquals(src.f9[1], dst.f9[1]); + assertEquals(src.f10, dst.f10); + } + + @Test + public void testGeneralReferenceTypeFieldsClass01() throws Exception { + GeneralReferenceTypeFieldsClass src = null; + + byte[] raw = MessagePack.pack(src); + + GeneralReferenceTypeFieldsClass dst = + MessagePack.unpack(raw, GeneralReferenceTypeFieldsClass.class); + assertEquals(src, dst); + } + + public static class GeneralReferenceTypeFieldsClass { + public Byte f0; + public Short f1; + public Integer f2; + public Long f3; + public Float f4; + public Double f5; + public Boolean f6; + public BigInteger f7; + public String f8; + public byte[] f9; + public ByteBuffer f10; + + public GeneralReferenceTypeFieldsClass() { + } + } + + @Test + public void testGeneralOptionalReferenceTypeFieldsClass00() + throws Exception { + GeneralOptionalReferenceTypeFieldsClass src = new GeneralOptionalReferenceTypeFieldsClass(); + src.f0 = 0; + src.f1 = 1; + src.f2 = 2; + src.f3 = (long) 3; + src.f4 = (float) 4; + src.f5 = (double) 5; + src.f6 = false; + src.f7 = new BigInteger("7"); + src.f8 = "8"; + src.f9 = new byte[] { 0x01, 0x02 }; + src.f10 = ByteBuffer.wrap("muga".getBytes()); + + byte[] raw = MessagePack.pack(src); + + GeneralOptionalReferenceTypeFieldsClass dst = + MessagePack.unpack(raw, GeneralOptionalReferenceTypeFieldsClass.class); + assertEquals(src.f0, dst.f0); + assertEquals(src.f1, dst.f1); + assertEquals(src.f2, dst.f2); + assertEquals(src.f3, dst.f3); + assertEquals(src.f4, dst.f4); + assertEquals(src.f5, dst.f5); + assertEquals(src.f6, dst.f6); + assertEquals(src.f7, dst.f7); + assertEquals(src.f8, dst.f8); + assertEquals(src.f9[0], dst.f9[0]); + assertEquals(src.f9[1], dst.f9[1]); + assertEquals(src.f10, dst.f10); + } + + @Test + public void testGeneralOptionalReferenceTypeFieldsClass01() + throws Exception { + GeneralOptionalReferenceTypeFieldsClass src = new GeneralOptionalReferenceTypeFieldsClass(); + src.f0 = null; + src.f1 = null; + src.f2 = null; + src.f3 = null; + src.f4 = null; + src.f5 = null; + src.f6 = null; + src.f7 = null; + src.f8 = null; + src.f9 = null; + src.f10 = null; + + byte[] raw = MessagePack.pack(src); + + GeneralOptionalReferenceTypeFieldsClass dst = + MessagePack.unpack(raw, GeneralOptionalReferenceTypeFieldsClass.class); + assertEquals(src.f0, dst.f0); + assertEquals(src.f1, dst.f1); + assertEquals(src.f2, dst.f2); + assertEquals(src.f3, dst.f3); + assertEquals(src.f4, dst.f4); + assertEquals(src.f5, dst.f5); + assertEquals(src.f6, dst.f6); + assertEquals(src.f7, dst.f7); + assertEquals(src.f8, dst.f8); + assertEquals(src.f9, dst.f9); + assertEquals(src.f10, dst.f10); + } + + @Test + public void testGeneralOptionalReferenceTypeFieldsClass02() + throws Exception { + GeneralOptionalReferenceTypeFieldsClass src = null; + + byte[] raw = MessagePack.pack(src); + + GeneralOptionalReferenceTypeFieldsClass dst = + MessagePack.unpack(raw, GeneralOptionalReferenceTypeFieldsClass.class); + assertEquals(src, dst); + } + + public static class GeneralOptionalReferenceTypeFieldsClass { + @Optional + public Byte f0; + @Optional + public Short f1; + @Optional + public Integer f2; + @Optional + public Long f3; + @Optional + public Float f4; + @Optional + public Double f5; + @Optional + public Boolean f6; + @Optional + public BigInteger f7; + @Optional + public String f8; + @Optional + public byte[] f9; + @Optional + public ByteBuffer f10; + + public GeneralOptionalReferenceTypeFieldsClass() { + } + } + + @Test + public void testListTypes00() throws Exception { + SampleListTypes src = new SampleListTypes(); + src.f0 = new ArrayList<Integer>(); + src.f1 = new ArrayList<Integer>(); + src.f1.add(1); + src.f1.add(2); + src.f1.add(3); + src.f2 = new ArrayList<String>(); + src.f2.add("e1"); + src.f2.add("e2"); + src.f2.add("e3"); + src.f3 = new ArrayList<List<String>>(); + src.f3.add(src.f2); + src.f4 = new ArrayList<SampleListNestedType>(); + SampleListNestedType slnt = new SampleListNestedType(); + slnt.f0 = new byte[] { 0x01, 0x02 }; + slnt.f1 = "muga"; + src.f4.add(slnt); + src.f5 = new ArrayList<ByteBuffer>(); + src.f5.add(ByteBuffer.wrap("e1".getBytes())); + src.f5.add(ByteBuffer.wrap("e2".getBytes())); + src.f5.add(ByteBuffer.wrap("e3".getBytes())); + + byte[] raw = MessagePack.pack(src); + + SampleListTypes dst = + MessagePack.unpack(raw, SampleListTypes.class); + for (int i = 0; i < src.f1.size(); ++i) { + assertEquals(src.f1.get(i), dst.f1.get(i)); + } + assertEquals(src.f2.size(), dst.f2.size()); + for (int i = 0; i < src.f2.size(); ++i) { + assertEquals(src.f2.get(i), dst.f2.get(i)); + } + assertEquals(src.f3.size(), dst.f3.size()); + for (int i = 0; i < src.f3.size(); ++i) { + List<String> srclist = src.f3.get(i); + List<String> dstlist = dst.f3.get(i); + assertEquals(srclist.size(), dstlist.size()); + for (int j = 0; j < srclist.size(); ++j) { + assertEquals(srclist.get(j), dstlist.get(j)); + } + } + assertEquals(src.f4.size(), dst.f4.size()); + for (int i = 0; i < src.f4.size(); ++i) { + SampleListNestedType s = src.f4.get(i); + SampleListNestedType d = dst.f4.get(i); + assertEquals(s.f0[0], d.f0[0]); + assertEquals(s.f0[1], d.f0[1]); + assertEquals(s.f1, d.f1); + } + assertEquals(src.f5.size(), dst.f5.size()); + for (int i = 0; i < src.f5.size(); ++i) { + ByteBuffer s = src.f5.get(i); + ByteBuffer d = dst.f5.get(i); + assertEquals(s, d); + } + } + + @Test + public void testListTypes01() throws Exception { + SampleListTypes src = null; + + byte[] raw = MessagePack.pack(src); + + SampleListTypes dst = + MessagePack.unpack(raw, SampleListTypes.class); + assertEquals(src, dst); + } + + public static class SampleListTypes { + public List<Integer> f0; + public List<Integer> f1; + public List<String> f2; + public List<List<String>> f3; + public List<SampleListNestedType> f4; + public List<ByteBuffer> f5; + + public SampleListTypes() { + } + } + + @MessagePackMessage + public static class SampleListNestedType { + public byte[] f0; + public String f1; + + public SampleListNestedType() { + } + } + + @Test + public void testOptionalListTypes00() throws Exception { + SampleOptionalListTypes src = new SampleOptionalListTypes(); + src.f0 = new ArrayList<Integer>(); + src.f1 = new ArrayList<Integer>(); + src.f1.add(1); + src.f1.add(2); + src.f1.add(3); + src.f2 = new ArrayList<String>(); + src.f2.add("e1"); + src.f2.add("e2"); + src.f2.add("e3"); + src.f3 = new ArrayList<List<String>>(); + src.f3.add(src.f2); + src.f4 = new ArrayList<SampleOptionalListNestedType>(); + SampleOptionalListNestedType slnt = new SampleOptionalListNestedType(); + slnt.f0 = new byte[] { 0x01, 0x02 }; + slnt.f1 = "muga"; + src.f4.add(slnt); + src.f5 = new ArrayList<ByteBuffer>(); + src.f5.add(ByteBuffer.wrap("e1".getBytes())); + src.f5.add(ByteBuffer.wrap("e2".getBytes())); + src.f5.add(ByteBuffer.wrap("e3".getBytes())); + + byte[] raw = MessagePack.pack(src); + + SampleOptionalListTypes dst = + MessagePack.unpack(raw, SampleOptionalListTypes.class); + assertEquals(src.f0.size(), dst.f0.size()); + assertEquals(src.f1.size(), dst.f1.size()); + for (int i = 0; i < src.f1.size(); ++i) { + assertEquals(src.f1.get(i), dst.f1.get(i)); + } + assertEquals(src.f2.size(), dst.f2.size()); + for (int i = 0; i < src.f2.size(); ++i) { + assertEquals(src.f2.get(i), dst.f2.get(i)); + } + assertEquals(src.f3.size(), dst.f3.size()); + for (int i = 0; i < src.f3.size(); ++i) { + List<String> srclist = src.f3.get(i); + List<String> dstlist = dst.f3.get(i); + assertEquals(srclist.size(), dstlist.size()); + for (int j = 0; j < srclist.size(); ++j) { + assertEquals(srclist.get(j), dstlist.get(j)); + } + } + assertEquals(src.f4.size(), dst.f4.size()); + for (int i = 0; i < src.f4.size(); ++i) { + SampleOptionalListNestedType s = src.f4.get(i); + SampleOptionalListNestedType d = dst.f4.get(i); + assertEquals(s.f0[0], d.f0[0]); + assertEquals(s.f0[1], d.f0[1]); + assertEquals(s.f1, d.f1); + } + assertEquals(src.f5.size(), dst.f5.size()); + for (int i = 0; i < src.f5.size(); ++i) { + ByteBuffer s = src.f5.get(i); + ByteBuffer d = dst.f5.get(i); + assertEquals(s, d); + } + } + + @Test + public void testOptionalListTypes01() throws Exception { + SampleOptionalListTypes src = new SampleOptionalListTypes(); + src.f0 = new ArrayList<Integer>(); + src.f1 = null; + src.f2 = new ArrayList<String>(); + src.f3 = new ArrayList<List<String>>(); + src.f4 = null; + src.f5 = new ArrayList<ByteBuffer>(); + + byte[] raw = MessagePack.pack(src); + + SampleOptionalListTypes dst = + MessagePack.unpack(raw, SampleOptionalListTypes.class); + assertEquals(src.f0.size(), dst.f0.size()); + assertEquals(src.f1, dst.f1); + assertEquals(src.f2.size(), dst.f2.size()); + assertEquals(src.f3.size(), dst.f3.size()); + assertEquals(src.f4, dst.f4); + assertEquals(src.f5.size(), dst.f5.size()); + } + + @Test + public void testOptionalListTypes02() throws Exception { + SampleListTypes src = null; + + byte[] raw = MessagePack.pack(src); + + SampleListTypes dst = + MessagePack.unpack(raw, SampleListTypes.class); + assertEquals(src, dst); + } + + public static class SampleOptionalListTypes { + @Optional + public List<Integer> f0; + @Optional + public List<Integer> f1; + @Optional + public List<String> f2; + @Optional + public List<List<String>> f3; + @Optional + public List<SampleOptionalListNestedType> f4; + @Optional + public List<ByteBuffer> f5; + + public SampleOptionalListTypes() { + } + } + + @MessagePackMessage + public static class SampleOptionalListNestedType { + @Optional + public byte[] f0; + @Optional + public String f1; + + public SampleOptionalListNestedType() { + } + } + + @Test + public void testMapTypes00() throws Exception { + SampleMapTypes src = new SampleMapTypes(); + src.f0 = new HashMap<Integer, Integer>(); + src.f1 = new HashMap<Integer, Integer>(); + src.f1.put(1, 1); + src.f1.put(2, 2); + src.f1.put(3, 3); + src.f2 = new HashMap<String, Integer>(); + src.f2.put("k1", 1); + src.f2.put("k2", 2); + src.f2.put("k3", 3); + + byte[] raw = MessagePack.pack(src); + + SampleMapTypes dst = + MessagePack.unpack(raw, SampleMapTypes.class); + Iterator<Integer> srcf1 = src.f1.keySet().iterator(); + Iterator<Integer> dstf1 = dst.f1.keySet().iterator(); + while (srcf1.hasNext()) { + Integer s1 = srcf1.next(); + Integer d1 = dstf1.next(); + assertEquals(s1, d1); + assertEquals(src.f1.get(s1), dst.f1.get(d1)); + } + assertEquals(src.f2.size(), dst.f2.size()); + Iterator<String> srcf2 = src.f2.keySet().iterator(); + Iterator<String> dstf2 = dst.f2.keySet().iterator(); + while (srcf2.hasNext()) { + String s2 = srcf2.next(); + String d2 = dstf2.next(); + assertEquals(s2, d2); + assertEquals(src.f2.get(s2), dst.f2.get(d2)); + } + } + + @Test + public void testMapTypes01() throws Exception { + SampleMapTypes src = null; + + byte[] raw = MessagePack.pack(src); + + SampleMapTypes dst = + MessagePack.unpack(raw, SampleMapTypes.class); + assertEquals(src, dst); + } + + public static class SampleMapTypes { + public Map<Integer, Integer> f0; + public Map<Integer, Integer> f1; + public Map<String, Integer> f2; + + public SampleMapTypes() { + } + } + + @Test + public void testOptionalMapTypes00() throws Exception { + SampleOptionalMapTypes src = new SampleOptionalMapTypes(); + src.f0 = new HashMap<Integer, Integer>(); + src.f1 = new HashMap<Integer, Integer>(); + src.f1.put(1, 1); + src.f1.put(2, 2); + src.f1.put(3, 3); + src.f2 = new HashMap<String, Integer>(); + src.f2.put("k1", 1); + src.f2.put("k2", 2); + src.f2.put("k3", 3); + + byte[] raw = MessagePack.pack(src); + + SampleOptionalMapTypes dst = + MessagePack.unpack(raw, SampleOptionalMapTypes.class); + assertEquals(src.f0.size(), dst.f0.size()); + assertEquals(src.f1.size(), dst.f1.size()); + Iterator<Integer> srcf1 = src.f1.keySet().iterator(); + Iterator<Integer> dstf1 = dst.f1.keySet().iterator(); + while (srcf1.hasNext()) { + Integer s1 = srcf1.next(); + Integer d1 = dstf1.next(); + assertEquals(s1, d1); + assertEquals(src.f1.get(s1), dst.f1.get(d1)); + } + assertEquals(src.f2.size(), dst.f2.size()); + Iterator<String> srcf2 = src.f2.keySet().iterator(); + Iterator<String> dstf2 = dst.f2.keySet().iterator(); + while (srcf2.hasNext()) { + String s2 = srcf2.next(); + String d2 = dstf2.next(); + assertEquals(s2, d2); + assertEquals(src.f2.get(s2), dst.f2.get(d2)); + } + } + + @Test + public void testOptionalMapTypes01() throws Exception { + SampleOptionalMapTypes src = new SampleOptionalMapTypes(); + src.f0 = new HashMap<Integer, Integer>(); + src.f1 = null; + src.f2 = new HashMap<String, Integer>(); + + byte[] raw = MessagePack.pack(src); + + SampleOptionalMapTypes dst = + MessagePack.unpack(raw, SampleOptionalMapTypes.class); + assertEquals(src.f0.size(), dst.f0.size()); + assertEquals(src.f1, dst.f1); + assertEquals(src.f2.size(), dst.f2.size()); + } + + @Test + public void testOptionalMapTypes02() throws Exception { + SampleOptionalMapTypes src = null; + + byte[] raw = MessagePack.pack(src); + + SampleOptionalMapTypes dst = + MessagePack.unpack(raw, SampleOptionalMapTypes.class); + assertEquals(src, dst); + } + + public static class SampleOptionalMapTypes { + @Optional + public Map<Integer, Integer> f0; + @Optional + public Map<Integer, Integer> f1; + @Optional + public Map<String, Integer> f2; + + public SampleOptionalMapTypes() { + } + } + + @Test + public void testFinalClass() throws Exception { + try { + TemplateBuilder builder = BuilderSelectorRegistry.getInstance().select(FinalModifierClass.class); + Assert.assertNull(builder); + BuilderSelectorRegistry.getInstance().getForceBuilder().buildTemplate(FinalModifierClass.class); + assertTrue(true); + } catch (TemplateBuildException e) { + fail(); + } + assertTrue(true); + } + + public final static class FinalModifierClass { + } + + public abstract static class AbstractModifierClass { + } + + @Test + public void testInterfaceType00() throws Exception { + try { + TemplateBuilder builder = BuilderSelectorRegistry.getInstance().select(SampleInterface.class); + Assert.assertNull(builder); + BuilderSelectorRegistry.getInstance().getForceBuilder().buildTemplate(SampleInterface.class); + fail(); + } catch (TemplateBuildException e) { + assertTrue(true); + } + assertTrue(true); + } + + @Test + public void testInterfaceType01() throws Exception { + try { + TemplateBuilder builder = BuilderSelectorRegistry.getInstance().select(SampleInterface.class); + Assert.assertNull(builder); + BuilderSelectorRegistry.getInstance().getForceBuilder().buildTemplate(SampleInterface.class); + fail(); + } catch (TemplateBuildException e) { + assertTrue(true); + } + assertTrue(true); + } + + public interface SampleInterface { + } + + @Test + public void testEnumTypeForOrdinal00() throws Exception { + SampleEnumFieldClass src = new SampleEnumFieldClass(); + src.f0 = 0; + src.f1 = SampleEnum.ONE; + + byte[] raw = MessagePack.pack(src); + + SampleEnumFieldClass dst = + MessagePack.unpack(raw, SampleEnumFieldClass.class); + assertTrue(src.f1 == dst.f1); + } + + @Test + public void testEnumTypeForOrdinal01() throws Exception { + SampleEnumFieldClass src = null; + + byte[] raw = MessagePack.pack(src); + + SampleEnumFieldClass dst = + MessagePack.unpack(raw, SampleEnumFieldClass.class); + assertEquals(src, dst); + } + + public static class SampleEnumFieldClass { + public int f0; + + public SampleEnum f1; + + public SampleEnumFieldClass() { + } + } + + @MessagePackOrdinalEnum + public enum SampleEnum { + ONE, TWO, THREE; + } + + @Test + public void testOptionalEnumTypeForOrdinal00() throws Exception { + SampleOptionalEnumFieldClass src = new SampleOptionalEnumFieldClass(); + src.f0 = 0; + src.f1 = SampleOptionalEnum.ONE; + + byte[] raw = MessagePack.pack(src); + + SampleOptionalEnumFieldClass dst = + MessagePack.unpack(raw, SampleOptionalEnumFieldClass.class); + assertTrue(src.f0 == dst.f0); + assertTrue(src.f1 == dst.f1); + } + + @Test + public void testOptionalEnumTypeForOrdinal01() throws Exception { + SampleOptionalEnumFieldClass src = new SampleOptionalEnumFieldClass(); + src.f1 = null; + + byte[] raw = MessagePack.pack(src); + + SampleOptionalEnumFieldClass dst = + MessagePack.unpack(raw, SampleOptionalEnumFieldClass.class); + assertTrue(src.f0 == dst.f0); + assertEquals(src.f1, dst.f1); + } + + @Test + public void testOptionalEnumTypeForOrdinal02() throws Exception { + SampleEnumFieldClass src = null; + + byte[] raw = MessagePack.pack(src); + + SampleEnumFieldClass dst = + MessagePack.unpack(raw, SampleEnumFieldClass.class); + assertEquals(src, dst); + } + + public static class SampleOptionalEnumFieldClass { + @Optional + public int f0; + + @Optional + public SampleOptionalEnum f1; + + public SampleOptionalEnumFieldClass() { + } + } + + @MessagePackOrdinalEnum + public enum SampleOptionalEnum { + ONE, TWO, THREE; + } + + @Test + public void testFieldModifiers() throws Exception { + FieldModifiersClass src = new FieldModifiersClass(); + src.f0 = 0; + src.f2 = 2; + src.f3 = 3; + src.f4 = 4; + + byte[] raw = MessagePack.pack(src); + + FieldModifiersClass dst = + MessagePack.unpack(raw, FieldModifiersClass.class); + assertTrue(src.f1 == dst.f1); + assertTrue(src.f2 != dst.f2); + assertTrue(src.f3 != dst.f3); + assertTrue(src.f4 != dst.f4); + } + + public static class FieldModifiersClass { + public int f0; + public final int f1 = 1; + private int f2; + protected int f3; + int f4; + + public FieldModifiersClass() { + } + } + + @Test + public void testOptionalFieldModifiers() throws Exception { + OptionalFieldModifiersClass src = new OptionalFieldModifiersClass(); + src.f0 = 0; + src.f2 = 2; + src.f3 = 3; + src.f4 = 4; + + byte[] raw = MessagePack.pack(src); + + OptionalFieldModifiersClass dst = + MessagePack.unpack(raw, OptionalFieldModifiersClass.class); + assertTrue(src.f0 == dst.f0); + assertTrue(src.f1 == dst.f1); + assertTrue(src.f2 != dst.f2); + assertTrue(src.f3 != dst.f3); + assertTrue(src.f4 != dst.f4); + } + + public static class OptionalFieldModifiersClass { + @Optional + public int f0; + @Optional + public final int f1 = 1; + private int f2; + protected int f3; + int f4; + + public OptionalFieldModifiersClass() { + } + } + + @Test + public void testNestedFieldClass00() throws Exception { + BaseClass src = new BaseClass(); + NestedClass src2 = new NestedClass(); + src.f0 = 0; + src2.f2 = 2; + src.f1 = src2; + + byte[] raw = MessagePack.pack(src); + + BaseClass dst = + MessagePack.unpack(raw, BaseClass.class); + assertTrue(src.f0 == dst.f0); + assertTrue(src.f1.f2 == dst.f1.f2); + } + + @Test + public void testNestedFieldClass01() throws Exception { + BaseClass src = null; + + byte[] raw = MessagePack.pack(src); + + BaseClass dst = + MessagePack.unpack(raw, BaseClass.class); + assertEquals(src, dst); + } + + public static class BaseClass { + public int f0; + public NestedClass f1; + + public BaseClass() { + } + } + + public static class NestedClass { + public int f2; + + public NestedClass() { + } + } + + @Test + public void testOptionalNestedFieldClass00() throws Exception { + OptionalBaseClass src = new OptionalBaseClass(); + OptionalNestedClass src2 = new OptionalNestedClass(); + src.f0 = 0; + src2.f2 = 2; + src.f1 = src2; + + byte[] raw = MessagePack.pack(src); + + OptionalBaseClass dst = + MessagePack.unpack(raw, OptionalBaseClass.class); + assertTrue(src.f0 == dst.f0); + assertTrue(src.f1.f2 == dst.f1.f2); + } + + @Test + public void testOptionalNestedFieldClass01() throws Exception { + OptionalBaseClass src = new OptionalBaseClass(); + src.f1 = null; + + byte[] raw = MessagePack.pack(src); + + OptionalBaseClass dst = + MessagePack.unpack(raw, OptionalBaseClass.class); + assertTrue(src.f0 == dst.f0); + assertTrue(src.f1 == dst.f1); + } + + @Test + public void testOptionalNestedFieldClass02() throws Exception { + OptionalBaseClass src = null; + + byte[] raw = MessagePack.pack(src); + + OptionalBaseClass dst = + MessagePack.unpack(raw, OptionalBaseClass.class); + assertEquals(src, dst); + } + + public static class OptionalBaseClass { + @Optional + public int f0; + @Optional + public OptionalNestedClass f1; + + public OptionalBaseClass() { + } + } + + public static class OptionalNestedClass { + @Optional + public int f2; + + public OptionalNestedClass() { + } + } + + @Test + public void testMessagePackMessageFieldClass00() throws Exception { + BaseClass2 src = new BaseClass2(); + MessagePackMessageClass2 src2 = new MessagePackMessageClass2(); + src.f0 = 0; + src2.f2 = 2; + src.f1 = src2; + + byte[] raw = MessagePack.pack(src); + + BaseClass2 dst = + MessagePack.unpack(raw, BaseClass2.class); + assertTrue(src.f0 == dst.f0); + assertTrue(src.f1.f2 == dst.f1.f2); + } + + @Test + public void testMessagePackMessageFieldClass01() throws Exception { + BaseClass2 src = null; + + byte[] raw = MessagePack.pack(src); + + BaseClass2 dst = + MessagePack.unpack(raw, BaseClass2.class); + assertEquals(src, dst); + } + + public static class BaseClass2 { + public int f0; + public MessagePackMessageClass2 f1; + + public BaseClass2() { + } + } + + @MessagePackMessage + public static class MessagePackMessageClass2 { + public int f2; + + public MessagePackMessageClass2() { + } + } + + @Test + public void testOptionalMessagePackMessageFieldClass00() throws Exception { + OptionalBaseClass2 src = new OptionalBaseClass2(); + OptionalMessagePackMessageClass2 src2 = new OptionalMessagePackMessageClass2(); + src.f0 = 0; + src2.f2 = 2; + src.f1 = src2; + + byte[] raw = MessagePack.pack(src); + + OptionalBaseClass2 dst = + MessagePack.unpack(raw, OptionalBaseClass2.class); + assertTrue(src.f0 == dst.f0); + assertTrue(src.f1.f2 == dst.f1.f2); + } + + @Test + public void testOptionalMessagePackMessageFieldClass01() throws Exception { + OptionalBaseClass2 src = new OptionalBaseClass2(); + src.f1 = null; + + byte[] raw = MessagePack.pack(src); + + OptionalBaseClass2 dst = + MessagePack.unpack(raw, OptionalBaseClass2.class); + assertTrue(src.f0 == dst.f0); + assertEquals(src.f1, dst.f1); + } + + @Test + public void testOptionalMessagePackMessageFieldClass02() throws Exception { + OptionalBaseClass2 src = null; + + byte[] raw = MessagePack.pack(src); + + OptionalBaseClass2 dst = + MessagePack.unpack(raw, OptionalBaseClass2.class); + assertEquals(src, dst); + } + + public static class OptionalBaseClass2 { + @Optional + public int f0; + @Optional + public OptionalMessagePackMessageClass2 f1; + + public OptionalBaseClass2() { + } + } + + @MessagePackMessage + public static class OptionalMessagePackMessageClass2 { + @Optional + public int f2; + + public OptionalMessagePackMessageClass2() { + } + } + + @Test + public void testExtendedClass00() throws Exception { + SampleSubClass src = new SampleSubClass(); + src.f0 = 0; + src.f2 = 2; + src.f3 = 3; + src.f4 = 4; + src.f5 = 5; + src.f8 = 8; + src.f9 = 9; + + byte[] raw = MessagePack.pack(src); + + SampleSubClass dst = + MessagePack.unpack(raw, SampleSubClass.class); + assertTrue(src.f0 == dst.f0); + assertTrue(src.f1 == dst.f1); + assertTrue(src.f2 != dst.f2); + assertTrue(src.f3 != dst.f3); + assertTrue(src.f4 != dst.f4); + assertTrue(src.f5 == dst.f5); + assertTrue(src.f6 == dst.f6); + assertTrue(src.f8 != dst.f8); + assertTrue(src.f9 != dst.f9); + } + + @Test + public void testExtendedClass01() throws Exception { + SampleSubClass src = null; + + byte[] raw = MessagePack.pack(src); + + SampleSubClass dst = + MessagePack.unpack(raw, SampleSubClass.class); + assertEquals(src, dst); + } + + public static class SampleSubClass extends SampleSuperClass { + public int f0; + public final int f1 = 1; + private int f2; + protected int f3; + int f4; + + public SampleSubClass() { + } + } + + public static class SampleSuperClass { + public int f5; + public final int f6 = 2; + @SuppressWarnings("unused") + private int f7; + protected int f8; + int f9; + + public SampleSuperClass() { + } + } + + @Test + public void testOptionalExtendedClass00() throws Exception { + SampleOptionalSubClass src = new SampleOptionalSubClass(); + src.f0 = 0; + src.f2 = 2; + src.f3 = 3; + src.f4 = 4; + src.f5 = 5; + src.f8 = 8; + src.f9 = 9; + + byte[] raw = MessagePack.pack(src); + + SampleOptionalSubClass dst = + MessagePack.unpack(raw, SampleOptionalSubClass.class); + assertTrue(src.f0 == dst.f0); + assertTrue(src.f1 == dst.f1); + assertTrue(src.f2 != dst.f2); + assertTrue(src.f3 != dst.f3); + assertTrue(src.f4 != dst.f4); + assertTrue(src.f5 == dst.f5); + assertTrue(src.f6 == dst.f6); + assertTrue(src.f8 != dst.f8); + assertTrue(src.f9 != dst.f9); + } + + @Test + public void testOptionalExtendedClass01() throws Exception { + SampleOptionalSubClass src = null; + + byte[] raw = MessagePack.pack(src); + + SampleOptionalSubClass dst = + MessagePack.unpack(raw, SampleOptionalSubClass.class); + assertEquals(src, dst); + } + + public static class SampleOptionalSubClass extends SampleOptionalSuperClass { + @Optional + public int f0; + public final int f1 = 1; + private int f2; + protected int f3; + int f4; + + public SampleOptionalSubClass() { + } + } + + public static class SampleOptionalSuperClass { + @Optional + public int f5; + public final int f6 = 2; + @SuppressWarnings("unused") + private int f7; + protected int f8; + int f9; + + public SampleOptionalSuperClass() { + } + } + + @Test + public void testMessagePackableUnpackableClass00() throws Exception { + BaseMessagePackableUnpackableClass src = new BaseMessagePackableUnpackableClass(); + MessagePackableUnpackableClass src1 = new MessagePackableUnpackableClass(); + List<MessagePackableUnpackableClass> src2 = new ArrayList<MessagePackableUnpackableClass>(); + src1.f0 = 0; + src1.f1 = 1; + src.f0 = src1; + src.f1 = 1; + src2.add(src1); + src.f2 = src2; + + byte[] raw = MessagePack.pack(src); + + BaseMessagePackableUnpackableClass dst = + MessagePack.unpack(raw, BaseMessagePackableUnpackableClass.class); + assertEquals(src.f0.f0, dst.f0.f0); + assertEquals(src.f0.f1, dst.f0.f1); + assertEquals(src.f1, dst.f1); + assertEquals(src.f2.size(), dst.f2.size()); + assertEquals(src.f2.get(0).f0, dst.f2.get(0).f0); + assertEquals(src.f2.get(0).f1, dst.f2.get(0).f1); + } + + @Test + public void testMessagePackableUnpackableClass01() throws Exception { + BaseMessagePackableUnpackableClass src = null; + + byte[] raw = MessagePack.pack(src); + + BaseMessagePackableUnpackableClass dst = + MessagePack.unpack(raw, BaseMessagePackableUnpackableClass.class); + assertEquals(src, dst); + } + + public static class BaseMessagePackableUnpackableClass { + public MessagePackableUnpackableClass f0; + public int f1; + public List<MessagePackableUnpackableClass> f2; + + public BaseMessagePackableUnpackableClass() { + } + } + + public static class MessagePackableUnpackableClass implements + MessagePackable, MessageUnpackable { + public int f0; + public int f1; + + public MessagePackableUnpackableClass() { + } + + @Override + public void messagePack(Packer packer) throws IOException { + packer.packArray(2); + packer.pack(f0); + packer.pack(f1); + } + + @Override + public void messageUnpack(Unpacker unpacker) throws IOException, + MessageTypeException { + if (unpacker.tryUnpackNull()) { + return; + } + unpacker.unpackArray(); + f0 = unpacker.unpackInt(); + f1 = unpacker.unpackInt(); + } + } + + @Test + public void testOptionalMessagePackableUnpackableClass00() throws Exception { + OptionalBaseMessagePackableUnpackableClass src = new OptionalBaseMessagePackableUnpackableClass(); + OptionalMessagePackableUnpackableClass src1 = new OptionalMessagePackableUnpackableClass(); + List<OptionalMessagePackableUnpackableClass> src2 = new ArrayList<OptionalMessagePackableUnpackableClass>(); + src1.f0 = 0; + src1.f1 = 1; + src.f0 = src1; + src.f1 = 1; + src2.add(src1); + src.f2 = src2; + + byte[] raw = MessagePack.pack(src); + + OptionalBaseMessagePackableUnpackableClass dst = + MessagePack.unpack(raw, OptionalBaseMessagePackableUnpackableClass.class); + assertEquals(src.f0.f0, dst.f0.f0); + assertEquals(src.f0.f1, dst.f0.f1); + assertEquals(src.f1, dst.f1); + assertEquals(src.f2.size(), dst.f2.size()); + assertEquals(src.f2.get(0).f0, dst.f2.get(0).f0); + assertEquals(src.f2.get(0).f1, dst.f2.get(0).f1); + } + + @Test + public void testOptionalMessagePackableUnpackableClass01() throws Exception { + OptionalBaseMessagePackableUnpackableClass src = new OptionalBaseMessagePackableUnpackableClass(); + src.f0 = null; + src.f1 = 1; + src.f2 = null; + + byte[] raw = MessagePack.pack(src); + + OptionalBaseMessagePackableUnpackableClass dst = + MessagePack.unpack(raw, OptionalBaseMessagePackableUnpackableClass.class); + assertEquals(src.f0, dst.f0); + assertEquals(src.f1, dst.f1); + assertEquals(src.f2, dst.f2); + } + + @Test + public void testOptionalMessagePackableUnpackableClass02() throws Exception { + OptionalBaseMessagePackableUnpackableClass src = null; + + byte[] raw = MessagePack.pack(src); + + OptionalBaseMessagePackableUnpackableClass dst = + MessagePack.unpack(raw, OptionalBaseMessagePackableUnpackableClass.class); + assertEquals(src, dst); + } + + public static class OptionalBaseMessagePackableUnpackableClass { + @Optional + public OptionalMessagePackableUnpackableClass f0; + @Optional + public int f1; + @Optional + public List<OptionalMessagePackableUnpackableClass> f2; + + public OptionalBaseMessagePackableUnpackableClass() { + } + } + + public static class OptionalMessagePackableUnpackableClass implements + MessagePackable, MessageUnpackable { + @Optional + public int f0; + @Optional + public int f1; + + public OptionalMessagePackableUnpackableClass() { + } + + @Override + public void messagePack(Packer packer) throws IOException { + packer.packArray(2); + packer.pack(f0); + packer.pack(f1); + } + + @Override + public void messageUnpack(Unpacker unpacker) throws IOException, + MessageTypeException { + if (unpacker.tryUnpackNull()) { + return; + } + unpacker.unpackArray(); + f0 = unpacker.unpackInt(); + f1 = unpacker.unpackInt(); + } + } +} + diff --git a/java/src/test/java/org/msgpack/template/TestTemplateBuilderJavaBeansPackUnpack.java b/java/src/test/java/org/msgpack/template/TestTemplateBuilderJavaBeansPackUnpack.java new file mode 100644 index 00000000..1310cddb --- /dev/null +++ b/java/src/test/java/org/msgpack/template/TestTemplateBuilderJavaBeansPackUnpack.java @@ -0,0 +1,2234 @@ +package org.msgpack.template; + +import java.io.ByteArrayInputStream; +import java.io.ByteArrayOutputStream; +import java.io.IOException; +import java.math.BigInteger; +import java.nio.ByteBuffer; +import java.util.ArrayList; +import java.util.HashMap; +import java.util.Iterator; +import java.util.List; +import java.util.Map; + +import org.hamcrest.CoreMatchers; +import org.junit.Ignore; +import org.junit.Test; + +import org.msgpack.MessagePack; +import org.msgpack.MessagePackable; +import org.msgpack.MessagePacker; +import org.msgpack.MessageTypeException; +import org.msgpack.MessageUnpackable; +import org.msgpack.Packer; +import org.msgpack.Template; +import org.msgpack.Unpacker; +import org.msgpack.annotation.MessagePackBeans; +import org.msgpack.annotation.MessagePackMessage; +import org.msgpack.annotation.MessagePackOrdinalEnum; +import org.msgpack.annotation.Optional; +import org.msgpack.template.TestTemplateBuilderPackConvert.SampleInterface; +import org.msgpack.template.builder.BuilderSelectorRegistry; +import org.msgpack.template.builder.TemplateBuilder; + +import org.junit.Assert; +import junit.framework.TestCase; +import static org.hamcrest.CoreMatchers.*; + +public class TestTemplateBuilderJavaBeansPackUnpack extends TestCase { + static { + MessagePack.register(PrimitiveTypeFieldsClass.class); + MessagePack.register(OptionalPrimitiveTypeFieldsClass.class); + MessagePack.register(GeneralReferenceTypeFieldsClass.class); + MessagePack.register(GeneralOptionalReferenceTypeFieldsClass.class); + MessagePack.register(SampleListTypes.class); + MessagePack.register(SampleOptionalListTypes.class); + MessagePack.register(SampleMapTypes.class); + MessagePack.register(SampleOptionalMapTypes.class); + MessagePack.register(SampleEnumFieldClass.class); + MessagePack.register(SampleOptionalEnumFieldClass.class); + MessagePack.register(FieldModifiersClass.class); + MessagePack.register(OptionalFieldModifiersClass.class); + MessagePack.register(BaseClass.class); + MessagePack.register(NestedClass.class); + MessagePack.register(BaseClass2.class); + MessagePack.register(OptionalBaseClass.class); + MessagePack.register(OptionalNestedClass.class); + MessagePack.register(OptionalBaseClass2.class); + MessagePack.register(SampleSubClass.class); + MessagePack.register(SampleSuperClass.class); + MessagePack.register(SampleOptionalSubClass.class); + MessagePack.register(SampleOptionalSuperClass.class); + MessagePack.register(BaseMessagePackableUnpackableClass.class); + MessagePack.register(MessagePackableUnpackableClass.class); + MessagePack.register(OptionalBaseMessagePackableUnpackableClass.class); + MessagePack.register(OptionalMessagePackableUnpackableClass.class); + } + + @Test + public void testPrimitiveTypeFields00() throws Exception { + PrimitiveTypeFieldsClass src = new PrimitiveTypeFieldsClass(); + src.f0 = (byte) 0; + src.f1 = 1; + src.f2 = 2; + src.f3 = 3; + src.f4 = 4; + src.f5 = 5; + src.f6 = false; + + byte[] raw = MessagePack.pack(src); + + PrimitiveTypeFieldsClass dst = + MessagePack.unpack(raw, PrimitiveTypeFieldsClass.class); + assertEquals(src.f0, dst.f0); + assertEquals(src.f1, dst.f1); + assertEquals(src.f2, dst.f2); + assertEquals(src.f3, dst.f3); + assertEquals(src.f4, dst.f4); + assertEquals(src.f5, dst.f5); + assertEquals(src.f6, dst.f6); + } + + @Test + public void testPrimitiveTypeFields01() throws Exception { + PrimitiveTypeFieldsClass src = new PrimitiveTypeFieldsClass(); + + byte[] raw = MessagePack.pack(src); + + PrimitiveTypeFieldsClass dst = + MessagePack.unpack(raw, PrimitiveTypeFieldsClass.class); + assertEquals(src.f0, dst.f0); + assertEquals(src.f1, dst.f1); + assertEquals(src.f2, dst.f2); + assertEquals(src.f3, dst.f3); + assertEquals(src.f4, dst.f4); + assertEquals(src.f5, dst.f5); + assertEquals(src.f6, dst.f6); + } + + @Test + public void testPrimitiveTypeFields02() throws Exception { + PrimitiveTypeFieldsClass src = null; + + byte[] raw = MessagePack.pack(src); + + PrimitiveTypeFieldsClass dst = + MessagePack.unpack(raw, PrimitiveTypeFieldsClass.class); + assertEquals(src, dst); + } + + @MessagePackBeans + public static class PrimitiveTypeFieldsClass { + byte f0; + short f1; + int f2; + long f3; + float f4; + double f5; + boolean f6; + + public byte getF0() { + return f0; + } + + public void setF0(byte f0) { + this.f0 = f0; + } + + public short getF1() { + return f1; + } + + public void setF1(short f1) { + this.f1 = f1; + } + + public int getF2() { + return f2; + } + + public void setF2(int f2) { + this.f2 = f2; + } + + public long getF3() { + return f3; + } + + public void setF3(long f3) { + this.f3 = f3; + } + + public float getF4() { + return f4; + } + + public void setF4(float f4) { + this.f4 = f4; + } + + public double getF5() { + return f5; + } + + public void setF5(double f5) { + this.f5 = f5; + } + + public boolean isF6() { + return f6; + } + + public void setF6(boolean f6) { + this.f6 = f6; + } + + public PrimitiveTypeFieldsClass() { + } + } + + @Test + public void testOptionalPrimitiveTypeFields00() throws Exception { + OptionalPrimitiveTypeFieldsClass src = new OptionalPrimitiveTypeFieldsClass(); + src.f0 = (byte) 0; + src.f1 = 1; + src.f2 = 2; + src.f3 = 3; + src.f4 = 4; + src.f5 = 5; + src.f6 = false; + + byte[] raw = MessagePack.pack(src); + + PrimitiveTypeFieldsClass dst = + MessagePack.unpack(raw, PrimitiveTypeFieldsClass.class); + assertEquals(src.f0, dst.f0); + assertEquals(src.f1, dst.f1); + assertEquals(src.f2, dst.f2); + assertEquals(src.f3, dst.f3); + assertEquals(src.f4, dst.f4); + assertEquals(src.f5, dst.f5); + assertEquals(src.f6, dst.f6); + } + + @Test + public void testOptionalPrimitiveTypeFields01() throws Exception { + OptionalPrimitiveTypeFieldsClass src = new OptionalPrimitiveTypeFieldsClass(); + + byte[] raw = MessagePack.pack(src); + + OptionalPrimitiveTypeFieldsClass dst = + MessagePack.unpack(raw, OptionalPrimitiveTypeFieldsClass.class); + assertEquals(src.f0, dst.f0); + assertEquals(src.f1, dst.f1); + assertEquals(src.f2, dst.f2); + assertEquals(src.f3, dst.f3); + assertEquals(src.f4, dst.f4); + assertEquals(src.f5, dst.f5); + assertEquals(src.f6, dst.f6); + } + + @Test + public void testOptionalPrimitiveTypeFields02() throws Exception { + OptionalPrimitiveTypeFieldsClass src = null; + + byte[] raw = MessagePack.pack(src); + + OptionalPrimitiveTypeFieldsClass dst = + MessagePack.unpack(raw, OptionalPrimitiveTypeFieldsClass.class); + assertEquals(src, dst); + } + + @MessagePackBeans + public static class OptionalPrimitiveTypeFieldsClass { + @Optional + public byte f0; + @Optional + public short f1; + @Optional + public int f2; + @Optional + public long f3; + @Optional + public float f4; + @Optional + public double f5; + @Optional + public boolean f6; + + @Optional + public byte getF0() { + return f0; + } + + @Optional + public void setF0(byte f0) { + this.f0 = f0; + } + + @Optional + public short getF1() { + return f1; + } + + public void setF1(short f1) { + this.f1 = f1; + } + + public int getF2() { + return f2; + } + + @Optional + public void setF2(int f2) { + this.f2 = f2; + } + + @Optional + public long getF3() { + return f3; + } + + public void setF3(long f3) { + this.f3 = f3; + } + + @Optional + public float getF4() { + return f4; + } + + public void setF4(float f4) { + this.f4 = f4; + } + + @Optional + public double getF5() { + return f5; + } + + public void setF5(double f5) { + this.f5 = f5; + } + + @Optional + public boolean isF6() { + return f6; + } + + public void setF6(boolean f6) { + this.f6 = f6; + } + + public OptionalPrimitiveTypeFieldsClass() { + } + } + + @Test + public void testGeneralReferenceTypeFieldsClass00() throws Exception { + GeneralReferenceTypeFieldsClass src = new GeneralReferenceTypeFieldsClass(); + src.f0 = 0; + src.f1 = 1; + src.f2 = 2; + src.f3 = (long) 3; + src.f4 = (float) 4; + src.f5 = (double) 5; + src.f6 = false; + src.f7 = new BigInteger("7"); + src.f8 = "8"; + src.f9 = new byte[] { 0x01, 0x02 }; + src.f10 = ByteBuffer.wrap("muga".getBytes()); + + byte[] raw = MessagePack.pack(src); + + GeneralReferenceTypeFieldsClass dst = + MessagePack.unpack(raw, GeneralReferenceTypeFieldsClass.class); + assertEquals(src.f0, dst.f0); + assertEquals(src.f1, dst.f1); + assertEquals(src.f2, dst.f2); + assertEquals(src.f3, dst.f3); + assertEquals(src.f4, dst.f4); + assertEquals(src.f5, dst.f5); + assertEquals(src.f6, dst.f6); + assertEquals(src.f7, dst.f7); + assertEquals(src.f8, dst.f8); + assertEquals(src.f9[0], dst.f9[0]); + assertEquals(src.f9[1], dst.f9[1]); + assertEquals(src.f10, dst.f10); + } + + @Test + public void testGeneralReferenceTypeFieldsClass01() throws Exception { + GeneralReferenceTypeFieldsClass src = null; + + byte[] raw = MessagePack.pack(src); + + GeneralReferenceTypeFieldsClass dst = + MessagePack.unpack(raw, GeneralReferenceTypeFieldsClass.class); + assertEquals(src, dst); + } + + @MessagePackBeans + public static class GeneralReferenceTypeFieldsClass { + public Byte f0; + public Short f1; + public Integer f2; + public Long f3; + public Float f4; + public Double f5; + public Boolean f6; + public BigInteger f7; + public String f8; + public byte[] f9; + public ByteBuffer f10; + + public Byte getF0() { + return f0; + } + + public void setF0(Byte f0) { + this.f0 = f0; + } + + public Short getF1() { + return f1; + } + + public void setF1(Short f1) { + this.f1 = f1; + } + + public Integer getF2() { + return f2; + } + + public void setF2(Integer f2) { + this.f2 = f2; + } + + public Long getF3() { + return f3; + } + + public void setF3(Long f3) { + this.f3 = f3; + } + + public Float getF4() { + return f4; + } + + public void setF4(Float f4) { + this.f4 = f4; + } + + public Double getF5() { + return f5; + } + + public void setF5(Double f5) { + this.f5 = f5; + } + + public Boolean getF6() { + return f6; + } + + public void setF6(Boolean f6) { + this.f6 = f6; + } + + public BigInteger getF7() { + return f7; + } + + public void setF7(BigInteger f7) { + this.f7 = f7; + } + + public String getF8() { + return f8; + } + + public void setF8(String f8) { + this.f8 = f8; + } + + public byte[] getF9() { + return f9; + } + + public void setF9(byte[] f9) { + this.f9 = f9; + } + + public ByteBuffer getF10() { + return f10; + } + + public void setF10(ByteBuffer f10) { + this.f10 = f10; + } + + public GeneralReferenceTypeFieldsClass() { + } + } + + @Test + public void testGeneralOptionalReferenceTypeFieldsClass00() + throws Exception { + GeneralOptionalReferenceTypeFieldsClass src = new GeneralOptionalReferenceTypeFieldsClass(); + src.f0 = 0; + src.f1 = 1; + src.f2 = 2; + src.f3 = (long) 3; + src.f4 = (float) 4; + src.f5 = (double) 5; + src.f6 = false; + src.f7 = new BigInteger("7"); + src.f8 = "8"; + src.f9 = new byte[] { 0x01, 0x02 }; + src.f10 = ByteBuffer.wrap("muga".getBytes()); + + byte[] raw = MessagePack.pack(src); + + GeneralOptionalReferenceTypeFieldsClass dst = + MessagePack.unpack(raw, GeneralOptionalReferenceTypeFieldsClass.class); + assertEquals(src.f0, dst.f0); + assertEquals(src.f1, dst.f1); + assertEquals(src.f2, dst.f2); + assertEquals(src.f3, dst.f3); + assertEquals(src.f4, dst.f4); + assertEquals(src.f5, dst.f5); + assertEquals(src.f6, dst.f6); + assertEquals(src.f7, dst.f7); + assertEquals(src.f8, dst.f8); + assertEquals(src.f9[0], dst.f9[0]); + assertEquals(src.f9[1], dst.f9[1]); + assertEquals(src.f10, dst.f10); + } + + @Test + public void testGeneralOptionalReferenceTypeFieldsClass01() + throws Exception { + GeneralOptionalReferenceTypeFieldsClass src = new GeneralOptionalReferenceTypeFieldsClass(); + src.f0 = null; + src.f1 = null; + src.f2 = null; + src.f3 = null; + src.f4 = null; + src.f5 = null; + src.f6 = null; + src.f7 = null; + src.f8 = null; + src.f9 = null; + src.f10 = null; + + byte[] raw = MessagePack.pack(src); + + GeneralOptionalReferenceTypeFieldsClass dst = + MessagePack.unpack(raw, GeneralOptionalReferenceTypeFieldsClass.class); + assertEquals(src.f0, dst.f0); + assertEquals(src.f1, dst.f1); + assertEquals(src.f2, dst.f2); + assertEquals(src.f3, dst.f3); + assertEquals(src.f4, dst.f4); + assertEquals(src.f5, dst.f5); + assertEquals(src.f6, dst.f6); + assertEquals(src.f7, dst.f7); + assertEquals(src.f8, dst.f8); + assertEquals(src.f9, dst.f9); + assertEquals(src.f10, dst.f10); + } + + @Test + public void testGeneralOptionalReferenceTypeFieldsClass02() + throws Exception { + GeneralOptionalReferenceTypeFieldsClass src = null; + + byte[] raw = MessagePack.pack(src); + + GeneralOptionalReferenceTypeFieldsClass dst = + MessagePack.unpack(raw, GeneralOptionalReferenceTypeFieldsClass.class); + assertEquals(src, dst); + } + + @MessagePackBeans + public static class GeneralOptionalReferenceTypeFieldsClass { + @Optional + public Byte f0; + @Optional + public Short f1; + @Optional + public Integer f2; + @Optional + public Long f3; + @Optional + public Float f4; + @Optional + public Double f5; + @Optional + public Boolean f6; + @Optional + public BigInteger f7; + @Optional + public String f8; + @Optional + public byte[] f9; + @Optional + public ByteBuffer f10; + + @Optional + public Byte getF0() { + return f0; + } + + @Optional + public void setF0(Byte f0) { + this.f0 = f0; + } + + @Optional + public Short getF1() { + return f1; + } + + public void setF1(Short f1) { + this.f1 = f1; + } + + public Integer getF2() { + return f2; + } + + @Optional + public void setF2(Integer f2) { + this.f2 = f2; + } + + @Optional + public Long getF3() { + return f3; + } + + public void setF3(Long f3) { + this.f3 = f3; + } + + @Optional + public Float getF4() { + return f4; + } + + public void setF4(Float f4) { + this.f4 = f4; + } + + @Optional + public Double getF5() { + return f5; + } + + public void setF5(Double f5) { + this.f5 = f5; + } + + @Optional + public Boolean getF6() { + return f6; + } + + public void setF6(Boolean f6) { + this.f6 = f6; + } + + @Optional + public BigInteger getF7() { + return f7; + } + + public void setF7(BigInteger f7) { + this.f7 = f7; + } + + @Optional + public String getF8() { + return f8; + } + + public void setF8(String f8) { + this.f8 = f8; + } + + @Optional + public byte[] getF9() { + return f9; + } + + public void setF9(byte[] f9) { + this.f9 = f9; + } + + @Optional + public ByteBuffer getF10() { + return f10; + } + + public void setF10(ByteBuffer f10) { + this.f10 = f10; + } + + public GeneralOptionalReferenceTypeFieldsClass() { + } + } + + @Test + public void testListTypes00() throws Exception { + SampleListTypes src = new SampleListTypes(); + src.f0 = new ArrayList<Integer>(); + src.f1 = new ArrayList<Integer>(); + src.f1.add(1); + src.f1.add(2); + src.f1.add(3); + src.f2 = new ArrayList<String>(); + src.f2.add("e1"); + src.f2.add("e2"); + src.f2.add("e3"); + src.f3 = new ArrayList<List<String>>(); + src.f3.add(src.f2); + src.f4 = new ArrayList<SampleListNestedType>(); + SampleListNestedType slnt = new SampleListNestedType(); + slnt.f0 = new byte[] { 0x01, 0x02 }; + slnt.f1 = "muga"; + src.f4.add(slnt); + src.f5 = new ArrayList<ByteBuffer>(); + src.f5.add(ByteBuffer.wrap("e1".getBytes())); + src.f5.add(ByteBuffer.wrap("e2".getBytes())); + src.f5.add(ByteBuffer.wrap("e3".getBytes())); + + byte[] raw = MessagePack.pack(src); + + SampleListTypes dst = + MessagePack.unpack(raw, SampleListTypes.class); + for (int i = 0; i < src.f1.size(); ++i) { + assertEquals(src.f1.get(i), dst.f1.get(i)); + } + assertEquals(src.f2.size(), dst.f2.size()); + for (int i = 0; i < src.f2.size(); ++i) { + assertEquals(src.f2.get(i), dst.f2.get(i)); + } + assertEquals(src.f3.size(), dst.f3.size()); + for (int i = 0; i < src.f3.size(); ++i) { + List<String> srclist = src.f3.get(i); + List<String> dstlist = dst.f3.get(i); + assertEquals(srclist.size(), dstlist.size()); + for (int j = 0; j < srclist.size(); ++j) { + assertEquals(srclist.get(j), dstlist.get(j)); + } + } + assertEquals(src.f4.size(), dst.f4.size()); + for (int i = 0; i < src.f4.size(); ++i) { + SampleListNestedType s = src.f4.get(i); + SampleListNestedType d = dst.f4.get(i); + assertEquals(s.f0[0], d.f0[0]); + assertEquals(s.f0[1], d.f0[1]); + assertEquals(s.f1, d.f1); + } + assertEquals(src.f5.size(), dst.f5.size()); + for (int i = 0; i < src.f5.size(); ++i) { + ByteBuffer s = src.f5.get(i); + ByteBuffer d = dst.f5.get(i); + assertEquals(s, d); + } + } + + @Test + public void testListTypes01() throws Exception { + SampleListTypes src = null; + + byte[] raw = MessagePack.pack(src); + + SampleListTypes dst = + MessagePack.unpack(raw, SampleListTypes.class); + assertEquals(src, dst); + } + + @MessagePackBeans + public static class SampleListTypes { + public List<Integer> f0; + public List<Integer> f1; + public List<String> f2; + public List<List<String>> f3; + public List<SampleListNestedType> f4; + public List<ByteBuffer> f5; + + public List<Integer> getF0() { + return f0; + } + + public void setF0(List<Integer> f0) { + this.f0 = f0; + } + + public List<Integer> getF1() { + return f1; + } + + public void setF1(List<Integer> f1) { + this.f1 = f1; + } + + public List<String> getF2() { + return f2; + } + + public void setF2(List<String> f2) { + this.f2 = f2; + } + + public List<List<String>> getF3() { + return f3; + } + + public void setF3(List<List<String>> f3) { + this.f3 = f3; + } + + public List<SampleListNestedType> getF4() { + return f4; + } + + public void setF4(List<SampleListNestedType> f4) { + this.f4 = f4; + } + + public List<ByteBuffer> getF5() { + return f5; + } + + public void setF5(List<ByteBuffer> f5) { + this.f5 = f5; + } + + public SampleListTypes() { + } + } + + @MessagePackMessage + public static class SampleListNestedType { + public byte[] f0; + public String f1; + + public SampleListNestedType() { + } + } + + @Test + public void testOptionalListTypes00() throws Exception { + SampleOptionalListTypes src = new SampleOptionalListTypes(); + src.f0 = new ArrayList<Integer>(); + src.f1 = new ArrayList<Integer>(); + src.f1.add(1); + src.f1.add(2); + src.f1.add(3); + src.f2 = new ArrayList<String>(); + src.f2.add("e1"); + src.f2.add("e2"); + src.f2.add("e3"); + src.f3 = new ArrayList<List<String>>(); + src.f3.add(src.f2); + src.f4 = new ArrayList<SampleOptionalListNestedType>(); + SampleOptionalListNestedType slnt = new SampleOptionalListNestedType(); + slnt.f0 = new byte[] { 0x01, 0x02 }; + slnt.f1 = "muga"; + src.f4.add(slnt); + src.f5 = new ArrayList<ByteBuffer>(); + src.f5.add(ByteBuffer.wrap("e1".getBytes())); + src.f5.add(ByteBuffer.wrap("e2".getBytes())); + src.f5.add(ByteBuffer.wrap("e3".getBytes())); + + byte[] raw = MessagePack.pack(src); + + SampleOptionalListTypes dst = + MessagePack.unpack(raw, SampleOptionalListTypes.class); + assertEquals(src.f0.size(), dst.f0.size()); + assertEquals(src.f1.size(), dst.f1.size()); + for (int i = 0; i < src.f1.size(); ++i) { + assertEquals(src.f1.get(i), dst.f1.get(i)); + } + assertEquals(src.f2.size(), dst.f2.size()); + for (int i = 0; i < src.f2.size(); ++i) { + assertEquals(src.f2.get(i), dst.f2.get(i)); + } + assertEquals(src.f3.size(), dst.f3.size()); + for (int i = 0; i < src.f3.size(); ++i) { + List<String> srclist = src.f3.get(i); + List<String> dstlist = dst.f3.get(i); + assertEquals(srclist.size(), dstlist.size()); + for (int j = 0; j < srclist.size(); ++j) { + assertEquals(srclist.get(j), dstlist.get(j)); + } + } + assertEquals(src.f4.size(), dst.f4.size()); + for (int i = 0; i < src.f4.size(); ++i) { + SampleOptionalListNestedType s = src.f4.get(i); + SampleOptionalListNestedType d = dst.f4.get(i); + assertEquals(s.f0[0], d.f0[0]); + assertEquals(s.f0[1], d.f0[1]); + assertEquals(s.f1, d.f1); + } + assertEquals(src.f5.size(), dst.f5.size()); + for (int i = 0; i < src.f5.size(); ++i) { + ByteBuffer s = src.f5.get(i); + ByteBuffer d = dst.f5.get(i); + assertEquals(s, d); + } + } + + @Test + public void testOptionalListTypes01() throws Exception { + SampleOptionalListTypes src = new SampleOptionalListTypes(); + src.f0 = new ArrayList<Integer>(); + src.f1 = null; + src.f2 = new ArrayList<String>(); + src.f3 = new ArrayList<List<String>>(); + src.f4 = null; + src.f5 = new ArrayList<ByteBuffer>(); + + byte[] raw = MessagePack.pack(src); + + SampleOptionalListTypes dst = + MessagePack.unpack(raw, SampleOptionalListTypes.class); + assertEquals(src.f0.size(), dst.f0.size()); + assertEquals(src.f1, dst.f1); + assertEquals(src.f2.size(), dst.f2.size()); + assertEquals(src.f3.size(), dst.f3.size()); + assertEquals(src.f4, dst.f4); + assertEquals(src.f5.size(), dst.f5.size()); + } + + @Test + public void testOptionalListTypes02() throws Exception { + SampleListTypes src = null; + + byte[] raw = MessagePack.pack(src); + + SampleListTypes dst = + MessagePack.unpack(raw, SampleListTypes.class); + assertEquals(src, dst); + } + + @MessagePackBeans + public static class SampleOptionalListTypes { + @Optional + public List<Integer> f0; + @Optional + public List<Integer> f1; + @Optional + public List<String> f2; + @Optional + public List<List<String>> f3; + @Optional + public List<SampleOptionalListNestedType> f4; + @Optional + public List<ByteBuffer> f5; + + @Optional + public List<Integer> getF0() { + return f0; + } + + @Optional + public void setF0(List<Integer> f0) { + this.f0 = f0; + } + + @Optional + public List<Integer> getF1() { + return f1; + } + + public void setF1(List<Integer> f1) { + this.f1 = f1; + } + + public List<String> getF2() { + return f2; + } + + @Optional + public void setF2(List<String> f2) { + this.f2 = f2; + } + + @Optional + public List<List<String>> getF3() { + return f3; + } + + public void setF3(List<List<String>> f3) { + this.f3 = f3; + } + + @Optional + public List<SampleOptionalListNestedType> getF4() { + return f4; + } + + public void setF4(List<SampleOptionalListNestedType> f4) { + this.f4 = f4; + } + + @Optional + public List<ByteBuffer> getF5() { + return f5; + } + + public void setF5(List<ByteBuffer> f5) { + this.f5 = f5; + } + + public SampleOptionalListTypes() { + } + } + + @MessagePackBeans + public static class SampleOptionalListNestedType { + @Optional + public byte[] f0; + @Optional + public String f1; + + @Optional + public byte[] getF0() { + return f0; + } + + public void setF0(byte[] f0) { + this.f0 = f0; + } + + @Optional + public String getF1() { + return f1; + } + + public void setF1(String f1) { + this.f1 = f1; + } + + public SampleOptionalListNestedType() { + } + } + + @Test + public void testMapTypes00() throws Exception { + SampleMapTypes src = new SampleMapTypes(); + src.f0 = new HashMap<Integer, Integer>(); + src.f1 = new HashMap<Integer, Integer>(); + src.f1.put(1, 1); + src.f1.put(2, 2); + src.f1.put(3, 3); + src.f2 = new HashMap<String, Integer>(); + src.f2.put("k1", 1); + src.f2.put("k2", 2); + src.f2.put("k3", 3); + + byte[] raw = MessagePack.pack(src); + + SampleMapTypes dst = + MessagePack.unpack(raw, SampleMapTypes.class); + Iterator<Integer> srcf1 = src.f1.keySet().iterator(); + Iterator<Integer> dstf1 = dst.f1.keySet().iterator(); + while (srcf1.hasNext()) { + Integer s1 = srcf1.next(); + Integer d1 = dstf1.next(); + assertEquals(s1, d1); + assertEquals(src.f1.get(s1), dst.f1.get(d1)); + } + assertEquals(src.f2.size(), dst.f2.size()); + Iterator<String> srcf2 = src.f2.keySet().iterator(); + Iterator<String> dstf2 = dst.f2.keySet().iterator(); + while (srcf2.hasNext()) { + String s2 = srcf2.next(); + String d2 = dstf2.next(); + assertEquals(s2, d2); + assertEquals(src.f2.get(s2), dst.f2.get(d2)); + } + } + + @Test + public void testMapTypes01() throws Exception { + SampleMapTypes src = null; + + byte[] raw = MessagePack.pack(src); + + SampleMapTypes dst = + MessagePack.unpack(raw, SampleMapTypes.class); + assertEquals(src, dst); + } + + @MessagePackBeans + public static class SampleMapTypes { + public Map<Integer, Integer> f0; + public Map<Integer, Integer> f1; + public Map<String, Integer> f2; + + public Map<Integer, Integer> getF0() { + return f0; + } + + public void setF0(Map<Integer, Integer> f0) { + this.f0 = f0; + } + + public Map<Integer, Integer> getF1() { + return f1; + } + + public void setF1(Map<Integer, Integer> f1) { + this.f1 = f1; + } + + public Map<String, Integer> getF2() { + return f2; + } + + public void setF2(Map<String, Integer> f2) { + this.f2 = f2; + } + + public SampleMapTypes() { + } + } + + @Test + public void testOptionalMapTypes00() throws Exception { + SampleOptionalMapTypes src = new SampleOptionalMapTypes(); + src.f0 = new HashMap<Integer, Integer>(); + src.f1 = new HashMap<Integer, Integer>(); + src.f1.put(1, 1); + src.f1.put(2, 2); + src.f1.put(3, 3); + src.f2 = new HashMap<String, Integer>(); + src.f2.put("k1", 1); + src.f2.put("k2", 2); + src.f2.put("k3", 3); + + byte[] raw = MessagePack.pack(src); + + SampleOptionalMapTypes dst = + MessagePack.unpack(raw, SampleOptionalMapTypes.class); + assertEquals(src.f0.size(), dst.f0.size()); + assertEquals(src.f1.size(), dst.f1.size()); + Iterator<Integer> srcf1 = src.f1.keySet().iterator(); + Iterator<Integer> dstf1 = dst.f1.keySet().iterator(); + while (srcf1.hasNext()) { + Integer s1 = srcf1.next(); + Integer d1 = dstf1.next(); + assertEquals(s1, d1); + assertEquals(src.f1.get(s1), dst.f1.get(d1)); + } + assertEquals(src.f2.size(), dst.f2.size()); + Iterator<String> srcf2 = src.f2.keySet().iterator(); + Iterator<String> dstf2 = dst.f2.keySet().iterator(); + while (srcf2.hasNext()) { + String s2 = srcf2.next(); + String d2 = dstf2.next(); + assertEquals(s2, d2); + assertEquals(src.f2.get(s2), dst.f2.get(d2)); + } + } + + @Test + public void testOptionalMapTypes01() throws Exception { + SampleOptionalMapTypes src = new SampleOptionalMapTypes(); + src.f0 = new HashMap<Integer, Integer>(); + src.f1 = null; + src.f2 = new HashMap<String, Integer>(); + + byte[] raw = MessagePack.pack(src); + + SampleOptionalMapTypes dst = + MessagePack.unpack(raw, SampleOptionalMapTypes.class); + assertEquals(src.f0.size(), dst.f0.size()); + assertEquals(src.f1, dst.f1); + assertEquals(src.f2.size(), dst.f2.size()); + } + + @Test + public void testOptionalMapTypes02() throws Exception { + SampleOptionalMapTypes src = null; + + byte[] raw = MessagePack.pack(src); + + SampleOptionalMapTypes dst = + MessagePack.unpack(raw, SampleOptionalMapTypes.class); + assertEquals(src, dst); + } + + @MessagePackBeans + public static class SampleOptionalMapTypes { + @Optional + public Map<Integer, Integer> f0; + @Optional + public Map<Integer, Integer> f1; + @Optional + public Map<String, Integer> f2; + + @Optional + public Map<Integer, Integer> getF0() { + return f0; + } + + public void setF0(Map<Integer, Integer> f0) { + this.f0 = f0; + } + + @Optional + public Map<Integer, Integer> getF1() { + return f1; + } + + public void setF1(Map<Integer, Integer> f1) { + this.f1 = f1; + } + + @Optional + public Map<String, Integer> getF2() { + return f2; + } + + public void setF2(Map<String, Integer> f2) { + this.f2 = f2; + } + + public SampleOptionalMapTypes() { + } + } + + + @MessagePackBeans + public abstract static class AbstractModifierClass { + } + + @Test + public void testInterfaceType00() throws Exception { + try { + TemplateBuilder builder = BuilderSelectorRegistry.getInstance().select(SampleInterface.class); + Assert.assertNull(builder); + BuilderSelectorRegistry.getInstance().getForceBuilder().buildTemplate(SampleInterface.class); + fail(); + } catch (TemplateBuildException e) { + assertTrue(true); + } + assertTrue(true); + } + + @Test + public void testInterfaceType01() throws Exception { + try { + TemplateBuilder builder = BuilderSelectorRegistry.getInstance().select(SampleInterface.class); + Assert.assertNull(builder); + BuilderSelectorRegistry.getInstance().getForceBuilder().buildTemplate(SampleInterface.class); + fail(); + } catch (TemplateBuildException e) { + assertTrue(true); + } + assertTrue(true); + } + + public interface SampleInterface { + } + + @Test + public void testEnumTypeForOrdinal00() throws Exception { + SampleEnumFieldClass src = new SampleEnumFieldClass(); + src.f0 = 23; + src.f1 = SampleEnum.ONE; + + byte[] raw = MessagePack.pack(src); + + SampleEnumFieldClass dst = + MessagePack.unpack(raw, SampleEnumFieldClass.class); + Assert.assertThat(dst.f0, is(src.f0)); + Assert.assertThat(dst.f1, is(src.f1)); + } + + @Test + public void testEnumTypeForOrdinal01() throws Exception { + SampleEnumFieldClass src = null; + + byte[] raw = MessagePack.pack(src); + + SampleEnumFieldClass dst = + MessagePack.unpack(raw, SampleEnumFieldClass.class); + Assert.assertThat(dst,is(src)); + } + + @MessagePackBeans + public static class SampleEnumFieldClass { + public int f0; + + public SampleEnum f1; + + public int getF0() { + return f0; + } + + public void setF0(int f0) { + this.f0 = f0; + } + + public SampleEnum getF1() { + return f1; + } + + public void setF1(SampleEnum f1) { + this.f1 = f1; + } + + public SampleEnumFieldClass() { + } + } + + @MessagePackOrdinalEnum + public enum SampleEnum { + ONE, TWO, THREE; + } + + @Test + public void testOptionalEnumTypeForOrdinal00() throws Exception { + SampleOptionalEnumFieldClass src = new SampleOptionalEnumFieldClass(); + src.f0 = 0; + src.f1 = SampleOptionalEnum.ONE; + + byte[] raw = MessagePack.pack(src); + + SampleOptionalEnumFieldClass dst = + MessagePack.unpack(raw, SampleOptionalEnumFieldClass.class); + assertTrue(src.f0 == dst.f0); + assertTrue(src.f1 == dst.f1); + } + + @Test + public void testOptionalEnumTypeForOrdinal01() throws Exception { + SampleOptionalEnumFieldClass src = new SampleOptionalEnumFieldClass(); + src.f1 = null; + + byte[] raw = MessagePack.pack(src); + + SampleOptionalEnumFieldClass dst = + MessagePack.unpack(raw, SampleOptionalEnumFieldClass.class); + assertTrue(src.f0 == dst.f0); + assertEquals(src.f1, dst.f1); + } + + @Test + public void testOptionalEnumTypeForOrdinal02() throws Exception { + SampleEnumFieldClass src = null; + + byte[] raw = MessagePack.pack(src); + + SampleEnumFieldClass dst = + MessagePack.unpack(raw, SampleEnumFieldClass.class); + assertEquals(src, dst); + } + + @MessagePackBeans + public static class SampleOptionalEnumFieldClass { + @Optional + public int f0; + + @Optional + public SampleOptionalEnum f1; + + @Optional + public int getF0() { + return f0; + } + + public void setF0(int f0) { + this.f0 = f0; + } + + @Optional + public SampleOptionalEnum getF1() { + return f1; + } + + public void setF1(SampleOptionalEnum f1) { + this.f1 = f1; + } + + public SampleOptionalEnumFieldClass() { + } + } + + @MessagePackOrdinalEnum + public enum SampleOptionalEnum { + ONE, TWO, THREE; + } + + @Test + public void testFieldModifiers() throws Exception { + FieldModifiersClass src = new FieldModifiersClass(); + src.f0 = 0; + src.f2 = 2; + src.f3 = 3; + src.f4 = 4; + + byte[] raw = MessagePack.pack(src); + + FieldModifiersClass dst = + MessagePack.unpack(raw, FieldModifiersClass.class); + Assert.assertEquals(src.f1,dst.f1); + Assert.assertThat(dst.f2, is( not(src.f2))); + Assert.assertThat(dst.f3, is( not(src.f3))); + Assert.assertThat(dst.f4, is( not(src.f4))); + } + + @MessagePackBeans + public static class FieldModifiersClass { + public int f0; + public final int f1 = 1; + private int f2; + protected int f3; + int f4; + + public int getF0() { + return f0; + } + + public void setF0(int f0) { + this.f0 = f0; + } + + private int getF2() { + return f2; + } + + private void setF2(int f2) { + this.f2 = f2; + } + + public int getF3() { + return f3; + } + + protected void setF3(int f3) { + this.f3 = f3; + } + + public int getF4() { + return f4; + } + + void setF4(int f4) { + this.f4 = f4; + } + + public int getF1() { + return f1; + } + + public FieldModifiersClass() { + } + } + + @Test + public void testOptionalFieldModifiers() throws Exception { + OptionalFieldModifiersClass src = new OptionalFieldModifiersClass(); + src.f0 = 0; + src.f2 = 2; + src.f3 = 3; + src.f4 = 4; + + byte[] raw = MessagePack.pack(src); + + OptionalFieldModifiersClass dst = + MessagePack.unpack(raw, OptionalFieldModifiersClass.class); + Assert.assertThat(dst.f0, is(src.f0)); + Assert.assertThat(dst.f1, is(src.f1)); + Assert.assertThat(dst.f2, is(not(src.f2))); + Assert.assertThat(dst.f3, is(not(src.f3))); + Assert.assertThat(dst.f4, is(not(src.f4))); + } + + @MessagePackBeans + public static class OptionalFieldModifiersClass { + @Optional + public int f0; + @Optional + public final int f1 = 1; + private int f2; + protected int f3; + int f4; + + @Optional + public int getF0() { + return f0; + } + + public void setF0(int f0) { + this.f0 = f0; + } + + private int getF2() { + return f2; + } + + public void setF2(int f2) { + this.f2 = f2; + } + + protected int getF3() { + return f3; + } + + protected void setF3(int f3) { + this.f3 = f3; + } + + public int getF4() { + return f4; + } + + void setF4(int f4) { + this.f4 = f4; + } + + public int getF1() { + return f1; + } + + public OptionalFieldModifiersClass() { + } + } + + @Test + public void testNestedFieldClass00() throws Exception { + BaseClass src = new BaseClass(); + NestedClass src2 = new NestedClass(); + src.f0 = 0; + src2.f2 = 2; + src.f1 = src2; + + byte[] raw = MessagePack.pack(src); + + BaseClass dst = + MessagePack.unpack(raw, BaseClass.class); + assertTrue(src.f0 == dst.f0); + assertTrue(src.f1.f2 == dst.f1.f2); + } + + @Test + public void testNestedFieldClass01() throws Exception { + BaseClass src = null; + + byte[] raw = MessagePack.pack(src); + + BaseClass dst = + MessagePack.unpack(raw, BaseClass.class); + assertEquals(src, dst); + } + + @MessagePackBeans + public static class BaseClass { + public int f0; + public NestedClass f1; + + public int getF0() { + return f0; + } + + public void setF0(int f0) { + this.f0 = f0; + } + + public NestedClass getF1() { + return f1; + } + + public void setF1(NestedClass f1) { + this.f1 = f1; + } + + public BaseClass() { + } + } + + @MessagePackBeans + public static class NestedClass { + public int f2; + + public int getF2() { + return f2; + } + + public void setF2(int f2) { + this.f2 = f2; + } + + public NestedClass() { + } + } + + @Test + public void testOptionalNestedFieldClass00() throws Exception { + OptionalBaseClass src = new OptionalBaseClass(); + OptionalNestedClass src2 = new OptionalNestedClass(); + src.f0 = 0; + src2.f2 = 2; + src.f1 = src2; + + byte[] raw = MessagePack.pack(src); + + OptionalBaseClass dst = + MessagePack.unpack(raw, OptionalBaseClass.class); + assertTrue(src.f0 == dst.f0); + assertTrue(src.f1.f2 == dst.f1.f2); + } + + @Test + public void testOptionalNestedFieldClass01() throws Exception { + OptionalBaseClass src = new OptionalBaseClass(); + src.f1 = null; + + byte[] raw = MessagePack.pack(src); + + OptionalBaseClass dst = + MessagePack.unpack(raw, OptionalBaseClass.class); + assertTrue(src.f0 == dst.f0); + assertTrue(src.f1 == dst.f1); + } + + @Test + public void testOptionalNestedFieldClass02() throws Exception { + OptionalBaseClass src = null; + + byte[] raw = MessagePack.pack(src); + + OptionalBaseClass dst = + MessagePack.unpack(raw, OptionalBaseClass.class); + assertEquals(src, dst); + } + + @MessagePackBeans + public static class OptionalBaseClass { + @Optional + public int f0; + @Optional + public OptionalNestedClass f1; + + @Optional + public int getF0() { + return f0; + } + + public void setF0(int f0) { + this.f0 = f0; + } + + @Optional + public OptionalNestedClass getF1() { + return f1; + } + + public void setF1(OptionalNestedClass f1) { + this.f1 = f1; + } + + public OptionalBaseClass() { + } + } + + @MessagePackBeans + public static class OptionalNestedClass { + @Optional + public int f2; + + @Optional + public int getF2() { + return f2; + } + + public void setF2(int f2) { + this.f2 = f2; + } + + public OptionalNestedClass() { + } + } + + @Test + public void testMessagePackMessageFieldClass00() throws Exception { + BaseClass2 src = new BaseClass2(); + MessagePackMessageClass2 src2 = new MessagePackMessageClass2(); + src.f0 = 0; + src2.f2 = 2; + src.f1 = src2; + + byte[] raw = MessagePack.pack(src); + + BaseClass2 dst = + MessagePack.unpack(raw, BaseClass2.class); + assertTrue(src.f0 == dst.f0); + assertTrue(src.f1.f2 == dst.f1.f2); + } + + @Test + public void testMessagePackMessageFieldClass01() throws Exception { + BaseClass2 src = null; + + byte[] raw = MessagePack.pack(src); + + BaseClass2 dst = + MessagePack.unpack(raw, BaseClass2.class); + assertEquals(src, dst); + } + + @MessagePackBeans + public static class BaseClass2 { + public int f0; + public MessagePackMessageClass2 f1; + + public int getF0() { + return f0; + } + + public void setF0(int f0) { + this.f0 = f0; + } + + public MessagePackMessageClass2 getF1() { + return f1; + } + + public void setF1(MessagePackMessageClass2 f1) { + this.f1 = f1; + } + + public BaseClass2() { + } + } + + @MessagePackBeans + public static class MessagePackMessageClass2 { + public int getF2() { + return f2; + } + + public void setF2(int f2) { + this.f2 = f2; + } + + public int f2; + + public MessagePackMessageClass2() { + } + } + + @Test + public void testOptionalMessagePackMessageFieldClass00() throws Exception { + OptionalBaseClass2 src = new OptionalBaseClass2(); + OptionalMessagePackMessageClass2 src2 = new OptionalMessagePackMessageClass2(); + src.f0 = 0; + src2.f2 = 2; + src.f1 = src2; + + byte[] raw = MessagePack.pack(src); + + OptionalBaseClass2 dst = + MessagePack.unpack(raw, OptionalBaseClass2.class); + assertTrue(src.f0 == dst.f0); + assertTrue(src.f1.f2 == dst.f1.f2); + } + + @Test + public void testOptionalMessagePackMessageFieldClass01() throws Exception { + OptionalBaseClass2 src = new OptionalBaseClass2(); + src.f1 = null; + + byte[] raw = MessagePack.pack(src); + + OptionalBaseClass2 dst = + MessagePack.unpack(raw, OptionalBaseClass2.class); + assertTrue(src.f0 == dst.f0); + assertEquals(src.f1, dst.f1); + } + + @Test + public void testOptionalMessagePackMessageFieldClass02() throws Exception { + OptionalBaseClass2 src = null; + + byte[] raw = MessagePack.pack(src); + + OptionalBaseClass2 dst = + MessagePack.unpack(raw, OptionalBaseClass2.class); + assertEquals(src, dst); + } + + @MessagePackBeans + public static class OptionalBaseClass2 { + @Optional + public int f0; + @Optional + public OptionalMessagePackMessageClass2 f1; + + @Optional + public int getF0() { + return f0; + } + + public void setF0(int f0) { + this.f0 = f0; + } + + @Optional + public OptionalMessagePackMessageClass2 getF1() { + return f1; + } + + public void setF1(OptionalMessagePackMessageClass2 f1) { + this.f1 = f1; + } + + public OptionalBaseClass2() { + } + } + + @MessagePackBeans + public static class OptionalMessagePackMessageClass2 { + @Optional + public int f2; + + @Optional + public int getF2() { + return f2; + } + + public void setF2(int f2) { + this.f2 = f2; + } + + public OptionalMessagePackMessageClass2() { + } + } + + @Test + public void testExtendedClass00() throws Exception { + SampleSubClass src = new SampleSubClass(); + src.f0 = 0; + src.f2 = 2; + src.f3 = 3; + src.f4 = 4; + src.f5 = 5; + src.f8 = 8; + src.f9 = 9; + + byte[] raw = MessagePack.pack(src); + + SampleSubClass dst = + MessagePack.unpack(raw, SampleSubClass.class); + assertTrue(src.f0 == dst.f0); + assertTrue(src.f1 == dst.f1); + assertTrue(src.f2 != dst.f2); + assertTrue(src.f3 != dst.f3); + assertTrue(src.f4 != dst.f4); + assertTrue(src.f5 == dst.f5); + assertTrue(src.f6 == dst.f6); + assertTrue(src.f8 != dst.f8); + assertTrue(src.f9 != dst.f9); + } + + @Test + public void testExtendedClass01() throws Exception { + SampleSubClass src = null; + + byte[] raw = MessagePack.pack(src); + + SampleSubClass dst = + MessagePack.unpack(raw, SampleSubClass.class); + assertEquals(src, dst); + } + + @MessagePackBeans + public static class SampleSubClass extends SampleSuperClass { + public int f0; + public final int f1 = 1; + private int f2; + protected int f3; + int f4; + + public int getF0() { + return f0; + } + + public void setF0(int f0) { + this.f0 = f0; + } + + public int getF1() { + return f1; + } + + public SampleSubClass() { + } + } + + @MessagePackBeans + public static class SampleSuperClass { + public int f5; + public final int f6 = 2; + @SuppressWarnings("unused") + private int f7; + protected int f8; + int f9; + + public int getF5() { + return f5; + } + + public void setF5(int f5) { + this.f5 = f5; + } + + public SampleSuperClass() { + } + } + + @Test + public void testOptionalExtendedClass00() throws Exception { + SampleOptionalSubClass src = new SampleOptionalSubClass(); + src.f0 = 0; + src.f2 = 2; + src.f3 = 3; + src.f4 = 4; + src.f5 = 5; + src.f8 = 8; + src.f9 = 9; + + byte[] raw = MessagePack.pack(src); + + SampleOptionalSubClass dst = + MessagePack.unpack(raw, SampleOptionalSubClass.class); + assertTrue(src.f0 == dst.f0); + assertTrue(src.f1 == dst.f1); + assertTrue(src.f2 != dst.f2); + assertTrue(src.f3 != dst.f3); + assertTrue(src.f4 != dst.f4); + assertTrue(src.f5 == dst.f5); + assertTrue(src.f6 == dst.f6); + assertTrue(src.f8 != dst.f8); + assertTrue(src.f9 != dst.f9); + } + + @Test + public void testOptionalExtendedClass01() throws Exception { + SampleOptionalSubClass src = null; + + byte[] raw = MessagePack.pack(src); + + SampleOptionalSubClass dst = + MessagePack.unpack(raw, SampleOptionalSubClass.class); + assertEquals(src, dst); + } + + @MessagePackBeans + public static class SampleOptionalSubClass extends SampleOptionalSuperClass { + @Optional + public int f0; + public final int f1 = 1; + private int f2; + protected int f3; + int f4; + @Optional + public int getF0() { + return f0; + } + + public void setF0(int f0) { + this.f0 = f0; + } + + public SampleOptionalSubClass() { + } + } + + @MessagePackBeans + public static class SampleOptionalSuperClass { + @Optional + public int getF5() { + return f5; + } + + public void setF5(int f5) { + this.f5 = f5; + } + + @Optional + public int f5; + public final int f6 = 2; + @SuppressWarnings("unused") + private int f7; + protected int f8; + int f9; + + public SampleOptionalSuperClass() { + } + } + + @Test + public void testMessagePackableUnpackableClass00() throws Exception { + BaseMessagePackableUnpackableClass src = new BaseMessagePackableUnpackableClass(); + MessagePackableUnpackableClass src1 = new MessagePackableUnpackableClass(); + List<MessagePackableUnpackableClass> src2 = new ArrayList<MessagePackableUnpackableClass>(); + src1.f0 = 0; + src1.f1 = 1; + src.f0 = src1; + src.f1 = 1; + src2.add(src1); + src.f2 = src2; + + byte[] raw = MessagePack.pack(src); + + BaseMessagePackableUnpackableClass dst = + MessagePack.unpack(raw, BaseMessagePackableUnpackableClass.class); + assertEquals(src.f0.f0, dst.f0.f0); + assertEquals(src.f0.f1, dst.f0.f1); + assertEquals(src.f1, dst.f1); + assertEquals(src.f2.size(), dst.f2.size()); + assertEquals(src.f2.get(0).f0, dst.f2.get(0).f0); + assertEquals(src.f2.get(0).f1, dst.f2.get(0).f1); + } + + @Test + public void testMessagePackableUnpackableClass01() throws Exception { + BaseMessagePackableUnpackableClass src = null; + + byte[] raw = MessagePack.pack(src); + + BaseMessagePackableUnpackableClass dst = + MessagePack.unpack(raw, BaseMessagePackableUnpackableClass.class); + assertEquals(src, dst); + } + + @MessagePackBeans + public static class BaseMessagePackableUnpackableClass { + public MessagePackableUnpackableClass f0; + public int f1; + public List<MessagePackableUnpackableClass> f2; + + public MessagePackableUnpackableClass getF0() { + return f0; + } + + public void setF0(MessagePackableUnpackableClass f0) { + this.f0 = f0; + } + + public int getF1() { + return f1; + } + + public void setF1(int f1) { + this.f1 = f1; + } + + public List<MessagePackableUnpackableClass> getF2() { + return f2; + } + + public void setF2(List<MessagePackableUnpackableClass> f2) { + this.f2 = f2; + } + + public BaseMessagePackableUnpackableClass() { + } + } + + @MessagePackBeans + public static class MessagePackableUnpackableClass implements + MessagePackable, MessageUnpackable { + public int getF0() { + return f0; + } + + public void setF0(int f0) { + this.f0 = f0; + } + + public int getF1() { + return f1; + } + + public void setF1(int f1) { + this.f1 = f1; + } + + public int f0; + public int f1; + + public MessagePackableUnpackableClass() { + } + + @Override + public void messagePack(Packer packer) throws IOException { + packer.packArray(2); + packer.pack(f0); + packer.pack(f1); + } + + @Override + public void messageUnpack(Unpacker unpacker) throws IOException, + MessageTypeException { + if (unpacker.tryUnpackNull()) { + return; + } + unpacker.unpackArray(); + f0 = unpacker.unpackInt(); + f1 = unpacker.unpackInt(); + } + } + + @Test + public void testOptionalMessagePackableUnpackableClass00() throws Exception { + OptionalBaseMessagePackableUnpackableClass src = new OptionalBaseMessagePackableUnpackableClass(); + OptionalMessagePackableUnpackableClass src1 = new OptionalMessagePackableUnpackableClass(); + List<OptionalMessagePackableUnpackableClass> src2 = new ArrayList<OptionalMessagePackableUnpackableClass>(); + src1.f0 = 0; + src1.f1 = 1; + src.f0 = src1; + src.f1 = 1; + src2.add(src1); + src.f2 = src2; + + byte[] raw = MessagePack.pack(src); + + OptionalBaseMessagePackableUnpackableClass dst = + MessagePack.unpack(raw, OptionalBaseMessagePackableUnpackableClass.class); + assertEquals(src.f0.f0, dst.f0.f0); + assertEquals(src.f0.f1, dst.f0.f1); + assertEquals(src.f1, dst.f1); + assertEquals(src.f2.size(), dst.f2.size()); + assertEquals(src.f2.get(0).f0, dst.f2.get(0).f0); + assertEquals(src.f2.get(0).f1, dst.f2.get(0).f1); + } + + @Test + public void testOptionalMessagePackableUnpackableClass01() throws Exception { + OptionalBaseMessagePackableUnpackableClass src = new OptionalBaseMessagePackableUnpackableClass(); + src.f0 = null; + src.f1 = 1; + src.f2 = null; + + byte[] raw = MessagePack.pack(src); + + OptionalBaseMessagePackableUnpackableClass dst = + MessagePack.unpack(raw, OptionalBaseMessagePackableUnpackableClass.class); + assertEquals(src.f0, dst.f0); + assertEquals(src.f1, dst.f1); + assertEquals(src.f2, dst.f2); + } + + @Test + public void testOptionalMessagePackableUnpackableClass02() throws Exception { + OptionalBaseMessagePackableUnpackableClass src = null; + + byte[] raw = MessagePack.pack(src); + + OptionalBaseMessagePackableUnpackableClass dst = + MessagePack.unpack(raw, OptionalBaseMessagePackableUnpackableClass.class); + assertEquals(src, dst); + } + + @MessagePackBeans + public static class OptionalBaseMessagePackableUnpackableClass { + @Optional + public OptionalMessagePackableUnpackableClass f0; + @Optional + public int f1; + @Optional + public List<OptionalMessagePackableUnpackableClass> f2; + + @Optional + public OptionalMessagePackableUnpackableClass getF0() { + return f0; + } + + public void setF0(OptionalMessagePackableUnpackableClass f0) { + this.f0 = f0; + } + + @Optional + public int getF1() { + return f1; + } + + public void setF1(int f1) { + this.f1 = f1; + } + + @Optional + public List<OptionalMessagePackableUnpackableClass> getF2() { + return f2; + } + + public void setF2(List<OptionalMessagePackableUnpackableClass> f2) { + this.f2 = f2; + } + + public OptionalBaseMessagePackableUnpackableClass() { + } + } + + @MessagePackBeans + public static class OptionalMessagePackableUnpackableClass implements + MessagePackable, MessageUnpackable { + @Optional + public int getF0() { + return f0; + } + + public void setF0(int f0) { + this.f0 = f0; + } + + @Optional + public int getF1() { + return f1; + } + + public void setF1(int f1) { + this.f1 = f1; + } + + @Optional + public int f0; + @Optional + public int f1; + + public OptionalMessagePackableUnpackableClass() { + } + + @Override + public void messagePack(Packer packer) throws IOException { + packer.packArray(2); + packer.pack(f0); + packer.pack(f1); + } + + @Override + public void messageUnpack(Unpacker unpacker) throws IOException, + MessageTypeException { + if (unpacker.tryUnpackNull()) { + return; + } + unpacker.unpackArray(); + f0 = unpacker.unpackInt(); + f1 = unpacker.unpackInt(); + } + } +} + diff --git a/java/src/test/java/org/msgpack/template/TestTemplateBuilderPackConvert.java b/java/src/test/java/org/msgpack/template/TestTemplateBuilderPackConvert.java index a99fa260..f316e64a 100644 --- a/java/src/test/java/org/msgpack/template/TestTemplateBuilderPackConvert.java +++ b/java/src/test/java/org/msgpack/template/TestTemplateBuilderPackConvert.java @@ -24,7 +24,10 @@ import org.msgpack.Unpacker; import org.msgpack.annotation.MessagePackMessage; import org.msgpack.annotation.MessagePackOrdinalEnum; import org.msgpack.annotation.Optional; +import org.msgpack.template.builder.BuilderSelectorRegistry; +import org.msgpack.template.builder.TemplateBuilder; +import junit.framework.Assert; import junit.framework.TestCase; public class TestTemplateBuilderPackConvert extends TestCase { @@ -714,7 +717,9 @@ public class TestTemplateBuilderPackConvert extends TestCase { @Test public void testFinalClass() throws Exception { try { - TemplateBuilder.build(FinalModifierClass.class); + TemplateBuilder builder = BuilderSelectorRegistry.getInstance().select(FinalModifierClass.class); + Assert.assertNull(builder);// no available builder + BuilderSelectorRegistry.getInstance().getForceBuilder().buildTemplate(FinalModifierClass.class); assertTrue(true); } catch (TemplateBuildException e) { fail(); @@ -731,7 +736,9 @@ public class TestTemplateBuilderPackConvert extends TestCase { @Test public void testInterfaceType00() throws Exception { try { - TemplateBuilder.build(SampleInterface.class); + TemplateBuilder builder = BuilderSelectorRegistry.getInstance().select(SampleInterface.class); + Assert.assertNull(builder);// no available builder + BuilderSelectorRegistry.getInstance().getForceBuilder().buildTemplate(SampleInterface.class); fail(); } catch (TemplateBuildException e) { assertTrue(true); @@ -742,7 +749,9 @@ public class TestTemplateBuilderPackConvert extends TestCase { @Test public void testInterfaceType01() throws Exception { try { - TemplateBuilder.build(SampleInterface.class); + TemplateBuilder builder = BuilderSelectorRegistry.getInstance().select(SampleInterface.class); + Assert.assertNull(builder);// no available builder + BuilderSelectorRegistry.getInstance().getForceBuilder().buildTemplate(SampleInterface.class); fail(); } catch (TemplateBuildException e) { assertTrue(true); diff --git a/java/src/test/java/org/msgpack/template/TestTemplateBuilderPackUnpack.java b/java/src/test/java/org/msgpack/template/TestTemplateBuilderPackUnpack.java index a2430a43..9ac94ef7 100644 --- a/java/src/test/java/org/msgpack/template/TestTemplateBuilderPackUnpack.java +++ b/java/src/test/java/org/msgpack/template/TestTemplateBuilderPackUnpack.java @@ -24,7 +24,11 @@ import org.msgpack.Unpacker; import org.msgpack.annotation.MessagePackMessage; import org.msgpack.annotation.MessagePackOrdinalEnum; import org.msgpack.annotation.Optional; +import org.msgpack.template.TestTemplateBuilderPackConvert.SampleInterface; +import org.msgpack.template.builder.BuilderSelectorRegistry; +import org.msgpack.template.builder.TemplateBuilder; +import junit.framework.Assert; import junit.framework.TestCase; public class TestTemplateBuilderPackUnpack extends TestCase { @@ -714,7 +718,9 @@ public class TestTemplateBuilderPackUnpack extends TestCase { @Test public void testFinalClass() throws Exception { try { - TemplateBuilder.build(FinalModifierClass.class); + TemplateBuilder builder = BuilderSelectorRegistry.getInstance().select(FinalModifierClass.class); + Assert.assertNull(builder); + BuilderSelectorRegistry.getInstance().getForceBuilder().buildTemplate(FinalModifierClass.class); assertTrue(true); } catch (TemplateBuildException e) { fail(); @@ -731,7 +737,9 @@ public class TestTemplateBuilderPackUnpack extends TestCase { @Test public void testInterfaceType00() throws Exception { try { - TemplateBuilder.build(SampleInterface.class); + TemplateBuilder builder = BuilderSelectorRegistry.getInstance().select(SampleInterface.class); + Assert.assertNull(builder); + BuilderSelectorRegistry.getInstance().getForceBuilder().buildTemplate(SampleInterface.class); fail(); } catch (TemplateBuildException e) { assertTrue(true); @@ -742,7 +750,9 @@ public class TestTemplateBuilderPackUnpack extends TestCase { @Test public void testInterfaceType01() throws Exception { try { - TemplateBuilder.build(SampleInterface.class); + TemplateBuilder builder = BuilderSelectorRegistry.getInstance().select(SampleInterface.class); + Assert.assertNull(builder); + BuilderSelectorRegistry.getInstance().getForceBuilder().buildTemplate(SampleInterface.class); fail(); } catch (TemplateBuildException e) { assertTrue(true); diff --git a/scala/.gitignore b/scala/.gitignore new file mode 100644 index 00000000..97250138 --- /dev/null +++ b/scala/.gitignore @@ -0,0 +1,40 @@ +# use glob syntax. +syntax: glob +*.ser +*.class +*~ +*.bak +#*.off +*.old + +# eclipse conf file +.settings +.classpath +.project +.manager +.scala_dependencies + +# idea +.idea +*.iml + +# building +target +build +null +tmp* +dist +test-output +build.log + +# other scm +.svn +.CVS +.hg* + +# switch to regexp syntax. +# syntax: regexp +# ^\.pc/ + +#SHITTY output not in target directory +build.log diff --git a/scala/pom.xml b/scala/pom.xml new file mode 100644 index 00000000..b6a14f2c --- /dev/null +++ b/scala/pom.xml @@ -0,0 +1,158 @@ +<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd"> + <modelVersion>4.0.0</modelVersion> + <groupId>org.msgpack</groupId> + <artifactId>scala-msgpack</artifactId> + <version>0.0.1-SNAPSHOT</version> + <name>${project.artifactId}</name> + <description>My wonderfull scala app</description> + <inceptionYear>2010</inceptionYear> + <licenses> + <license> + <name>My License</name> + <url>http://....</url> + <distribution>repo</distribution> + </license> + </licenses> + + <properties> + <maven.compiler.source>1.5</maven.compiler.source> + <maven.compiler.target>1.5</maven.compiler.target> + <encoding>UTF-8</encoding> + <scala.version>2.8.1</scala.version> + </properties> + <repositories> + <repository> + <id>msgpack.org</id> + <name>MessagePack Repository for Maven</name> + <url>http://msgpack.org/maven2/</url> + </repository> + </repositories> + +<!-- + <repositories> + <repository> + <id>scala-tools.org</id> + <name>Scala-Tools Maven2 Repository</name> + <url>http://scala-tools.org/repo-releases</url> + </repository> + </repositories> + + <pluginRepositories> + <pluginRepository> + <id>scala-tools.org</id> + <name>Scala-Tools Maven2 Repository</name> + <url>http://scala-tools.org/repo-releases</url> + </pluginRepository> + </pluginRepositories> +--> + <dependencies> + <dependency> + <groupId>org.scala-lang</groupId> + <artifactId>scala-library</artifactId> + <version>${scala.version}</version> + </dependency> + + <!-- Test --> + <dependency> + <groupId>junit</groupId> + <artifactId>junit</artifactId> + <version>4.8.1</version> + <scope>test</scope> + </dependency> + <dependency> + <groupId>org.scala-tools.testing</groupId> + <artifactId>specs_${scala.version}</artifactId> + <version>1.6.6</version> + <scope>test</scope> + </dependency> + <dependency> + <groupId>org.msgpack</groupId> + <artifactId>msgpack</artifactId> + <version>0.5.2-SNAPSHOT</version> + </dependency> + </dependencies> + + <distributionManagement> + <repository> + <uniqueVersion>false</uniqueVersion> + <id>msgpack.org</id> + <name>Repository at msgpack.org</name> + <!--<url>file://${project.build.directory}/website/maven2/</url>--> + <url>${deploy-release-url}</url> + </repository> + <snapshotRepository> + <uniqueVersion>true</uniqueVersion> + <id>msgpack.org</id> + <name>Repository at msgpack.org</name> + <!--<url>file://${project.build.directory}/website/maven2/</url>--> + <url>${deploy-snapshot-url}</url> + </snapshotRepository> + </distributionManagement> + + <build> + <sourceDirectory>src/main/scala</sourceDirectory> + <testSourceDirectory>src/test/scala</testSourceDirectory> + <plugins> + <plugin> + <groupId>org.scala-tools</groupId> + <artifactId>maven-scala-plugin</artifactId> + <version>2.15.0</version> + <executions> + <execution> + <goals> + <goal>compile</goal> + <goal>testCompile</goal> + </goals> + <configuration> + <args> + <arg>-make:transitive</arg> + <arg>-dependencyfile</arg> + <arg>${project.build.directory}/.scala_dependencies</arg> + </args> + </configuration> + </execution> + </executions> + </plugin> + <plugin> + <groupId>org.apache.maven.plugins</groupId> + <artifactId>maven-surefire-plugin</artifactId> + <version>2.6</version> + <configuration> + <useFile>false</useFile> + <disableXmlReport>true</disableXmlReport> + <!-- If you have classpath issue like NoDefClassError,... --> + <!-- useManifestOnlyJar>false</useManifestOnlyJar --> + <includes> + <include>**/*Test.*</include> + <include>**/*Suite.*</include> + </includes> + </configuration> + </plugin> + <plugin> + <groupId>org.apache.maven.plugins</groupId> + <artifactId>maven-surefire-report-plugin</artifactId> + </plugin> + <plugin> + <artifactId>maven-assembly-plugin</artifactId> + <configuration> + <descriptorRefs> + <!-- ここはこのままでOK --> + <descriptorRef>jar-with-dependencies</descriptorRef> + </descriptorRefs> + + </configuration> + <executions> + <!-- ここでpackageのPhaseで実行されるように設定している--> + <execution> + <id>make-assembly</id> <!-- this is used for inheritance merges --> + <phase>package</phase> <!-- append to the packaging phase. --> + <goals> + <goal>single</goal> <!-- goals == mojos --> + </goals> + </execution> + </executions> + + </plugin> + </plugins> + </build> +</project> diff --git a/scala/src/main/scala/org/msgpack/App.scala b/scala/src/main/scala/org/msgpack/App.scala new file mode 100644 index 00000000..f80d7a0d --- /dev/null +++ b/scala/src/main/scala/org/msgpack/App.scala @@ -0,0 +1,15 @@ +package org.msgpack + +/** + * @author ${user.name} + */ +object App { + + def foo(x : Array[String]) = x.foldLeft("")((a,b) => a + b) + + def main(args : Array[String]) { + println( "Hello World!" ) + println("concat arguments = " + foo(args)) + } + +} diff --git a/scala/src/main/scala/org/msgpack/JavassistTypeScalaTemplateBuilder.scala b/scala/src/main/scala/org/msgpack/JavassistTypeScalaTemplateBuilder.scala new file mode 100644 index 00000000..879bddea --- /dev/null +++ b/scala/src/main/scala/org/msgpack/JavassistTypeScalaTemplateBuilder.scala @@ -0,0 +1,521 @@ +package org.msgpack + +import _root_.javassist.{CtClass, CtNewConstructor} +import annotation._ +import template._ +import java.lang.Class +import collection.immutable.{ListMap, TreeMap} +import java.lang.reflect.{Type, Modifier, Method, Field} +import java.lang.annotation.{Annotation => JavaAnnotation} +import javassist.{JavassistTemplate, BuildContextBase, BuildContext} +import scala.collection.JavaConverters._ +; +/* + * Created by IntelliJ IDEA. + * User: takeshita + * Date: 11/03/10 + * Time: 12:29 + */ + + + class BuildContextForScala(builder : JavassistTemplateBuilder) extends BuildContextBase[IFieldEntry](builder){ + + var entries : Array[IFieldEntry] = null + var origClass : Class[_] = null + var origName : String = null + var templates : Array[Template] = null + var minimumArrayLength : Int = 0 + + def buildTemplate(targetClass : Class[_] , entries : Array[IFieldEntry], templates : Array[Template]) = { + this.entries = entries; + this.templates = templates; + this.origClass = targetClass; + this.origName = this.origClass.getName(); + build(this.origName); + } + + def setSuperClass() = { + tmplCtClass.setSuperclass(director.getCtClass(classOf[JavassistTemplate].getName)) + } + + def buildConstructor() = { + val newCtCons = CtNewConstructor.make( + Array[CtClass]( + director.getCtClass(classOf[Class[_]].getName), + director.getCtClass(classOf[Template].getName + "[]") + ), + new Array[CtClass](0), + tmplCtClass + ) + this.tmplCtClass.addConstructor(newCtCons) + } + def buildInstance(c : Class[_]) = { + val cons = c.getConstructor(classOf[Class[_]], classOf[Array[Template]]) + val tmpl = cons.newInstance(origClass,templates) + tmpl.asInstanceOf[Template] + } + override def buildMethodInit() = { + this.minimumArrayLength = 0; + var i : Int = 0 + for(e <- entries) { + if(e.isRequired() || e.isNullable()) { + this.minimumArrayLength = i+1; + } + i += 1 + } + } + + lazy val newInstanceDeclaration : String = { + + def defCon = "new " + origClass.getName + "();" + try{ + val c = origClass.getClassLoader.loadClass(origClass.getName + "$") + if(Modifier.isPublic(c.getModifiers)){ + val method = c.getMethod("apply") + + if(Modifier.isPublic(method.getModifiers) && + origClass.isAssignableFrom(method.getReturnType)){ + val staticField = c.getDeclaredField("MODULE$") + "%s.%s.apply();".format(c.getName,staticField.getName) + }else{ + defCon + } + }else{ + defCon + } + }catch{ + case e : ClassNotFoundException => { + defCon + } + } + } + + protected def buildPackMethodBody() : String = { + resetStringBuilder(); + buildString("{"); + buildString("%s _$$_t = (%s)$2;", this.origName, this.origName); + buildString("$1.packArray(%d);", entries.length.asInstanceOf[AnyRef]); + for(i <- 0 until entries.length) { + val e = entries(i) + + if(!e.isAvailable) { + buildString("$1.packNil();"); + }else{ + val t = e.getType; + if(t.isPrimitive()) { + buildString("$1.%s(_$$_t.%s());", primitivePackName(t), e.getName()); + } else { + buildString("if(_$$_t.%s() == null) {", e.getName()); + if(!e.isNullable() && !e.isOptional()) { + buildString("throw new %s();", classOf[MessageTypeException].getName()); + } else { + buildString("$1.packNil();"); + } + buildString("} else {"); + buildString(" this.templates[%d].pack($1, _$$_t.%s());", i.asInstanceOf[AnyRef], e.getName()); + buildString("}"); + } + } + + } + buildString("}"); + return getBuiltString(); + } + + + def buildUnpackMethodBody() : String = { + resetStringBuilder(); + buildString("{ "); + + buildString("%s _$$_t;", this.origName); + buildString("if($2 == null) {"); + buildString(" _$$_t = " + newInstanceDeclaration) //new %s();", this.origName); + buildString("} else {"); + buildString(" _$$_t = (%s)$2;", this.origName); + buildString("}"); + + buildString("int length = $1.unpackArray();"); + buildString("if(length < %d) {", this.minimumArrayLength.asInstanceOf[AnyRef]); + buildString(" throw new %s();", classOf[MessageTypeException].getName()); + buildString("}"); + + for(i <- 0 until this.minimumArrayLength) { + val e = entries(i); + if(!e.isAvailable()) { + buildString("$1.unpackObject();"); + }else{ + + buildString("if($1.tryUnpackNull()) {"); + if(e.isRequired()) { + // Required + nil => exception + buildString("throw new %s();", classOf[MessageTypeException].getName()); + } else if(e.isOptional()) { + // Optional + nil => keep default value + } else { // Nullable + // Nullable + nil => set null + buildString("_$$_t.%s_$eq(null);", e.getName()); + } + buildString("} else {"); + val t = e.getType(); + if(t.isPrimitive()) { + buildString("_$$_t.%s_$eq( $1.%s() );", e.getName(), primitiveUnpackName(t)); + } else { + buildString("_$$_t.%s_$eq( (%s)this.templates[%d].unpack($1, _$$_t.%s()));", e.getName(), e.getJavaTypeName(), i.asInstanceOf[AnyRef], e.getName()); + } + buildString("}"); + } + } + + for(i <- this.minimumArrayLength until entries.length) { + buildString("if(length <= %d) { return _$$_t; }", i.asInstanceOf[AnyRef]); + + val e = entries(i); + if(!e.isAvailable()) { + buildString("$1.unpackObject();"); + }else{ + + buildString("if($1.tryUnpackNull()) {"); + // this is Optional field becaue i >= minimumArrayLength + // Optional + nil => keep default value + buildString("} else {"); + val t = e.getType(); + if(t.isPrimitive()) { + buildString("_$$_t.%s_$eq( $1.%s());", e.getName(), primitiveUnpackName(t)); + } else { + buildString("_$$_t.%s_$eq( (%s)this.templates[%d].unpack($1, _$$_t.%s) );", e.getName(), e.getJavaTypeName(), i.asInstanceOf[AnyRef], e.getName()); + } + buildString("}"); + } + } + + // latter entries are all Optional + nil => keep default value + + buildString("for(int i=%d; i < length; i++) {", entries.length.asInstanceOf[AnyRef]); + buildString(" $1.unpackObject();"); + buildString("}"); + + buildString("return _$$_t;"); + + buildString("}"); + return getBuiltString(); + } + + protected override def buildConvertMethodBody() : String = { + resetStringBuilder(); + buildString("{ "); + + buildString("%s _$$_t;", this.origName); + buildString("if($2 == null) {"); + buildString(" _$$_t = " + newInstanceDeclaration) //new %s();", this.origName); + buildString("} else {"); + buildString(" _$$_t = (%s)$2;", this.origName); + buildString("}"); + + buildString("%s[] array = $1.asArray();", classOf[MessagePackObject].getName()); + buildString("int length = array.length;"); + buildString("if(length < %d) {", this.minimumArrayLength.asInstanceOf[AnyRef]); + buildString(" throw new %s();", classOf[MessageTypeException].getName()); + buildString("}"); + + buildString("%s obj;", classOf[MessagePackObject].getName()); + + for(i <- 0 until this.minimumArrayLength) { + val e = entries(i); + if(e.isAvailable()) { + buildString("obj = array[%d];", i.asInstanceOf[AnyRef]); + buildString("if(obj.isNil()) {"); + if(e.isRequired()) { + // Required + nil => exception + buildString("throw new %s();", classOf[MessageTypeException].getName()); + } else if(e.isOptional()) { + // Optional + nil => keep default value + } else { // Nullable + // Nullable + nil => set null + buildString("_$$_t.%s_$eq( null );", e.getName()); + } + buildString("} else {"); + val t = e.getType(); + if(t.isPrimitive()) { + buildString("_$$_t.%s_$eq( obj.%s());", e.getName(), primitiveConvertName(t)); + } else { + buildString("_$$_t.%s_$eq( (%s)this.templates[%d].convert(obj, _$$_t.%s()) );", e.getName(), e.getJavaTypeName(), i.asInstanceOf[AnyRef], e.getName()); + } + buildString("}"); + } + } + + for(i <- this.minimumArrayLength until entries.length) { + buildString("if(length <= %d) { return _$$_t; }", i.asInstanceOf[AnyRef]); + + val e = entries(i); + if(e.isAvailable()) { + + + buildString("obj = array[%d];", i.asInstanceOf[AnyRef]); + buildString("if(obj.isNil()) {"); + // this is Optional field becaue i >= minimumArrayLength + // Optional + nil => keep default value + buildString("} else {"); + val t = e.getType(); + if(t.isPrimitive()) { + buildString("_$$_t.%s_$eq( obj.%s());", e.getName(), primitiveConvertName(t)); + } else { + buildString("_$$_t.%s_$eq( (%s)this.templates[%d].convert(obj, _$$_t.%s) );", e.getName(), e.getJavaTypeName(), i.asInstanceOf[AnyRef], e.getName()); + } + buildString("}"); + } + } + + // latter entries are all Optional + nil => keep default value + + buildString("return _$$_t;"); + + buildString("}"); + return getBuiltString(); + } + } + +class ScalaFieldEntryReader extends IFieldEntryReader{ + + type Property = (Method,Method,Field) + type PropertySet = (String,Property) + + def readImplicitFieldOption(targetClass: Class[_]) = { + FieldOption.NULLABLE + } + + def convertFieldEntries(targetClass: Class[_], flist: FieldList) = { + + val list : List[FieldList.Entry] = flist.getList.asScala.toList + + list.map( s => { + if(s.isAvailable){ + val getter = targetClass.getMethod(s.getName) + if(getter.getReturnType.getName != "void"){ + val setter = targetClass.getMethod(s.getName + "_$eq",getter.getReturnType) + if(setter.getReturnType.getName == "void"){ + val f = try{targetClass.getDeclaredField(s.getName)} + catch{ + case e : NoSuchFieldException => null + } + val prop = (s.getName,(getter,setter,f)) + convertToScalaFieldEntry(prop) + }else{ + new ScalaFieldEntry("") + } + }else new ScalaFieldEntry("") + }else{ + new ScalaFieldEntry("") + } + }).toArray + } + + def readFieldEntries(targetClass: Class[_], implicitOption: FieldOption) = { + val props = findPropertyMethods(targetClass) filter( !hasAnnotation(_,classOf[Ignore])) + + val indexed = indexing(props) + indexed.map(convertToScalaFieldEntry(_)) + } + + + def setter_?(method : Method) : Boolean = { + Modifier.isPublic(method.getModifiers) && + method.getReturnType.getName == "void" && + method.getName.endsWith("_$eq") && + method.getParameterTypes.length == 1 + } + + def getter_?(method : Method) : Boolean = { + Modifier.isPublic(method.getModifiers) && + method.getReturnType.getName != "void" && + method.getParameterTypes.length == 0 + + } + + + + + def findPropertyMethods(targetClass: Class[_]) : Map[String,Property] = { + var getters : Map[String,Method] = ListMap.empty + var setters : Map[String,Method] = ListMap.empty + + def extractName( n : String) = { + n.substring(0,n.length - 4) + } + + //Find getters and setters + for( m <- targetClass.getMethods){ + if(setter_?(m)){ + setters +=(extractName(m.getName) -> m) + }else if(getter_?(m)){ + getters +=(m.getName -> m) + } + } + + var props : Map[String,Property] = ListMap.empty + + def sameType_?( getter : Method,setter : Method) = { + getter.getReturnType == setter.getParameterTypes()(0) + } + + for(g <- getters){ + setters.get(g._1).map( s => { + if(sameType_?(g._2,s)){ + + val name = g._1 + val f = try{targetClass.getDeclaredField(name)} + catch{ + case e : NoSuchFieldException => null + } + + //TODO add validation for field + props +=( name -> (g._2,s,f)) + } + }) + } + props + } + + def indexing( props : Map[String , Property]) : Array[PropertySet] = { + val indexed = new Array[PropertySet](props.size) + + var notIndexed : List[PropertySet] = Nil + + for(s <- props){ + val i = getAnnotation(s,classOf[Index]) + if(i == null){ + notIndexed = notIndexed :+ s + }else{ + val index = i.value + if(indexed(index) != null){ + throw new TemplateBuildException("duplicated index: "+index); + }else{ + try{ + indexed(index) = s + }catch{ + case e : Exception => { + throw new TemplateBuildException("invalid index: %s index must be 0 <= x < %s".format(index,indexed.length)); + } + } + } + } + } + + for( i <- 0 until indexed.length ){ + if(indexed(i) == null){ + indexed(i) = notIndexed.head + notIndexed = notIndexed.drop(1) + } + } + + + indexed + } + + def convertToScalaFieldEntry( propInfo : PropertySet) = { + val entry = new ScalaFieldEntry(propInfo._1) + entry.option = readFieldOption(propInfo,FieldOption.NULLABLE) + entry.normalType = readValueType(propInfo) + entry.genericType = readGenericType(propInfo) + + entry + } + + + def hasAnnotation[T <: JavaAnnotation](prop : PropertySet , classOfAnno : Class[T]) : Boolean = { + val getter = prop._2._1 + val setter = prop._2._2 + val field = prop._2._3 + getter.getAnnotation(classOfAnno) != null || + setter.getAnnotation(classOfAnno) != null || + {if(field != null) field.getAnnotation(classOfAnno) != null + else false} + } + def getAnnotation[T <: JavaAnnotation](prop : PropertySet , classOfAnno : Class[T]) : T = { + val getter = prop._2._1 + val setter = prop._2._2 + val field = prop._2._3 + + + + val a = getter.getAnnotation(classOfAnno) + if(a != null){ + a + }else{ + val b = setter.getAnnotation(classOfAnno) + if(b != null){ + b + }else if(field != null){ + field.getAnnotation(classOfAnno) + }else{ + null.asInstanceOf[T] + } + } + } + + def readFieldOption(prop : PropertySet , implicitOption : FieldOption) = { + if(hasAnnotation(prop,classOf[Required])){ + FieldOption.REQUIRED + } else if(hasAnnotation(prop,classOf[Optional])){ + FieldOption.OPTIONAL + } else if(hasAnnotation(prop,classOf[Nullable])){ + if(readValueType(prop).isPrimitive){ + FieldOption.REQUIRED + }else{ + FieldOption.NULLABLE + } + } else{ + if(implicitOption == FieldOption.NULLABLE){ + if(readValueType(prop).isPrimitive){ + FieldOption.REQUIRED + }else{ + FieldOption.NULLABLE + } + }else{ + implicitOption + } + } + + } + + def readValueType(prop : PropertySet) = { + prop._2._1.getReturnType + } + def readGenericType(prop : PropertySet) = { + prop._2._1.getGenericReturnType + } +} + +class ScalaFieldEntry(name : String) extends IFieldEntry{ + + def getName() = name + + def isNullable() = {getOption == FieldOption.NULLABLE} + + def isOptional = {getOption == FieldOption.OPTIONAL} + + def isRequired = {getOption == FieldOption.REQUIRED} + + def isAvailable = {getOption != FieldOption.IGNORE} + + var option : FieldOption = null + + var genericType : Type = null + + def getJavaTypeName = { + if(getType.isArray){ + //TODO implement here + getType.getName() + }else{ + getType.getName() + } + + } + + var normalType : Class[_] = null + + def getOption() = option + def getType() = normalType + def getGenericType() = genericType + +} \ No newline at end of file diff --git a/scala/src/main/scala/org/msgpack/ScalaMessagePack.scala b/scala/src/main/scala/org/msgpack/ScalaMessagePack.scala new file mode 100644 index 00000000..45b6f5fc --- /dev/null +++ b/scala/src/main/scala/org/msgpack/ScalaMessagePack.scala @@ -0,0 +1,76 @@ +package org.msgpack + +import template._ +import builder.{MessagePackMessageBuilderSelector, BuilderSelectorRegistry} +import template.javassist.BuildContextFactory +import collection.mutable.{MutableList, LinkedList} +import collection.mutable.{Map => MMap,HashMap => MHashMap} +; +/* + * Created by IntelliJ IDEA. + * User: takeshita + * Date: 11/03/10 + * Time: 1:34 + */ + +object ScalaMessagePack { + + { + // for scala object + BuilderSelectorRegistry.getInstance.insertBefore( + MessagePackMessageBuilderSelector.NAME, + new ScalaTemplateBuilderSelector) + + // register scala's list classes + TemplateRegistry.register(classOf[List[_]],new ImmutableListTemplate(AnyTemplate.getInstance)) + TemplateRegistry.registerGeneric(classOf[List[_]],new GenericTemplate1(classOf[ImmutableListTemplate])) + TemplateRegistry.register(classOf[Seq[_]],new ImmutableListTemplate(AnyTemplate.getInstance)) + TemplateRegistry.registerGeneric(classOf[Seq[_]],new GenericTemplate1(classOf[ImmutableListTemplate])) + TemplateRegistry.register(classOf[LinkedList[_]],new LinkedListTemplate(AnyTemplate.getInstance)) + TemplateRegistry.registerGeneric(classOf[LinkedList[_]],new GenericTemplate1(classOf[LinkedListTemplate])) + TemplateRegistry.register(classOf[MutableList[_]],new MutableListCTemplate(AnyTemplate.getInstance)) + TemplateRegistry.registerGeneric(classOf[MutableList[_]],new GenericTemplate1(classOf[MutableListCTemplate])) + + // register scala's map classes + TemplateRegistry.register(classOf[Map[_,_]],new ImmutableMapTemplate( + AnyTemplate.getInstance,AnyTemplate.getInstance)) + TemplateRegistry.registerGeneric(classOf[Map[_,_]],new GenericTemplate2( + classOf[ImmutableMapTemplate])) + TemplateRegistry.register(classOf[MMap[_,_]],new MutableHashMapTemplate( + AnyTemplate.getInstance,AnyTemplate.getInstance)) + TemplateRegistry.registerGeneric(classOf[MMap[_,_]],new GenericTemplate2( + classOf[MutableHashMapTemplate])) + TemplateRegistry.register(classOf[MHashMap[_,_]],new MutableHashMapTemplate( + AnyTemplate.getInstance,AnyTemplate.getInstance)) + TemplateRegistry.registerGeneric(classOf[MHashMap[_,_]],new GenericTemplate2( + classOf[MutableHashMapTemplate])) + + + + + } + + /** + * dammy method for initialize + */ + def init() = {} + + + def pack( obj : Any) = { + MessagePack.pack(obj.asInstanceOf[AnyRef]) + } + + def unpack[T]( buffer : Array[Byte])(implicit manifest : ClassManifest[T]) : T = { + MessagePack.unpack[T]( buffer, manifest.erasure.asInstanceOf[Class[T]]) + } + + def unpackD(buffer : Array[Byte]) = { + MessagePack.unpack(buffer) + } + + + + + + +} \ No newline at end of file diff --git a/scala/src/main/scala/org/msgpack/ScalaTemplateBuilder.scala b/scala/src/main/scala/org/msgpack/ScalaTemplateBuilder.scala new file mode 100644 index 00000000..f8cc2a7a --- /dev/null +++ b/scala/src/main/scala/org/msgpack/ScalaTemplateBuilder.scala @@ -0,0 +1,16 @@ +package org.msgpack; +/* + * Created by IntelliJ IDEA. + * User: takeshita + * Date: 11/03/10 + * Time: 1:52 + */ + +class ScalaTemplateBuilder { + + + def pack(v : Int) = { + + } + +} \ No newline at end of file diff --git a/scala/src/main/scala/org/msgpack/ScalaTemplateBuilderSelector.scala b/scala/src/main/scala/org/msgpack/ScalaTemplateBuilderSelector.scala new file mode 100644 index 00000000..b8b7c122 --- /dev/null +++ b/scala/src/main/scala/org/msgpack/ScalaTemplateBuilderSelector.scala @@ -0,0 +1,48 @@ +package org.msgpack + +import annotation.MessagePackMessage +import template.builder.BuilderSelector +import java.lang.reflect.Type +import template.javassist.BuildContextFactory +import template.JavassistTemplateBuilder +import java.lang.annotation.{Annotation => JAnnotation} +; +/* + * Created by IntelliJ IDEA. + * User: takeshita + * Date: 11/03/14 + * Time: 17:59 + */ + +class ScalaTemplateBuilderSelector extends BuilderSelector +{ + val b = new JavassistTemplateBuilder() + + { + b.setFieldEntryReader(new ScalaFieldEntryReader) + b.setBuildContextFactory(new BuildContextFactory{ + def createBuildContext(builder: JavassistTemplateBuilder) = { + new BuildContextForScala(builder) + } + }) + } + + def getName = "ScalaMessagePackMessageTemplateBuilderSelector"; + + def getTemplateBuilder(targetType: Type) = { + b + } + + def matchType(targetType: Type) = { + val c : Class[_] = targetType.asInstanceOf[Class[Object]] + isAnnotated(c, classOf[MessagePackMessage]) && + classOf[ScalaObject].isAssignableFrom(c)//c.isAssignableFrom(classOf[ScalaObject]) + + } + + private def isAnnotated(targetType : Class[_], annotation : Class[_ <: JAnnotation]) = { + targetType.getAnnotation(annotation) != null + + } + +} \ No newline at end of file diff --git a/scala/src/main/scala/org/msgpack/template/ImmutableListTemplate.scala b/scala/src/main/scala/org/msgpack/template/ImmutableListTemplate.scala new file mode 100644 index 00000000..5fab23ba --- /dev/null +++ b/scala/src/main/scala/org/msgpack/template/ImmutableListTemplate.scala @@ -0,0 +1,49 @@ +package org.msgpack.template + +import org.msgpack._ + +; +/* + * Created by IntelliJ IDEA. + * User: takeshita + * Date: 11/03/11 + * Time: 2:25 + */ + +class ImmutableListTemplate(elementTemplate : Template) extends Template{ + def unpack(pac: Unpacker, to: AnyRef) = { + + val length = pac.unpackArray(); + val array : Array[Object] = new Array(length) + + for(i <- 0 until length){ + array(i) = elementTemplate.unpack(pac,null) + } + + array.toList + + } + + def pack(pk: Packer, target: AnyRef) = { + + val list = try{target.asInstanceOf[List[_]]} + catch{ + case e : ClassCastException => { + throw new MessageTypeException("target is not List type: " + target.getClass()); + } + case e : NullPointerException => { + throw new MessageTypeException(new NullPointerException("target is null.")); + } + } + + pk.packArray(list.size) + for( e <- list){ + elementTemplate.pack(pk,e) + } + + } + + def convert(from: MessagePackObject, to: AnyRef) = { + from.asArray.map(elementTemplate.convert(_,null)).toList + } +} diff --git a/scala/src/main/scala/org/msgpack/template/ImmutableMapTemplate.scala b/scala/src/main/scala/org/msgpack/template/ImmutableMapTemplate.scala new file mode 100644 index 00000000..d4dd01f4 --- /dev/null +++ b/scala/src/main/scala/org/msgpack/template/ImmutableMapTemplate.scala @@ -0,0 +1,54 @@ +package org.msgpack.template + +import org.msgpack._ + +import scala.collection.JavaConverters._ + +/* + * Created by IntelliJ IDEA. + * User: takeshita + * Date: 11/03/11 + * Time: 11:11 + */ + +class ImmutableMapTemplate(keyTemplate : Template , valueTemplate : Template) extends Template { + + def unpack(pac: Unpacker, to: AnyRef) = { + + val length = pac.unpackMap() + val array : Array[(Object,Object)] = new Array(length) + + for(i <- 0 until length){ + array(i) = (keyTemplate.unpack(pac,null),valueTemplate.unpack(pac,null)) + } + + array.toMap + + } + + def pack(pk: Packer, target: AnyRef) = { + + val map = try{target.asInstanceOf[Map[_,_]]} + catch{ + case e : ClassCastException => { + throw new MessageTypeException("target is not List type: " + target.getClass()); + } + case e : NullPointerException => { + throw new MessageTypeException(new NullPointerException("target is null.")); + } + } + pk.packMap(map.size) + for( e <- map){ + keyTemplate.pack(pk,e._1) + valueTemplate.pack(pk,e._2) + } + + } + + def convert(from: MessagePackObject, to: AnyRef) = { + from.asMap.asScala.map(p => (keyTemplate.convert(p._1,null),valueTemplate.convert(p._2,null))).toMap + } + + + +} \ No newline at end of file diff --git a/scala/src/main/scala/org/msgpack/template/MutableListTemplate.scala b/scala/src/main/scala/org/msgpack/template/MutableListTemplate.scala new file mode 100644 index 00000000..c1973ae6 --- /dev/null +++ b/scala/src/main/scala/org/msgpack/template/MutableListTemplate.scala @@ -0,0 +1,56 @@ +package org.msgpack.template + +import org.msgpack.{MessagePackObject, Packer, Unpacker, Template} +import collection.mutable.{MutableList, LinearSeq, LinkedList} +; +/* + * Created by IntelliJ IDEA. + * User: takeshita + * Date: 11/03/11 + * Time: 2:37 + */ + +abstract class MutableListTemplate[T <: LinearSeq[_]](elementTemplate : Template) extends Template{ + def unpack(pac: Unpacker, to: AnyRef) = { + + val length = pac.unpackArray(); + + var list : LinearSeq[_] = if(to == null){ + toList(new Array[Object](0)) + }else{ + to.asInstanceOf[T] + } + for(i <- 0 until length){ + list = list :+ elementTemplate.unpack(pac,null) + } + + list + + } + def toList(array : Array[Object]) : T + + def pack(pk: Packer, target: AnyRef) = { + + val list = target.asInstanceOf[LinearSeq[_]] + pk.packArray(list.size) + for( e <- list){ + elementTemplate.pack(pk,e) + } + + } + + def convert(from: MessagePackObject, to: AnyRef) = { + toList(from.asArray.map(elementTemplate.convert(_,null))) + } +} + +class LinkedListTemplate(elementTemplate : Template) extends MutableListTemplate[LinkedList[_]](elementTemplate){ + def toList(array : Array[Object]) = LinkedList(array :_*) +} +class MutableListCTemplate(elementTemplate : Template) extends MutableListTemplate[MutableList[_]](elementTemplate){ + def toList(array : Array[Object]) = { + val list : MutableList[Object] = new MutableList + list ++= array + list + } +} \ No newline at end of file diff --git a/scala/src/main/scala/org/msgpack/template/MutableMapTemplate.scala b/scala/src/main/scala/org/msgpack/template/MutableMapTemplate.scala new file mode 100644 index 00000000..0503f069 --- /dev/null +++ b/scala/src/main/scala/org/msgpack/template/MutableMapTemplate.scala @@ -0,0 +1,70 @@ +package org.msgpack.template; +/* + * Created by IntelliJ IDEA. + * User: takeshita + * Date: 11/03/11 + * Time: 12:06 + */ + +import org.msgpack._ +import collection.mutable.{HashMap,Map => MMap} +import scala.collection.JavaConverters._ + +abstract class MutableMapTemplate[T <: MMap[_,_]](keyTemplate : Template , valueTemplate : Template) extends Template { + + def unpack(pac: Unpacker, to: AnyRef) = { + + val length = pac.unpackMap() + val array : Array[(Object,Object)] = new Array(length) + + for(i <- 0 until length){ + array(i) = (keyTemplate.unpack(pac,null),valueTemplate.unpack(pac,null)) + } + + toMap(array) + + } + + def toMap(array : Array[(Object,Object)]) : T + + + def pack(pk: Packer, target: AnyRef) = { + + val map = try{target.asInstanceOf[MMap[_,_]]} + catch{ + case e : ClassCastException => { + throw new MessageTypeException("target is not List type: " + target.getClass()); + } + case e : NullPointerException => { + throw new MessageTypeException(new NullPointerException("target is null.")); + } + } + pk.packMap(map.size) + for( e <- map){ + keyTemplate.pack(pk,e._1) + valueTemplate.pack(pk,e._2) + } + + + } + + def convert(from: MessagePackObject, to: AnyRef) = { + toMap(from.asMap.asScala.map(p => (keyTemplate.convert(p._1,null),valueTemplate.convert(p._2,null))).toArray) + + } + + + +} + + +class MutableHashMapTemplate(keyTemplate : Template , valueTemplate : Template) + extends MutableMapTemplate[HashMap[_,_]](keyTemplate,valueTemplate ) { + + def toMap(array : Array[(Object,Object)]) = { + HashMap(array :_*) + } + + + +} diff --git a/scala/src/test/scala/org/msgpack/ClassWithList.scala b/scala/src/test/scala/org/msgpack/ClassWithList.scala new file mode 100644 index 00000000..4fc5b4ff --- /dev/null +++ b/scala/src/test/scala/org/msgpack/ClassWithList.scala @@ -0,0 +1,21 @@ +package org.msgpack; +/* + * Created by IntelliJ IDEA. + * User: takeshita + * Date: 11/03/11 + * Time: 2:13 + */ + +import annotation.MessagePackMessage +import collection.mutable.{MutableList, LinkedList} + +@MessagePackMessage +class ClassWithList { + var immutable : List[String] = Nil + + var mutable : LinkedList[String] = LinkedList.empty + + var mutable2 : MutableList[String] = new MutableList + + //var tuple2 : (String,String) = (null,null) +} \ No newline at end of file diff --git a/scala/src/test/scala/org/msgpack/ClassWithMap.scala b/scala/src/test/scala/org/msgpack/ClassWithMap.scala new file mode 100644 index 00000000..6256dd76 --- /dev/null +++ b/scala/src/test/scala/org/msgpack/ClassWithMap.scala @@ -0,0 +1,19 @@ +package org.msgpack; +/* + * Created by IntelliJ IDEA. + * User: takeshita + * Date: 11/03/11 + * Time: 2:22 + */ + +import annotation.MessagePackMessage +import scala.collection.mutable.{Map => MMap} + +@MessagePackMessage +class ClassWithMap { + + var immutable : Map[String,String] = Map.empty + + var mutable : MMap[String,String] = MMap.empty + +} \ No newline at end of file diff --git a/scala/src/test/scala/org/msgpack/CollectionPackSpec.scala b/scala/src/test/scala/org/msgpack/CollectionPackSpec.scala new file mode 100644 index 00000000..ec305507 --- /dev/null +++ b/scala/src/test/scala/org/msgpack/CollectionPackSpec.scala @@ -0,0 +1,71 @@ +package org.msgpack + +import org.junit.runner.RunWith +import org.specs._ +import org.specs.matcher._ +import org.specs.runner.{ JUnitSuiteRunner, JUnit } +import scala.collection.mutable.LinkedList + +//import org.scalacheck.Gen + +/** + * Sample specification. + * + * This specification can be executed with: scala -cp <your classpath=""> ${package}.SpecsTest + * Or using maven: mvn test + * + * For more information on how to write or run specifications, please visit: http://code.google.com/p/specs. + * + */ +@RunWith(classOf[JUnitSuiteRunner]) +class CollectionPackSpec extends Specification with JUnit { + + "ScalaMessagePack" should { + "pack scala-list" in { + val c = new ClassWithList + + c.immutable = List("a","b","c") + c.mutable = LinkedList("a","b","d") + c.mutable2 ++= List("gh","fjei") + //c.tuple2 = ("hoge","wahoo") + + val b = ScalaMessagePack.pack(c) + val des = ScalaMessagePack.unpack[ClassWithList](b) + + des.immutable must be_==(c.immutable) + des.mutable must be_==(c.mutable) + //des.tuple2 must be_==(c.tuple2) + + val mpo = ScalaMessagePack.unpackD(b) + val des2 = mpo.convert(classOf[ClassWithList]) + + des2.immutable must be_==(c.immutable) + des2.mutable must be_==(c.mutable) + + } + "pack scala-map" in { + val c = new ClassWithMap + c.immutable = Map("a" -> "hoge","b" -> "fuga","c" -> "hehe") + c.mutable = scala.collection.mutable.Map("d" -> "oo" , "e" -> "aa") + + val b = ScalaMessagePack.pack(c) + val des = ScalaMessagePack.unpack[ClassWithMap](b) + + des.immutable must be_==(c.immutable) + des.mutable must be_==(c.mutable) + + val mpo = ScalaMessagePack.unpackD(b) + val des2 = mpo.convert(classOf[ClassWithMap]) + + des2.immutable must be_==(c.immutable) + des2.mutable must be_==(c.mutable) + + } + + } + + + + +} + diff --git a/scala/src/test/scala/org/msgpack/SampleClass.scala b/scala/src/test/scala/org/msgpack/SampleClass.scala new file mode 100644 index 00000000..4979ec61 --- /dev/null +++ b/scala/src/test/scala/org/msgpack/SampleClass.scala @@ -0,0 +1,77 @@ +package org.msgpack + +import annotation.MessagePackMessage +import annotation.{Optional, Index} +import java.util.Date +; +/* + * Created by IntelliJ IDEA. + * User: takeshita + * Date: 11/03/10 + * Time: 1:35 + */ + +@MessagePackMessage +class SampleClass { + var name : String = "hoge" + var number : Int = 2 + +} + +trait SampleTrait { + + var traitName : String = "" + + var traitNum : Int = 12 + +} + +class SampleClass2 extends SampleClass with SampleTrait { + + + @Index(3) + var sampleClass2Name : String = "sampleclass2" + + @Index(0) + def sampleClass2Num : Int = 22 + def sampleClass2Num_=(v : Int) = {} + + val notProperty : String ="This is not prop.Only getter" + + // wrong property + def wrongValue : Int = 53 + def wrongValue_=(v : String) = {} + +} + +object NotDefaultCons{ + + def apply() : NotDefaultCons2 = { + new NotDefaultCons2() + } +} +@MessagePackMessage +class NotDefaultCons(var name : String){ +} + +class NotDefaultCons2 extends NotDefaultCons("hoge") + +@MessagePackMessage +class BasicalTypes{ + + var intVar : Int = 0 + var longVar : Long = 0 + var shortVar : Short = 0 + var byteVar : Byte = 0 + var boolVar : Boolean = false + + var floatVar : Float = 0 + var doubleVar : Double = 0 + + var strVar : String = "" + + var dateVar : Date = null + + + +} \ No newline at end of file diff --git a/scala/src/test/scala/org/msgpack/ScalaFieldEntryReaderSpec.scala b/scala/src/test/scala/org/msgpack/ScalaFieldEntryReaderSpec.scala new file mode 100644 index 00000000..3eeffaad --- /dev/null +++ b/scala/src/test/scala/org/msgpack/ScalaFieldEntryReaderSpec.scala @@ -0,0 +1,120 @@ +package org.msgpack + +import org.junit.runner.RunWith +import org.specs._ +import org.specs.matcher._ +import org.specs.runner.{ JUnitSuiteRunner, JUnit } +//import org.scalacheck.Gen + +/** + * Sample specification. + * + * This specification can be executed with: scala -cp <your classpath=""> ${package}.SpecsTest + * Or using maven: mvn test + * + * For more information on how to write or run specifications, please visit: http://code.google.com/p/specs. + * + */ +@RunWith(classOf[JUnitSuiteRunner]) +class ScalaFieldEntryReaderSpec extends Specification with JUnit { + + "ScalaFieldEntryReader" should { + "check setter " in { + val reader = new ScalaFieldEntryReader() + + val c = classOf[SampleClass] + + reader.setter_?(c.getMethod("name")) must be_==(false) + reader.setter_?(c.getMethod("name_$eq",classOf[String])) must be_==(true) + } + "check getter " in { + val reader = new ScalaFieldEntryReader() + + val c = classOf[SampleClass] + + reader.getter_?(c.getMethod("name")) must be_==(true) + reader.getter_?(c.getMethod("name_$eq",classOf[String])) must be_==(false) + } + + "find props " in { + val reader = new ScalaFieldEntryReader() + + { + val c = classOf[SampleClass] + + val props = reader.findPropertyMethods(c) + + props.size must be_==(2) + props must haveKey("name") + props must haveKey("number") + } + + { + val c = classOf[SampleClass2] + + val props = reader.findPropertyMethods(c) + + println(props.keys) + + props.size must be_==(6) + props must haveKey("name") + props must haveKey("number") + props must haveKey("traitName") + props must haveKey("traitNum") + props must haveKey("sampleClass2Name") + props must haveKey("sampleClass2Num") + } + + } + + "indexing " in { + val reader = new ScalaFieldEntryReader() + + val c = classOf[SampleClass2] + + def printDecs(c : Class[_]) : Unit = { + println(c.getName + "---") + val ds = c.getDeclaredMethods + ds.foreach(m => {println(m) + println(m.getAnnotations.toList) + }) + if(c.getSuperclass != classOf[Object]){ + printDecs(c.getSuperclass) + } + } + printDecs(c) + + + + val props = reader.findPropertyMethods(c) + + val indexed = reader.indexing(props) + + println(indexed.map(_._1).toList) + + indexed.size must be_==(6) + indexed(0)._1 must be_==("sampleClass2Num") + indexed(3)._1 must be_==("sampleClass2Name") + indexed must notContain(null) + + } + + "read entries" in { + val reader = new ScalaFieldEntryReader() + + val c = classOf[SampleClass2] + import org.msgpack.template.FieldOption + + val e = reader.readFieldEntries(c, FieldOption.NULLABLE) + + e.size must be_==(6) + + } + + } + + + + +} + diff --git a/scala/src/test/scala/org/msgpack/ScalaMessagePackSpec.scala b/scala/src/test/scala/org/msgpack/ScalaMessagePackSpec.scala new file mode 100644 index 00000000..8f464000 --- /dev/null +++ b/scala/src/test/scala/org/msgpack/ScalaMessagePackSpec.scala @@ -0,0 +1,90 @@ +package org.msgpack + +import org.junit.runner.RunWith +import org.specs._ +import org.specs.matcher._ +import org.specs.runner.{ JUnitSuiteRunner, JUnit } +import java.util.Date + +//import org.scalacheck.Gen + +/** + * Sample specification. + * + * This specification can be executed with: scala -cp <your classpath=""> ${package}.SpecsTest + * Or using maven: mvn test + * + * For more information on how to write or run specifications, please visit: http://code.google.com/p/specs. + * + */ +@RunWith(classOf[JUnitSuiteRunner]) +class ScalaMessagePackTest extends Specification with JUnit /*with ScalaCheck*/ { + + "ScalaMessagePackTest" should { + "pack and unpack" in { + + val sc = new SampleClass() + sc.name = "Test object" + sc.number = 123456 + + println("Sampleclass is inherit ScalaObject " + classOf[ScalaObject].isAssignableFrom(classOf[SampleClass])) + new ScalaTemplateBuilderSelector().matchType(classOf[SampleClass]) must be_==(true) + val b = ScalaMessagePack.pack(sc) + + val deser = ScalaMessagePack.unpack[SampleClass](b) + + deser.name must be_==(sc.name) + deser.number must be_==(sc.number) + + val mso = ScalaMessagePack.unpackD(b) + val conv = mso.convert(classOf[SampleClass]) + conv.name must be_==(sc.name) + conv.number must be_==(sc.number) + } + "check basical types" in { + val v = new BasicalTypes + v.intVar = 20 + v.longVar = 11 + v.shortVar = 7 + v.byteVar = 1 + v.floatVar = 1.5f + v.doubleVar = 2.5 + v.strVar = "fugafuga" + v.dateVar = new Date(1233333) + + val b = ScalaMessagePack.pack(v) + val des : BasicalTypes = ScalaMessagePack.unpack[BasicalTypes](b) + + des.intVar must be_==(v.intVar) + des.longVar must be_==(v.longVar) + des.shortVar must be_==(v.shortVar) + des.byteVar must be_==(v.byteVar) + des.floatVar must be_==(v.floatVar) + des.doubleVar must be_==(v.doubleVar) + des.strVar must be_==(v.strVar) + des.dateVar must be_==(v.dateVar) + + + } + + "pack and unpack none-default constructor class" in { + + val sc = new NotDefaultCons("hehehehe") + + val b = ScalaMessagePack.pack(sc) + + val deser = ScalaMessagePack.unpack[NotDefaultCons](b) + + deser.name must be_==(sc.name) + + val mso = ScalaMessagePack.unpackD(b) + val conv = mso.convert(classOf[NotDefaultCons]) + conv.name must be_==(sc.name) + } + + + } + + +} + From 21f0d0bfc47ddc6d9092621705047f3bef385ba5 Mon Sep 17 00:00:00 2001 From: takeshita <takeshita@geishatokyo.com> Date: Mon, 4 Apr 2011 01:46:29 +0900 Subject: [PATCH 2/2] Delete moved class. (TemplateBuilder.java is moved to org.msgpack.template.builder) --- .../org/msgpack/template/TemplateBuilder.java | 381 ------------------ 1 file changed, 381 deletions(-) delete mode 100644 java/src/main/java/org/msgpack/template/TemplateBuilder.java diff --git a/java/src/main/java/org/msgpack/template/TemplateBuilder.java b/java/src/main/java/org/msgpack/template/TemplateBuilder.java deleted file mode 100644 index e3d25b29..00000000 --- a/java/src/main/java/org/msgpack/template/TemplateBuilder.java +++ /dev/null @@ -1,381 +0,0 @@ -// -// 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.template; - -import java.io.IOException; -import java.lang.reflect.*; -import java.lang.annotation.*; -import java.util.List; -import java.util.ArrayList; -import java.util.EnumSet; -import org.msgpack.*; -import org.msgpack.annotation.*; - -public abstract class TemplateBuilder { - public static class FieldEntry { - private Field field; - private FieldOption option; - - public FieldEntry() { - this.field = null; - this.option = FieldOption.IGNORE; - } - - public FieldEntry(FieldEntry e) { - this.field = e.field; - this.option = e.option; - } - - public FieldEntry(Field field, FieldOption option) { - this.field = field; - this.option = option; - } - - public Field getField() { - return field; - } - - public String getName() { - return field.getName(); - } - - public Class<?> getType() { - return field.getType(); - } - - public String getJavaTypeName() { - Class<?> type = field.getType(); - if(type.isArray()) { - return arrayTypeToString(type); - } else { - return type.getName(); - } - } - - public Type getGenericType() { - return field.getGenericType(); - } - - public FieldOption getOption() { - return option; - } - - public boolean isAvailable() { - return option != FieldOption.IGNORE; - } - - public boolean isRequired() { - return option == FieldOption.REQUIRED; - } - - public boolean isOptional() { - return option == FieldOption.OPTIONAL; - } - - public boolean isNullable() { - return option == FieldOption.NULLABLE; - } - - static String arrayTypeToString(Class<?> type) { - int dim = 1; - Class<?> baseType = type.getComponentType(); - while(baseType.isArray()) { - baseType = baseType.getComponentType(); - dim += 1; - } - StringBuilder sb = new StringBuilder(); - sb.append(baseType.getName()); - for (int i = 0; i < dim; ++i) { - sb.append("[]"); - } - return sb.toString(); - } - } - - // Override this method - public abstract Template buildTemplate(Class<?> targetClass, FieldEntry[] entries); - - // Override this method - public abstract Template buildOrdinalEnumTemplate(Class<?> targetClass, Enum<?>[] entries); - - // Override this method - public abstract Template buildArrayTemplate(Type arrayType, Type genericBaseType, Class<?> baseClass, int dim); - - - public Template buildTemplate(Class<?> targetClass, FieldList flist) throws NoSuchFieldException { - checkValidation(targetClass); - return buildTemplate(targetClass, convertFieldEntries(targetClass, flist)); - } - - public Template buildTemplate(Class<?> targetClass, FieldOption implicitOption) { - checkValidation(targetClass); - return buildTemplate(targetClass, readFieldEntries(targetClass, implicitOption)); - } - - public Template buildTemplate(Class<?> targetClass) { - FieldOption implicitOption = readImplicitFieldOption(targetClass); - return buildTemplate(targetClass, implicitOption); - } - - public Template buildOrdinalEnumTemplate(Class<?> targetClass) { - checkOrdinalEnumValidation(targetClass); - Enum<?>[] entries = (Enum<?>[])targetClass.getEnumConstants(); - return buildOrdinalEnumTemplate(targetClass, entries); - } - - public Template buildArrayTemplate(Type arrayType) { - Type baseType; - Class<?> baseClass; - int dim = 1; - if(arrayType instanceof GenericArrayType) { - GenericArrayType type = (GenericArrayType)arrayType; - baseType = type.getGenericComponentType(); - while(baseType instanceof GenericArrayType) { - baseType = ((GenericArrayType)baseType).getGenericComponentType(); - dim += 1; - } - if(baseType instanceof ParameterizedType) { - baseClass = (Class<?>)((ParameterizedType)baseType).getRawType(); - } else { - baseClass = (Class<?>)baseType; - } - } else { - Class<?> type = (Class<?>)arrayType; - baseClass = type.getComponentType(); - while(baseClass.isArray()) { - baseClass = baseClass.getComponentType(); - dim += 1; - } - baseType = baseClass; - } - return buildArrayTemplate(arrayType, baseType, baseClass, dim); - } - - private static Type getComponentType(Type arrayType) { - if(arrayType instanceof GenericArrayType) { - return ((GenericArrayType)arrayType).getGenericComponentType(); - } else { - return ((Class<?>)arrayType).getComponentType(); - } - } - - - private static TemplateBuilder instance; - static { - instance = selectDefaultTemplateBuilder(); - } - - private static TemplateBuilder selectDefaultTemplateBuilder() { - try { - // FIXME JavassistTemplateBuilder doesn't work on DalvikVM - if(System.getProperty("java.vm.name").equals("Dalvik")) { - return ReflectionTemplateBuilder.getInstance(); - } - } catch (Exception e) { - } - return JavassistTemplateBuilder.getInstance(); - } - - synchronized static void setInstance(TemplateBuilder builder) { - instance = builder; - } - - public static Template build(Class<?> targetClass) { - return instance.buildTemplate(targetClass); - } - - public static Template build(Class<?> targetClass, FieldOption implicitOption) { - return instance.buildTemplate(targetClass, implicitOption); - } - - public static Template build(Class<?> targetClass, FieldList flist) throws NoSuchFieldException { - return instance.buildTemplate(targetClass, flist); - } - - public static Template buildOrdinalEnum(Class<?> targetClass) { - return instance.buildOrdinalEnumTemplate(targetClass); - } - - public static Template buildArray(Type arrayType) { - return instance.buildArrayTemplate(arrayType); - } - - - private static void checkValidation(Class<?> targetClass) { - if(targetClass.isInterface()) { - throw new TemplateBuildException("cannot build template of interface"); - } - if(targetClass.isArray()) { - throw new TemplateBuildException("cannot build template of array class"); - } - if(targetClass.isPrimitive()) { - throw new TemplateBuildException("cannot build template of primitive type"); - } - } - - private static void checkOrdinalEnumValidation(Class<?> targetClass) { - if(!targetClass.isEnum()) { - throw new TemplateBuildException("tried to build ordinal enum template of non-enum class"); - } - } - - - static FieldEntry[] convertFieldEntries(Class<?> targetClass, FieldList flist) throws NoSuchFieldException { - List<FieldList.Entry> src = flist.getList(); - FieldEntry[] result = new FieldEntry[src.size()]; - for(int i=0; i < src.size(); i++) { - FieldList.Entry s = src.get(i); - if(s.isAvailable()) { - result[i] = new FieldEntry(targetClass.getDeclaredField(s.getName()), s.getOption()); - } else { - result[i] = new FieldEntry(); - } - } - return result; - } - - static FieldEntry[] readFieldEntries(Class<?> targetClass, FieldOption implicitOption) { - Field[] allFields = readAllFields(targetClass); - - /* index: - * @Index(0) int field_a; // 0 - * int field_b; // 1 - * @Index(3) int field_c; // 3 - * int field_d; // 4 - * @Index(2) int field_e; // 2 - * int field_f; // 5 - */ - List<FieldEntry> indexed = new ArrayList<FieldEntry>(); - int maxIndex = -1; - for(Field f : allFields) { - FieldOption opt = readFieldOption(f, implicitOption); - if(opt == FieldOption.IGNORE) { - // skip - continue; - } - - int index = readFieldIndex(f, maxIndex); - - if(indexed.size() > index && indexed.get(index) != null) { - throw new TemplateBuildException("duplicated index: "+index); - } - if(index < 0) { - throw new TemplateBuildException("invalid index: "+index); - } - - while(indexed.size() <= index) { - indexed.add(null); - } - indexed.set(index, new FieldEntry(f, opt)); - - if(maxIndex < index) { - maxIndex = index; - } - } - - FieldEntry[] result = new FieldEntry[maxIndex+1]; - for(int i=0; i < indexed.size(); i++) { - FieldEntry e = indexed.get(i); - if(e == null) { - result[i] = new FieldEntry(); - } else { - result[i] = e; - } - } - - return result; - } - - private static Field[] readAllFields(Class<?> targetClass) { - // order: [fields of super class, ..., fields of this class] - List<Field[]> succ = new ArrayList<Field[]>(); - int total = 0; - for(Class<?> c = targetClass; c != Object.class; c = c.getSuperclass()) { - Field[] fields = c.getDeclaredFields(); - total += fields.length; - succ.add(fields); - } - Field[] result = new Field[total]; - int off = 0; - for(int i=succ.size()-1; i >= 0; i--) { - Field[] fields = succ.get(i); - System.arraycopy(fields, 0, result, off, fields.length); - off += fields.length; - } - return result; - } - - private static FieldOption readImplicitFieldOption(Class<?> targetClass) { - MessagePackMessage a = targetClass.getAnnotation(MessagePackMessage.class); - if(a == null) { - return FieldOption.DEFAULT; - } - return a.value(); - } - - private static FieldOption readFieldOption(Field field, FieldOption implicitOption) { - int mod = field.getModifiers(); - if(Modifier.isStatic(mod) || Modifier.isFinal(mod)) { - return FieldOption.IGNORE; - } - - if(isAnnotated(field, Ignore.class)) { - return FieldOption.IGNORE; - } else if(isAnnotated(field, Required.class)) { - return FieldOption.REQUIRED; - } else if(isAnnotated(field, Optional.class)) { - return FieldOption.OPTIONAL; - } else if(isAnnotated(field, Nullable.class)) { - if(field.getDeclaringClass().isPrimitive()) { - return FieldOption.REQUIRED; - } else { - return FieldOption.NULLABLE; - } - } - - if(implicitOption != FieldOption.DEFAULT) { - return implicitOption; - } - - // default mode: - // transient : Ignore - // public : Required - // others : Ignore - if(Modifier.isTransient(mod)) { - return FieldOption.IGNORE; - } else if(Modifier.isPublic(mod)) { - return FieldOption.REQUIRED; - } else { - return FieldOption.IGNORE; - } - } - - private static int readFieldIndex(Field field, int maxIndex) { - Index a = field.getAnnotation(Index.class); - if(a == null) { - return maxIndex + 1; - } else { - return a.value(); - } - } - - private static boolean isAnnotated(AccessibleObject ao, Class<? extends Annotation> with) { - return ao.getAnnotation(with) != null; - } -} -