Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with
or
.
Download ZIP
Browse files

Up version to 0.6.1-SNAPSHOT

  • Loading branch information...
commit bacba7b77bc27df74de2a576dc516aa76995aef6 0 parents
takeshita authored
Showing with 1,770 additions and 0 deletions.
  1. +48 −0 .gitignore
  2. +199 −0 pom.xml
  3. +52 −0 src/main/scala/org/msgpack/ScalaMessagePack.scala
  4. +115 −0 src/main/scala/org/msgpack/ScalaTemplateRegistry.scala
  5. +13 −0 src/main/scala/org/msgpack/template/GenericImmutableListTemplate.scala
  6. +15 −0 src/main/scala/org/msgpack/template/GenericImmutableMapTemplate.scala
  7. +19 −0 src/main/scala/org/msgpack/template/GenericMutableListTemplate.scala
  8. +19 −0 src/main/scala/org/msgpack/template/GenericMutableMapTemplate.scala
  9. +43 −0 src/main/scala/org/msgpack/template/ImmutableListTemplate.scala
  10. +52 −0 src/main/scala/org/msgpack/template/ImmutableMapTemplate.scala
  11. +76 −0 src/main/scala/org/msgpack/template/MutableListTemplate.scala
  12. +68 −0 src/main/scala/org/msgpack/template/MutableMapTemplate.scala
  13. +289 −0 src/main/scala/org/msgpack/template/builder/JavassistScalaTemplateBuilder.scala
  14. +257 −0 src/main/scala/org/msgpack/template/builder/ScalaBuildContext.scala
  15. +51 −0 src/main/scala/org/msgpack/template/builder/ScalaFieldEntry.scala
  16. +23 −0 src/test/scala/org/msgpack/ClassWithList.scala
  17. +19 −0 src/test/scala/org/msgpack/ClassWithMap.scala
  18. +62 −0 src/test/scala/org/msgpack/CollectionPackSpec.scala
  19. +152 −0 src/test/scala/org/msgpack/PatternTest.scala
  20. +136 −0 src/test/scala/org/msgpack/SampleClasses.scala
  21. +62 −0 src/test/scala/org/msgpack/UsageTest.scala
48 .gitignore
@@ -0,0 +1,48 @@
+# 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
+
+#working dir
+target/*
+
+#intelliJ project
+*.iml
+*.ipr
+*.iws
199 pom.xml
@@ -0,0 +1,199 @@
+<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_${scala.version}</artifactId>
+ <version>0.6.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>
+
+
+ <profiles>
+ <profile>
+ <id>scala-2.8.1</id>
+ <properties>
+ <scala.version>2.8.1</scala.version>
+ </properties>
+ </profile>
+ <profile>
+ <id>scala-2.9.0</id>
+ <activation>
+ <activeByDefault>true</activeByDefault>
+ </activation>
+ <properties>
+ <scala.version>2.9.0</scala.version>
+ </properties>
+ </profile>
+ </profiles>
+
+<!--
+ <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.8</version>
+ <scope>test</scope>
+ </dependency>
+ <dependency>
+ <groupId>org.msgpack</groupId>
+ <artifactId>msgpack</artifactId>
+ <version>0.6.1-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>
+ </repository>
+ <snapshotRepository>
+ <uniqueVersion>true</uniqueVersion>
+ <id>msgpack.org</id>
+ <name>Repository at msgpack.org</name>
+ <url>file://${project.build.directory}/website/maven2/</url>
+ </snapshotRepository>-->
+ <repository>
+ <uniqueVersion>false</uniqueVersion>
+ <id>deploy.release</id>
+ <name>Repository for release</name>
+ <url>${deploy-release-url}</url>
+ </repository>
+ <snapshotRepository>
+ <uniqueVersion>true</uniqueVersion>
+ <id>deploy.snapshot</id>
+ <name>Repository for snapshot</name>
+ <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>
+ <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>
+</project>
52 src/main/scala/org/msgpack/ScalaMessagePack.scala
@@ -0,0 +1,52 @@
+package org.msgpack
+
+import `type`.Value
+import template._
+import collection.mutable.{MutableList, LinkedList}
+import collection.mutable.{Map => MMap, HashMap => MHashMap}
+import java.io.InputStream
+;
+/*
+ * Created by IntelliJ IDEA.
+ * User: takeshita
+ * Date: 11/03/10
+ * Time: 1:34
+ */
+
+object ScalaMessagePack {
+
+ val messagePack = new ScalaMessagePack()
+
+ def write( obj : Any) : Array[Byte] = {
+ messagePack.write(obj)
+ }
+ def writeT[T](obj : T)(implicit template : Template[T]) : Array[Byte] = {
+ messagePack.write(obj,template)
+ }
+
+ def read[T]( data : Array[Byte])(implicit manifest : Manifest[T]) : T = {
+ messagePack.read(data, manifest.erasure.asInstanceOf[Class[T]])
+ }
+
+ def read[T](data : InputStream)(implicit manifest : Manifest[T]) : T = {
+ messagePack.read(data, manifest.erasure.asInstanceOf[Class[T]])
+ }
+
+ def readTo[T](data : Array[Byte], obj : T) : T = {
+ messagePack.read(data,obj)
+ }
+
+ def readAsValue( data : Array[Byte]) : Value = {
+ messagePack.read(data)
+ }
+
+
+
+
+}
+
+class ScalaMessagePack extends MessagePack(new ScalaTemplateRegistry()){
+
+
+
+}
115 src/main/scala/org/msgpack/ScalaTemplateRegistry.scala
@@ -0,0 +1,115 @@
+package org.msgpack
+
+import template._
+import builder._
+import collection.mutable._
+
+/**
+ *
+ * User: takeshita
+ * Create: 11/10/12 21:21
+ */
+
+class ScalaTemplateRegistry extends TemplateRegistry(null){
+
+
+
+ {
+ def anyTemplate[T] = AnyTemplate.getInstance(this).asInstanceOf[Template[T]]
+
+ register(new ImmutableListTemplate[Any](anyTemplate))
+ register(new ImmutableMapTemplate(anyTemplate,anyTemplate))
+ register(new DoubleLinkedListTemplate(anyTemplate))
+ register(new LinkedListTemplate(anyTemplate))
+ register(new ListBufferTemplate(anyTemplate))
+ register(new MutableListCTemplate(anyTemplate))
+ register(new MutableHashMapTemplate(anyTemplate,anyTemplate))
+ register(new MutableListMapTemplate(anyTemplate,anyTemplate))
+ register(new MutableLinkedHashMapTemplate(anyTemplate,anyTemplate))
+ register(classOf[scala.collection.mutable.Map[_,_]],
+ new MutableHashMapTemplate(anyTemplate,anyTemplate))
+ register(classOf[scala.collection.mutable.Seq[_]],
+ new LinkedListTemplate(anyTemplate))
+ register(classOf[Seq[_]],new ImmutableListTemplate(anyTemplate))
+
+ // generics
+ registerGeneric(classOf[scala.collection.immutable.List[_]],new GenericImmutableListTemplate())
+ registerGeneric(classOf[scala.collection.immutable.Map[_,_]],new GenericImmutableMapTemplate())
+ registerGeneric(classOf[scala.collection.immutable.Seq[_]],new GenericImmutableListTemplate())
+
+ registerGeneric(classOf[DoubleLinkedList[_]],
+ new GenericMutableListTemplate[DoubleLinkedListTemplate[_]]())
+ registerGeneric(classOf[ListBuffer[_]],
+ new GenericMutableListTemplate[ListBufferTemplate[_]]())
+ registerGeneric(classOf[MutableList[_]],
+ new GenericMutableListTemplate[MutableListCTemplate[_]]())
+ registerGeneric(classOf[LinkedList[_]],
+ new GenericMutableListTemplate[LinkedListTemplate[_]]())
+ registerGeneric(classOf[scala.collection.mutable.Seq[_]],
+ new GenericMutableListTemplate[LinkedListTemplate[_]]())
+
+ registerGeneric(classOf[LinkedHashMap[_,_]],
+ new GenericMutableMapTemplate[MutableLinkedHashMapTemplate[_,_]])
+ registerGeneric(classOf[HashMap[_,_]],
+ new GenericMutableMapTemplate[MutableHashMapTemplate[_,_]])
+ registerGeneric(classOf[ListMap[_,_]],
+ new GenericMutableMapTemplate[MutableListMapTemplate[_,_]])
+ registerGeneric(classOf[scala.collection.mutable.Map[_,_]],
+ new GenericMutableMapTemplate[MutableHashMapTemplate[_,_]])
+
+ }
+
+ def register[T]( template : Template[T])(implicit manifest : Manifest[T]) : Unit = {
+ this.register(manifest.erasure,template)
+ }
+
+
+ override def createTemplateBuilderChain() = {
+ new ScalaTemplateBuilderChain(this)
+ }
+}
+
+class ScalaTemplateBuilderChain(registry : TemplateRegistry) extends TemplateBuilderChain(registry){
+
+ private def enableDynamicCodeGeneration: Boolean = {
+ try {
+ return !System.getProperty("java.vm.name").equals("Dalvik")
+ }
+ catch {
+ case e: Exception => {
+ return true
+ }
+ }
+ }
+
+ override def reset(registry: TemplateRegistry, cl: ClassLoader) = {
+ if (registry == null) {
+ throw new NullPointerException("registry is null")
+ }
+
+ templateBuilders.add(new ArrayTemplateBuilder(registry))
+
+
+ templateBuilders.add(new OrdinalEnumTemplateBuilder(registry))
+ if (enableDynamicCodeGeneration) {
+ val b = new JavassistScalaTemplateBuilder(registry)
+ if(cl != null){
+ b.addClassLoader(cl)
+ }
+ templateBuilders.add(b)
+ val builder = new JavassistTemplateBuilder(registry)
+ if (cl != null) {
+ builder.addClassLoader(cl)
+ }
+ templateBuilders.add(builder)
+ templateBuilders.add(new JavassistBeansTemplateBuilder(registry))
+ }
+ else {
+ val builder = new ReflectionTemplateBuilder(registry)
+ templateBuilders.add(builder)
+ templateBuilders.add(new OrdinalEnumTemplateBuilder(registry))
+ templateBuilders.add(new ReflectionBeansTemplateBuilder(registry))
+ }
+
+ }
+}
13 src/main/scala/org/msgpack/template/GenericImmutableListTemplate.scala
@@ -0,0 +1,13 @@
+package org.msgpack.template
+
+/**
+ *
+ * User: takeshita
+ * Create: 11/10/13 1:52
+ */
+
+class GenericImmutableListTemplate extends GenericTemplate{
+ def build(params: Array[Template[_]]) = {
+ new ImmutableListTemplate[Any](params(0).asInstanceOf[Template[Any]])
+ }
+}
15 src/main/scala/org/msgpack/template/GenericImmutableMapTemplate.scala
@@ -0,0 +1,15 @@
+package org.msgpack.template
+
+/**
+ *
+ * User: takeshita
+ * Create: 11/10/13 1:56
+ */
+
+class GenericImmutableMapTemplate extends GenericTemplate{
+ def build(params: Array[Template[_]]) = {
+ new ImmutableMapTemplate[Any,Any](
+ params(0).asInstanceOf[Template[Any]],
+ params(1).asInstanceOf[Template[Any]])
+ }
+}
19 src/main/scala/org/msgpack/template/GenericMutableListTemplate.scala
@@ -0,0 +1,19 @@
+package org.msgpack.template
+
+/**
+ *
+ * User: takeshita
+ * Create: 11/10/13 2:01
+ */
+
+class GenericMutableListTemplate[T <: MutableListTemplate[_,_]](implicit manifest : Manifest[T]) extends GenericTemplate{
+
+ val constructor = {
+ val c = manifest.erasure
+ c.getConstructor(classOf[Template[_]])
+ }
+
+ def build(params: Array[Template[_]]) = {
+ constructor.newInstance(params(0)).asInstanceOf[T]
+ }
+}
19 src/main/scala/org/msgpack/template/GenericMutableMapTemplate.scala
@@ -0,0 +1,19 @@
+package org.msgpack.template
+
+/**
+ *
+ * User: takeshita
+ * Create: 11/10/13 2:05
+ */
+
+class GenericMutableMapTemplate[T <: MutableMapTemplate[_,_,_]](implicit manifest : Manifest[T]) extends GenericTemplate{
+
+ val constructor = {
+ val c = manifest.erasure
+ c.getConstructor(classOf[Template[_]],classOf[Template[_]])
+ }
+
+ def build(params: Array[Template[_]]) = {
+ constructor.newInstance(params(0),params(1)).asInstanceOf[T]
+ }
+}
43 src/main/scala/org/msgpack/template/ImmutableListTemplate.scala
@@ -0,0 +1,43 @@
+package org.msgpack.template
+
+import org.msgpack._
+import packer.Packer
+import unpacker.Unpacker
+
+;
+/*
+ * Created by IntelliJ IDEA.
+ * User: takeshita
+ * Date: 11/03/11
+ * Time: 2:25
+ */
+
+class ImmutableListTemplate[T](elementTemplate : Template[T]) extends AbstractTemplate[List[T]]{
+
+
+ def read(u: Unpacker, to: List[T], required: Boolean) : List[T] = {
+ if(!required && u.trySkipNil){
+ return null.asInstanceOf[List[T]]
+ }
+ val length = u.readArrayBegin()
+ val seq = for(i <- 0 until length) yield elementTemplate.read(u,null.asInstanceOf[T],required)
+ u.readArrayEnd
+
+ seq.toList
+ }
+
+ def write(packer: Packer, v: List[T], required: Boolean) : Unit = {
+ if(v == null){
+ if(required){
+ throw new MessageTypeException("Attempted to write null")
+ }
+ packer.writeNil()
+ return
+ }
+
+ packer.writeArrayBegin(v.size)
+ v.foreach(e => elementTemplate.write(packer,e,required))
+ packer.writeArrayEnd()
+
+ }
+}
52 src/main/scala/org/msgpack/template/ImmutableMapTemplate.scala
@@ -0,0 +1,52 @@
+package org.msgpack.template
+
+import org.msgpack._
+
+import packer.Packer
+import scala.collection.JavaConverters._
+import unpacker.Unpacker
+
+/*
+ * Created by IntelliJ IDEA.
+ * User: takeshita
+ * Date: 11/03/11
+ * Time: 11:11
+ */
+
+class ImmutableMapTemplate[Key,Value](keyTemplate : Template[Key] , valueTemplate : Template[Value])
+ extends AbstractTemplate[Map[Key,Value]] {
+
+
+ def read(unpacker: Unpacker, to: Map[Key, Value], required: Boolean) : Map[Key,Value] = {
+ if(!required && unpacker.trySkipNil){
+ return null.asInstanceOf[Map[Key,Value]]
+ }
+
+ val length = unpacker.readMapBegin
+ val seq = for(i <- 0 until length ) yield (
+ keyTemplate.read(unpacker,null.asInstanceOf[Key],required),
+ valueTemplate.read(unpacker,null.asInstanceOf[Value],required))
+ unpacker.readMapEnd
+ Map(seq.toList :_*)
+ }
+
+ def write(packer: Packer, v: Map[Key, Value], required: Boolean) : Unit = {
+ if(v == null){
+ if(required){
+ throw new MessageTypeException("Attempted to write null")
+ }
+ packer.writeNil()
+ return
+ }
+
+ packer.writeMapBegin(v.size)
+ for( p <- v){
+ keyTemplate.write(packer,p._1,required)
+ valueTemplate.write(packer,p._2,required)
+ }
+ packer.writeMapEnd
+ }
+
+
+
+}
76 src/main/scala/org/msgpack/template/MutableListTemplate.scala
@@ -0,0 +1,76 @@
+package org.msgpack.template
+
+import org.msgpack.packer.Packer
+import org.msgpack.unpacker.Unpacker
+import org.msgpack.MessageTypeException
+import collection.mutable.{Seq => MSeq,DoubleLinkedList, MutableList, LinearSeq, LinkedList,ListBuffer}
+;
+/*
+ * Created by IntelliJ IDEA.
+ * User: takeshita
+ * Date: 11/03/11
+ * Time: 2:37
+ */
+
+abstract class MutableListTemplate[V,T <: MSeq[V]](elementTemplate : Template[V]) extends AbstractTemplate[T]{
+
+
+ def read(packer: Unpacker, to: T, required: Boolean) : T = {
+ if(!required && packer.trySkipNil){
+ return null.asInstanceOf[T]
+ }
+
+
+ var list : T = if(to == null){
+ createNewList()
+ }else{
+ to
+ }
+ val length = packer.readArrayBegin
+ for(i <- 0 until length){
+ list = (list :+ elementTemplate.read(packer,null.asInstanceOf[V])).asInstanceOf[T]
+ }
+ packer.readArrayEnd
+ list
+ }
+
+ def write(packer: Packer, v: T, required: Boolean) : Unit = {
+ if(v == null){
+ if(required){
+ throw new MessageTypeException("Attempted to write null")
+ }
+ packer.writeNil
+ return
+ }
+ packer.writeArrayBegin(v.size)
+ v.foreach(e => elementTemplate.write(packer,e))
+ packer.writeArrayEnd()
+ }
+
+ def createNewList() : T
+
+}
+
+class LinkedListTemplate[V](elementTemplate : Template[V])
+ extends MutableListTemplate[V,LinkedList[V]](elementTemplate){
+ def createNewList() = LinkedList.empty
+}
+class MutableListCTemplate[V](elementTemplate : Template[V])
+ extends MutableListTemplate[V,MutableList[V]](elementTemplate){
+ def createNewList() = {
+ MutableList.empty
+ }
+}
+class DoubleLinkedListTemplate[V](elementTemplate : Template[V])
+ extends MutableListTemplate[V,DoubleLinkedList[V]](elementTemplate){
+ def createNewList() = {
+ DoubleLinkedList.empty
+ }
+}
+
+class ListBufferTemplate[V](elementTemplate : Template[V])
+ extends MutableListTemplate[V,ListBuffer[V]](elementTemplate){
+ def createNewList() = {
+ ListBuffer.empty
+ }
+}
68 src/main/scala/org/msgpack/template/MutableMapTemplate.scala
@@ -0,0 +1,68 @@
+package org.msgpack.template;
+/*
+ * Created by IntelliJ IDEA.
+ * User: takeshita
+ * Date: 11/03/11
+ * Time: 12:06
+ */
+
+import org.msgpack._
+import packer.Packer
+import scala.collection.JavaConverters._
+import unpacker.Unpacker
+import collection.mutable.{LinkedHashMap, ListMap, HashMap, Map => MMap}
+
+abstract class MutableMapTemplate[K,V,T <: MMap[K,V]](keyTemplate : Template[K] , valueTemplate : Template[V])
+ extends AbstractTemplate[T] {
+
+ def read(unpacker: Unpacker, to: T, required: Boolean) : T = {
+ if(!required && unpacker.trySkipNil){
+ return null.asInstanceOf[T]
+ }
+ val map = if(to != null) to else createEmptyMap()
+ val length = unpacker.readMapBegin
+ for(i <- 0 until length){
+ map +=( keyTemplate.read(unpacker,null.asInstanceOf[K],required) ->
+ valueTemplate.read(unpacker,null.asInstanceOf[V],required))
+ }
+ unpacker.readMapEnd
+ map
+ }
+
+ def write(packer: Packer, v: T, required: Boolean) : Unit = {
+ if(v == null){
+ if(required){
+ throw new MessageTypeException("Attempted to write null")
+ }
+ packer.writeNil
+ return
+ }
+
+ packer.writeMapBegin(v.size)
+ for( p <- v){
+ keyTemplate.write(packer,p._1,required)
+ valueTemplate.write(packer,p._2,required)
+ }
+ packer.writeMapEnd
+
+ }
+
+
+ def createEmptyMap() : T
+}
+
+
+class MutableHashMapTemplate[K,V](keyTemplate : Template[K] , valueTemplate : Template[V])
+ extends MutableMapTemplate[K,V,HashMap[K,V]](keyTemplate,valueTemplate ) {
+ def createEmptyMap() = HashMap.empty
+}
+
+class MutableListMapTemplate[K,V](keyTemplate : Template[K] , valueTemplate : Template[V])
+ extends MutableMapTemplate[K,V,ListMap[K,V]](keyTemplate,valueTemplate ) {
+ def createEmptyMap() = ListMap.empty
+}
+
+class MutableLinkedHashMapTemplate[K,V](keyTemplate : Template[K] , valueTemplate : Template[V])
+ extends MutableMapTemplate[K,V,LinkedHashMap[K,V]](keyTemplate,valueTemplate ) {
+ def createEmptyMap() = LinkedHashMap.empty
+}
289 src/main/scala/org/msgpack/template/builder/JavassistScalaTemplateBuilder.scala
@@ -0,0 +1,289 @@
+//
+// MessagePack for Scala
+//
+// Copyright (C) 2009-2011 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 org.msgpack.unpacker.Unpacker
+import org.msgpack.packer.Packer
+import java.lang.{String, Class}
+import org.msgpack.template._
+import collection.immutable.ListMap
+import java.lang.annotation.{ Annotation => JAnnotation}
+import java.lang.reflect.{Field, Modifier, Method, Type}
+import org.msgpack.annotation._
+
+/**
+ *
+ * User: takeshita
+ * Create: 11/10/12 16:39
+ */
+
+class JavassistScalaTemplateBuilder(_registry : TemplateRegistry) extends JavassistTemplateBuilder(_registry){
+
+ val classPool = this.pool
+
+
+ // matching
+
+ override def matchType(targetType: Type, hasAnnotation: Boolean) = {
+
+ val c : Class[_] = targetType.asInstanceOf[Class[_]]
+ (isAnnotated(c, classOf[MessagePackMessage]) || isAnnotated(c, classOf[Message]) ) &&
+ classOf[ScalaObject].isAssignableFrom(c)
+ }
+
+ private def isAnnotated(targetType : Class[_], annotation : Class[_ <: JAnnotation]) = {
+ targetType.getAnnotation(annotation) != null
+
+ }
+
+ // build template
+
+
+
+ override def buildTemplate[T](targetClass: Class[T], entries: Array[FieldEntry]) = {
+ val templates : Array[Template[_]] = toTemplates(entries)
+ val bc = new ScalaBuildContext(this)
+
+ //cast manually
+ val sEntries = new Array[ScalaFieldEntry](entries.length)
+ for(i <- 0 until entries.length){
+ sEntries(i) = entries(i).asInstanceOf[ScalaFieldEntry]
+ }
+ bc.buildTemplate(targetClass,sEntries,templates).asInstanceOf[Template[T]]
+ }
+
+ private def toTemplates[T]( entries : Array[FieldEntry]) = {
+ val templates : Array[Template[_]] = new Array(entries.length)
+ var i = 0
+ for( e <- entries){
+ if(e.isAvailable){
+ val template = registry.lookup(e.getGenericType)
+ templates(i) = template
+ }else{
+ templates(i) = null
+ }
+ i += 1
+ }
+ templates
+ }
+
+
+ type Property = (Method,Method,Field)
+ type PropertySet = (String,Property)
+
+ override def toFieldEntries(targetClass: Class[_], from: FieldOption) = {
+ val props = findPropertyMethods(targetClass) filter( !hasAnnotation(_,classOf[Ignore]))
+ val indexed = indexing(props)
+ indexed.map(convertToScalaFieldEntry(_))
+ }
+
+ def setter_?(method : Method) : Boolean = {
+ val name = method.getName
+ Modifier.isPublic(method.getModifiers) &&
+ method.getReturnType.getName == "void" &&
+ !name.startsWith("_") &&
+ name.endsWith("_$eq") &&
+ method.getParameterTypes.length == 1
+ }
+
+ def getter_?(method : Method) : Boolean = {
+ !method.getName.startsWith("_") &&
+ 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)){
+ val valType = m.getParameterTypes()(0).getName
+ setters +=( (extractName(m.getName) + ":" + valType) -> m)
+ }else if(getter_?(m)){
+ val valType = m.getReturnType.getName
+ getters +=( (m.getName + ":" + valType) -> m)
+ }
+ }
+
+ var props : Map[String,Property] = ListMap.empty
+
+ def sameType_?( getter : Method,setter : Method) = {
+ getter.getReturnType == setter.getParameterTypes()(0)
+ }
+ // order of methods changes depends on call order, NOT declaration.
+
+ def getterAndSetter(name : String) : Option[(Method,Method)] = {
+ if(getters.contains(name) && setters.contains(name)){
+ val getter = getters(name)
+ val setter = setters(name)
+ if(getter.getReturnType == setter.getParameterTypes()(0)){
+ Some(getter -> setter)
+ }else{
+ None
+ }
+ }else None
+ }
+ def recursiveFind( clazz : Class[_]) : Unit = {
+ if(clazz.getSuperclass != classOf[Object]){
+ recursiveFind(clazz.getSuperclass)
+ }
+ for(f <- clazz.getDeclaredFields){
+ val name =f.getName
+ getterAndSetter(name + ":" + f.getType().getName()) match{
+ case Some((g,s)) => props +=( name -> (g,s,f))
+ case None => {
+ // if filed starts with "_" exists, it's also valid field for message pack.
+ // This rule is to support custom getter and setter.
+ if(name.startsWith("_")){
+ val sname = name.substring(1)
+ getterAndSetter(sname + ":" + f.getType().getName()) match{
+ case Some((g,s)) => props +=( sname -> (g,s,f))
+ case None =>
+ }
+ }
+ }
+ }
+ }
+ }
+ recursiveFind(targetClass)
+
+ 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,
+ readFieldOption(propInfo,FieldOption.OPTIONAL),
+ readValueType(propInfo),
+ readGenericType(propInfo),
+ propInfo._2._1,
+ propInfo._2._2
+ )
+
+ entry
+ }
+ def readFieldOption(prop : PropertySet , implicitOption : FieldOption) = {
+ if(hasAnnotation(prop,classOf[Optional])){
+ FieldOption.OPTIONAL
+ } else if(hasAnnotation(prop,classOf[NotNullable])){
+ FieldOption.NOTNULLABLE
+ }else if(hasAnnotation(prop,classOf[Ignore])){
+ FieldOption.IGNORE
+ }else{
+ if(readValueType(prop).isPrimitive){
+ FieldOption.NOTNULLABLE
+ }else{
+ FieldOption.OPTIONAL
+ }
+ }
+
+ }
+ def readValueType(prop : PropertySet) = {
+ prop._2._1.getReturnType
+ }
+ def readGenericType(prop : PropertySet) = {
+ prop._2._1.getGenericReturnType
+ }
+
+
+ def hasAnnotation[T <: JAnnotation](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 <: JAnnotation](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]
+ }
+ }
+ }
+
+ // builder context
+ override def createBuildContext() = {
+ new ScalaBuildContext(this)
+ }
+}
+
+abstract class JavassistScalaTemplate[T](var targetClass : Class[T], var templates : Array[Template[_]]) extends AbstractTemplate[T]{
+
+
+}
257 src/main/scala/org/msgpack/template/builder/ScalaBuildContext.scala
@@ -0,0 +1,257 @@
+//
+// MessagePack for Scala
+//
+// Copyright (C) 2009-2011 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.lang.{String, Class}
+import org.slf4j.{LoggerFactory, Logger}
+import javassist.{ClassPool, CtNewConstructor, CtClass}
+import org.msgpack.MessageTypeException
+import java.lang.reflect.{Constructor, Modifier}
+import org.msgpack.template.{TemplateRegistry, Template}
+
+/**
+ *
+ * User: takeshita
+ * Create: 11/10/12 17:53
+ */
+
+class ScalaBuildContext(builder : JavassistScalaTemplateBuilder) extends BuildContext[ScalaFieldEntry](builder){
+
+ private var logger : Logger = LoggerFactory.getLogger(classOf[ScalaBuildContext])
+
+
+ val pool = builder.pool
+ var originalClass : Class[_] = null
+ var templates : Array[Template[_]] = Array()
+ var entries : Array[ScalaFieldEntry] = Array()
+
+ def originalClassName = originalClass.getName()
+
+ def buildTemplate(targetClass: Class[_],
+ entries: Array[ScalaFieldEntry],
+ templates: Array[Template[_]]) = {
+ this.originalClass = targetClass
+ this.templates = templates
+ this.entries = entries
+ build(originalClassName)
+ }
+ def writeTemplate(targetClass: Class[_],
+ entries: Array[ScalaFieldEntry],
+ templates: Array[Template[_]], directoryName: String) = {}
+
+ def loadTemplate(targetClass: Class[_]) = {
+ this.originalClass = targetClass
+ load(originalClassName)
+ }
+
+
+
+ // build
+
+
+
+
+ def setSuperClass() = {
+ tmplCtClass.setSuperclass(pool.getCtClass(
+ classOf[JavassistScalaTemplate[_]].getName()
+ ))
+ }
+
+
+
+ def buildConstructor() = {
+ val newCtCons = CtNewConstructor.make(
+ Array[CtClass](pool.getCtClass(classOf[Class[_]].getName),
+ pool.getCtClass(classOf[Template[_]].getName + "[]")),
+ new Array[CtClass](0), tmplCtClass)
+ tmplCtClass.addConstructor(newCtCons)
+ }
+
+ def buildInstance(c: Class[_]) = {
+ var cons: Constructor[_] = c.getConstructor(
+ classOf[Class[Any]], classOf[Array[Template[Any]]])
+ cons.newInstance(originalClass,templates).asInstanceOf[Template[_]]
+ }
+
+ //for write
+
+ def buildWriteMethodBody() = {
+ val builder = new StringBuilder()
+
+ // null check
+ builder.append("""
+{
+ if($2 == null) {
+ if($3) {
+ throw new %s("Attempted to write null");
+ }
+ $1.writeNil();
+ return;
+ }
+""".format(classOf[MessageTypeException].getName()))
+
+ // constructor
+ builder.append(""" %s _$$_t = (%s) $2;
+ $1.writeArrayBegin(%d);
+""".format(originalClassName,originalClassName,entries.length))
+
+ // fields
+ var index = 0
+ for( e <- entries){
+ if(!e.available_?){
+ builder.append(" $1.writeNil();\n")
+ }else if(e.primitive_?){
+ writePrimitiveValue(builder,index,e)
+ }else if(e.nullable_?){
+ writeNullableMethod(builder,index,e)
+ }else{
+ writeNotNullableMethod(builder,index,e)
+ }
+ index += 1
+ }
+
+ // cap
+ builder.append(""" $1.writeArrayEnd();
+}""")
+
+ builder.toString()
+ }
+ protected def writePrimitiveValue(builder : StringBuilder,index : Int, entry : ScalaFieldEntry) = {
+ builder.append(""" $1.%s(_$$_t.%s());
+""".format(primitiveWriteName(entry.getType),entry.getName))
+ }
+
+ protected def writeNullableMethod(builder : StringBuilder,index : Int, entry : ScalaFieldEntry) = {
+ builder.append(""" if(_$$_t.%s() == null){
+ $1.writeNil();
+ }else{
+ templates()[%d].write($1, _$$_t.%s());
+ }
+""".format(entry.getName,index,entry.getName))
+ }
+
+ protected def writeNotNullableMethod(builder : StringBuilder,index : Int, entry : ScalaFieldEntry) = {
+ builder.append(""" if(_$$_t.%s() == null){
+ throw new %s();
+ }else{
+ templates()[%d].write($1, _$$_t.%s());
+ }
+""".format(entry.getName,classOf[MessageTypeException].getName(),index,entry.getName))
+ }
+
+ // for read
+
+ def buildReadMethodBody() = {
+ val builder = new StringBuilder
+ // init
+ builder.append("""
+{
+ if( !$3 && $1.trySkipNil()) {
+ return null;
+ }
+ %s _$$_t;
+ if ($2 == null){
+ _$$_t = %s;
+ } else {
+ _$$_t = (%s) $2;
+ }
+ $1.readArrayBegin();
+""".format(originalClassName,selectGoodConstructor,originalClassName))
+
+ // fields
+ var index = 0
+ for( e <- entries){
+ if(!e.available_?){
+ builder.append(" $1.skip();\n")
+ }else if(e.optional_?){
+ readOptionalMethod(builder,index,e)
+ }else if(e.primitive_?){
+ readPrimitive(builder,index,e)
+ }else{
+ readAnyRef(builder,index,e)
+ }
+
+ index += 1
+ }
+
+ //cap
+ builder.append("""
+ $1.readArrayEnd();
+ return _$$_t;
+}""")
+
+ builder.toString()
+ }
+
+ /**
+ * check constructor and companion class.
+ */
+ protected def selectGoodConstructor() : String = {
+ try{
+ val cons = originalClass.getConstructor()
+ if(Modifier.isPublic(cons.getModifiers)){
+ return "new %s()".format(originalClassName)
+ }
+ }catch{
+ case e : NoSuchMethodException =>
+ }
+ try{
+ val c = originalClass.getClassLoader.loadClass(originalClass.getName + "$")
+ if(Modifier.isPublic(c.getModifiers())){
+ val m = c.getMethod("apply")
+ if(Modifier.isPublic(m.getModifiers) &&
+ originalClass.isAssignableFrom(m.getReturnType)){
+
+ val staticField = c.getDeclaredField("MODULE$")
+ return "%s.%s.apply()".format(c.getName,staticField.getName)
+ }
+ }
+
+ }catch{
+ case e : ClassNotFoundException =>
+ case e : NoSuchMethodException =>
+ }
+ throw new MessageTypeException("Can't find plain constructor or companion object")
+
+ }
+
+ def readOptionalMethod(builder : StringBuilder , index : Int , entry : ScalaFieldEntry) = {
+ builder.append("""
+ if ( $1.trySkipNil()) {
+ _$$_t.%s_$eq(null);
+ }else{
+ """.format(entry.getName()))
+ readAnyRef(builder,index,entry)
+ builder.append("\n }")
+ }
+
+ def readPrimitive(builder : StringBuilder , index : Int , entry : ScalaFieldEntry) = {
+ builder.append("""
+ _$$_t.%s_$eq( $1.%s());""".format(entry.getName,primitiveReadName(entry.getType)))
+ }
+
+ def readAnyRef(builder : StringBuilder , index : Int , entry : ScalaFieldEntry) = {
+ builder.append("""
+ _$$_t.%s_$eq( (%s) (this.templates()[%d].read($1,_$$_t.%s()) ) );""".format(
+ entry.getName,entry.getJavaTypeName,index,entry.getName()))
+ }
+
+
+
+
+}
51 src/main/scala/org/msgpack/template/builder/ScalaFieldEntry.scala
@@ -0,0 +1,51 @@
+package org.msgpack.template.builder
+
+import org.msgpack.template.FieldOption
+import java.lang.reflect.{Method, Type}
+
+/**
+ *
+ * User: takeshita
+ * Create: 11/10/12 17:36
+ */
+
+class ScalaFieldEntry(name : String,
+ option : FieldOption,
+ normalType : Class[_],
+ genericType : Type,
+ getter : Method,
+ setter : Method
+ ) extends FieldEntry(option){
+
+
+
+ def getName = name
+
+ def getType = normalType
+
+ def getGenericType = genericType
+
+ def primitive_? = {
+ getType.isPrimitive
+ }
+
+ def nullable_? = {
+ option != FieldOption.NOTNULLABLE
+ }
+
+ def available_? = {
+ option != FieldOption.IGNORE
+ }
+
+ def optional_? = {
+ option == FieldOption.OPTIONAL
+ }
+
+ def get(target: AnyRef) = {
+ getter.invoke(target)
+ }
+
+ def set(target: AnyRef, value: AnyRef) = {
+ setter.invoke(target,value)
+ }
+}
23 src/test/scala/org/msgpack/ClassWithList.scala
@@ -0,0 +1,23 @@
+package org.msgpack;
+/*
+ * Created by IntelliJ IDEA.
+ * User: takeshita
+ * Date: 11/03/11
+ * Time: 2:13
+ */
+
+import annotation.MessagePackMessage
+import collection.mutable.{ListBuffer, MutableList, LinkedList}
+
+@MessagePackMessage
+class ClassWithList {
+ var immutable : List[String] = Nil
+
+ var mutable : LinkedList[String] = LinkedList.empty
+
+ var mutable2 : MutableList[String] = new MutableList
+
+ var mutable3 : ListBuffer[String] = ListBuffer.empty
+
+ //var tuple2 : (String,String) = (null,null)
+}
19 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
+
+}
62 src/test/scala/org/msgpack/CollectionPackSpec.scala
@@ -0,0 +1,62 @@
+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.{ListBuffer, 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 CollectionPackTest 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.mutable3 = ListBuffer("fdk","fei")
+ //c.tuple2 = ("hoge","wahoo")
+
+
+
+ val b = ScalaMessagePack.write(c)
+ val des = ScalaMessagePack.read[ClassWithList](b)
+
+ des must hasEqualProps(c).on("immutable","mutable2","mutable","mutable3")
+
+
+
+ }
+ "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.write(c)
+ val des = ScalaMessagePack.read[ClassWithMap](b)
+
+ des.immutable must be_==(c.immutable)
+ des.mutable must be_==(c.mutable)
+
+ }
+
+ }
+
+
+
+
+}
+
152 src/test/scala/org/msgpack/PatternTest.scala
@@ -0,0 +1,152 @@
+package org.msgpack
+
+import org.junit.runner.RunWith
+import org.specs.Specification
+import org.specs.runner.{JUnit, JUnitSuiteRunner}
+import org.specs.matcher.Matcher
+
+/**
+ *
+ * User: takeshita
+ * Create: 11/10/13 0:44
+ */
+
+@RunWith(classOf[JUnitSuiteRunner])
+class PatternTest extends Specification with JUnit{
+
+ "PrimitiveTypes" should{
+ "encode / decode" in{
+ val o = new PrimitiveTypes
+ o.byteVal = 33
+ o.intVal = 5829
+ o.shortVal = 232
+ o.longVal = 238912847
+ o.doubleVal = 230
+ o.floatVal = 328219.32f
+
+ checkOn(o,"intVal","byteVal","shortVal","longVal","doubleVal","floatVal")
+ }
+ }
+
+ "Indexing" should{
+ "index correctly" in{
+ val o = new Indexing()
+ o.one = 1
+ o.two = 2
+ o.three = 3
+ val decoded = checkOn(o,"zero","one","two","three")
+
+ // confirm field order
+ val data = ScalaMessagePack.write(o)
+ val mirror = ScalaMessagePack.read[IndexingMirror](data)
+ decoded must hasEqualProps(mirror).on("zero","one","two","three")
+ }
+ }
+
+ "Inherit" should{
+ "inherit parent class and trait" in{
+ val o = new Inherit()
+ o.targetClassName = "rin"
+ o.rootTraitName = "mio"
+ o.rootTraitNum = 89284
+ o.rootName = "kudo"
+ o.rootNum = 238492
+ checkOn(o,"targetClassName","rootTraitName","rootTraitNum","rootName","rootNum")
+ }
+ }
+
+ "CustomGetterSetter" should{
+ "target custum prop" in{
+ val o = new CustomGetterSetter
+ o.myNumber = 382902
+ checkOn(o,"myNumber")
+ }
+ }
+
+ "Options" should{
+ "throw error if name is null" in{
+ val o = new Options
+ o.name = null
+ ScalaMessagePack.write(o) must throwA[MessageTypeException]
+ }
+ "ignore @ignore" in{
+ val o = new Options
+ o.name = "sasasegawa sasami"
+ o.ignoreNum = 290391
+ val decode = checkOn(o,"name")
+ decode.ignoreNum must_== new Options().ignoreNum // default value
+ }
+ }
+
+ "WithCompanion" should{
+ "encode / decode" in{
+ checkOn(new WithCompanion("saegusa haruka"), "name")
+ }
+ }
+
+ "ConstructorOverload" should{
+ "encode / decode" in{
+ checkOn(new ConstructorOverload("futaki kanata"), "name")
+ }
+ }
+
+ "ReferSelfClass" should{
+ "encode / decode" in{
+ val o = new ReferSelfClass("top")
+ o.myClass = new ReferSelfClass("myClass")
+ o.myList = o.myList :+ new ReferSelfClass("myList")
+ o.myMap = o.myMap + ("myMap" -> new ReferSelfClass("myMap"))
+ val decode = checkOn(o,"name")
+
+ decode.myClass must hasEqualProps(o.myClass).on("name")
+ decode.myList(0) must hasEqualProps(o.myList(0)).on("name")
+ decode.myMap("myMap") must hasEqualProps(o.myMap("myMap")).on("name")
+ }
+
+ }
+
+ "Cycle" should{
+ "encode / decode" in{
+ checkOn(new CycleA,"name")
+ }
+ }
+
+
+
+ def checkOn[T <: AnyRef](obj : T , propNames : String*)(implicit manifest : Manifest[T]) : T = {
+ val data = ScalaMessagePack.write(obj)
+ val decode = ScalaMessagePack.read[T](data)
+ decode must hasEqualProps(obj).on(propNames :_*)
+ decode
+ }
+
+}
+
+case class hasEqualProps[T <: AnyRef]( expected : T){
+
+
+ def on( propNames : String*) = {
+ new PropMatcher(propNames.toList)
+ }
+
+ class PropMatcher(propNames : List[String]) extends Matcher[AnyRef]{
+ def apply(a: => AnyRef) : (Boolean,String,String) = {
+ val actual : AnyRef = a
+
+ for(propName <- propNames){
+ val eV = getValue(expected,propName)
+ val aV = getValue(actual,propName)
+ if(eV != aV ){
+ return (false,"","prop:%s expect ( %s ) but ( %s )".format(propName,eV , aV))
+ }
+ }
+ (true,"ok","")
+ }
+
+ def getValue( obj : AnyRef, propName : String) = {
+ obj.getClass.getMethod(propName).invoke(obj)
+ }
+
+ }
+
+}
136 src/test/scala/org/msgpack/SampleClasses.scala
@@ -0,0 +1,136 @@
+package org.msgpack
+
+import annotation.{Ignore, NotNullable, Index, Message}
+
+/**
+ * To test primitive types
+ * User: takeshita
+ * Create: 11/10/12 23:18
+ */
+@Message
+class PrimitiveTypes{
+
+ var intVal : Int = 1
+ var longVal : Long = 2
+ var shortVal : Short = 3
+ var byteVal : Byte = 4
+ var floatVal : Float = 5.0f
+ var doubleVal : Double = 6.0
+}
+
+
+
+@Message
+class Indexing{
+
+ @Index(2)
+ var two : Int = 0
+ var one : Int = 0
+ var three : Int = 0
+ @Index(0)
+ var zero : Int = 0
+}
+
+/**
+ * For checking indexing
+ */
+@Message
+class IndexingMirror{
+
+ var zero : Int = 0
+ var one : Int = 0
+ var two : Int = 0
+ var three : Int = 0
+}
+
+
+class RootClass{
+ var rootName : String = "rootClass"
+ var rootNum : Int = 234
+}
+
+trait RootTrait{
+ var rootTraitName : String = "root"
+ var rootTraitNum : Int = 23
+}
+
+@Message
+class Inherit extends RootClass with RootTrait{
+
+ var targetClassName : String = "targetClass"
+}
+@Message
+class CustomGetterSetter{
+
+ private var _myNumber : Int = 0
+
+ def myNumber : Int = _myNumber
+ def myNumber_=( v: Int) : Unit = _myNumber = v
+}
+
+@Message
+class OverloadVars{
+
+ private var _id : Long = 0
+
+ def id_=( v : String) = _id = v.toLong
+ def id_=( v : Long) = _id = v
+ def id : Long = _id
+ def id_=(obj : Any) = _id = obj.toString.toLong
+}
+
+@Message
+class Options{
+
+ @NotNullable
+ var name : String = ""
+
+ @Ignore
+ var ignoreNum : Int = 452
+}
+
+object WithCompanion{
+ def apply() = new WithCompanion2()
+}
+
+@Message
+class WithCompanion(var name : String){
+
+}
+
+@Message
+class WithCompanion2 extends WithCompanion("hoge")
+
+@Message
+class ConstructorOverload(var name : String){
+
+ def this() = this("fuga")
+}
+
+@Message
+class ReferSelfClass(var name : String){
+
+ def this() = this("")
+
+ var myClass : ReferSelfClass = null
+ var myList : List[ReferSelfClass] = List()
+ var myMap : Map[String,ReferSelfClass] = Map.empty
+
+}
+
+@Message
+class CycleA{
+ var name : String = ""
+ var cycleB : CycleB = new CycleB()
+}
+
+@Message
+class CycleB{
+ var cycleA : CycleA = null
+ var cycleC : CycleC = new CycleC()
+}
+
+@Message
+class CycleC{
+ var cycleA : CycleA = null
+}
62 src/test/scala/org/msgpack/UsageTest.scala
@@ -0,0 +1,62 @@
+package org.msgpack
+
+import annotation.Message
+import org.junit.runner.RunWith
+import org.specs.runner.{JUnit, JUnitSuiteRunner}
+import org.specs._
+import org.specs.matcher._
+
+/**
+ *
+ * User: takeshita
+ * Create: 11/10/12 23:17
+ */
+
+@RunWith(classOf[JUnitSuiteRunner])
+class UsageTest extends Specification with JUnit{
+
+ "Normal usage" should{
+
+ "write and read" in{
+ val user = new User
+ user.id = 439
+ user.name = "sizuru"
+ user.roles = Array("user")
+ user.profile.gender = 2
+
+ val data = ScalaMessagePack.write(user)
+ data must notBeNull
+ for(b <- data){
+ print("%02x ".format(b))
+ }
+ println("")
+
+ val recover = ScalaMessagePack.read[User](data)
+
+ recover.id must_== user.id
+ recover.name must_== user.name
+ recover.roles.toList must_== user.roles.toList
+ recover.profile.gender must_== user.profile.gender
+
+ }
+
+ }
+
+
+}
+@Message
+class User{
+
+ var id : Long = 0
+ var name : String = ""
+ var roles : Array[String] = Array("admin","user")
+
+ var profile : Profile = new Profile
+
+}
+
+@Message
+class Profile{
+ var gender : Int = 1
+}
+

0 comments on commit bacba7b

Please sign in to comment.
Something went wrong with that request. Please try again.