mirror of
https://github.com/msgpack/msgpack-c.git
synced 2025-03-19 04:52:59 +01:00
MessagePack for Scala moved to https://github.com/msgpack/msgpack/tree/master/scala
This commit is contained in:
parent
13ce808c47
commit
834d5a0e72
1
scala/README
Normal file
1
scala/README
Normal file
@ -0,0 +1 @@
|
|||||||
|
MessagePack for Scala moved to https://github.com/msgpack/msgpack-scala.
|
168
scala/pom.xml
168
scala/pom.xml
@ -1,168 +0,0 @@
|
|||||||
<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-devel</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>
|
|
||||||
</plugins>
|
|
||||||
</build>
|
|
||||||
</project>
|
|
@ -1,15 +0,0 @@
|
|||||||
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))
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
@ -1,593 +0,0 @@
|
|||||||
package org.msgpack
|
|
||||||
|
|
||||||
import _root_.javassist.{CtClass, CtNewConstructor}
|
|
||||||
import annotation._
|
|
||||||
import template._
|
|
||||||
import builder.JavassistTemplateBuilder.JavassistTemplate
|
|
||||||
import builder.{BuildContextBase, JavassistTemplateBuilder}
|
|
||||||
import java.lang.Class
|
|
||||||
import collection.immutable.{ListMap, TreeMap}
|
|
||||||
import java.lang.reflect.{Type, Modifier, Method, Field}
|
|
||||||
import java.lang.annotation.{Annotation => JavaAnnotation}
|
|
||||||
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 writeTemplate(targetClass : Class[_] , entries : Array[IFieldEntry],
|
|
||||||
templates : Array[Template], directoryName : String) = {
|
|
||||||
this.entries = entries;
|
|
||||||
this.templates = templates;
|
|
||||||
this.origClass = targetClass;
|
|
||||||
this.origName = this.origClass.getName();
|
|
||||||
write(this.origName, directoryName);
|
|
||||||
}
|
|
||||||
|
|
||||||
def loadTemplate(targetClass : Class[_] , entries : Array[IFieldEntry], templates : Array[Template]) = {
|
|
||||||
this.entries = entries;
|
|
||||||
this.templates = templates;
|
|
||||||
this.origClass = targetClass;
|
|
||||||
this.origName = this.origClass.getName();
|
|
||||||
load(this.origName);
|
|
||||||
}
|
|
||||||
|
|
||||||
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
|
|
||||||
}
|
|
||||||
case e : NoSuchMethodException => {
|
|
||||||
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))
|
|
||||||
}
|
|
||||||
})
|
|
||||||
}*/
|
|
||||||
// In some situation, reflection returns wrong ordered getter methods compare with declaration order.
|
|
||||||
// So to avoid such situation, list up props with setter methods
|
|
||||||
/*for(s <- setters){
|
|
||||||
getters.get(s._1).map( g => {
|
|
||||||
if(sameType_?(g,s._2)){
|
|
||||||
val name = s._1
|
|
||||||
val f = try{
|
|
||||||
targetClass.getDeclaredField(name)
|
|
||||||
}catch{
|
|
||||||
case e : NoSuchFieldException => null
|
|
||||||
}
|
|
||||||
|
|
||||||
props +=(name -> (g,s._2,f))
|
|
||||||
}
|
|
||||||
})
|
|
||||||
}*/
|
|
||||||
// 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) match{
|
|
||||||
case Some((g,s)) => props +=( name -> (g,s,f))
|
|
||||||
case None => {
|
|
||||||
if(name.startsWith("_")){
|
|
||||||
val sname = name.substring(1)
|
|
||||||
getterAndSetter(sname) 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)
|
|
||||||
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){
|
|
||||||
getType.getComponentType.getName + "[]"
|
|
||||||
|
|
||||||
}else{
|
|
||||||
getType.getName()
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
var normalType : Class[_] = null
|
|
||||||
|
|
||||||
def getOption() = option
|
|
||||||
def getType() = normalType
|
|
||||||
def getGenericType() = genericType
|
|
||||||
|
|
||||||
}
|
|
@ -1,75 +0,0 @@
|
|||||||
package org.msgpack
|
|
||||||
|
|
||||||
import template._
|
|
||||||
import builder.{AnnotationTemplateBuilderSelector, BuilderSelectorRegistry, 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(
|
|
||||||
AnnotationTemplateBuilderSelector.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)
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
}
|
|
@ -1,16 +0,0 @@
|
|||||||
package org.msgpack;
|
|
||||||
/*
|
|
||||||
* Created by IntelliJ IDEA.
|
|
||||||
* User: takeshita
|
|
||||||
* Date: 11/03/10
|
|
||||||
* Time: 1:52
|
|
||||||
*/
|
|
||||||
|
|
||||||
class ScalaTemplateBuilder {
|
|
||||||
|
|
||||||
|
|
||||||
def pack(v : Int) = {
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
@ -1,47 +0,0 @@
|
|||||||
package org.msgpack
|
|
||||||
|
|
||||||
import annotation.MessagePackMessage
|
|
||||||
import template.builder.BuilderSelector
|
|
||||||
import java.lang.reflect.Type
|
|
||||||
import template.builder.{JavassistTemplateBuilder, BuildContextFactory}
|
|
||||||
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
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
@ -1,49 +0,0 @@
|
|||||||
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
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,54 +0,0 @@
|
|||||||
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
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
}
|
|
@ -1,56 +0,0 @@
|
|||||||
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
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,70 +0,0 @@
|
|||||||
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 :_*)
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
}
|
|
@ -1,21 +0,0 @@
|
|||||||
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)
|
|
||||||
}
|
|
@ -1,19 +0,0 @@
|
|||||||
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
|
|
||||||
|
|
||||||
}
|
|
@ -1,71 +0,0 @@
|
|||||||
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 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.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)
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
@ -1,104 +0,0 @@
|
|||||||
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"
|
|
||||||
|
|
||||||
// Support getter/setter but must have _{name} field!
|
|
||||||
private var _sampleClass2Num : Int = 0
|
|
||||||
@Index(0)
|
|
||||||
def sampleClass2Num : Int = _sampleClass2Num
|
|
||||||
def sampleClass2Num_=(v : Int) = {_sampleClass2Num = v}
|
|
||||||
|
|
||||||
val notProperty : String ="This is not prop.Only getter"
|
|
||||||
|
|
||||||
private var _wrongValue : Int = 0
|
|
||||||
// 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
|
|
||||||
|
|
||||||
var intArray : Array[Int] = Array()
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
object FieldOrder{
|
|
||||||
val None = 0
|
|
||||||
val Offering = 11
|
|
||||||
val BeOffered = 12
|
|
||||||
val Friend = 13
|
|
||||||
val Block = 21
|
|
||||||
}
|
|
||||||
|
|
||||||
@MessagePackMessage
|
|
||||||
class FieldOrder{
|
|
||||||
|
|
||||||
var one : Int = 0
|
|
||||||
var two : String = "aaa"
|
|
||||||
var three : String = "bbb"
|
|
||||||
var four : String = ""
|
|
||||||
var five : Boolean = false
|
|
||||||
|
|
||||||
def six : Int = 1
|
|
||||||
def six_=(v : Int) = one = v
|
|
||||||
|
|
||||||
override def toString = "hogehoge"
|
|
||||||
|
|
||||||
}
|
|
@ -1,144 +0,0 @@
|
|||||||
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 ScalaFieldEntryReaderTest 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=" + props.keys)
|
|
||||||
|
|
||||||
props.size must be_==(6)
|
|
||||||
val l = props.toList
|
|
||||||
l(0)._1 must_== "name"
|
|
||||||
l(1)._1 must_== "number"
|
|
||||||
l(2)._1 must_== "sampleClass2Name"
|
|
||||||
l(3)._1 must_== "sampleClass2Num"
|
|
||||||
l(4)._1 must_== "traitName"
|
|
||||||
l(5)._1 must_== "traitNum"
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
"field order" in {
|
|
||||||
var reader = new ScalaFieldEntryReader
|
|
||||||
val c = classOf[FieldOrder]
|
|
||||||
|
|
||||||
println("Methods of FieldOrder class")
|
|
||||||
c.getMethods.foreach(println(_))
|
|
||||||
println("-- end --")
|
|
||||||
|
|
||||||
val props = reader.findPropertyMethods(c)
|
|
||||||
|
|
||||||
var index : Int = 0
|
|
||||||
val names = List("one","two","three","four","five","six")
|
|
||||||
for( p <- props.values){
|
|
||||||
p._1.getName must_== names(index)
|
|
||||||
index += 1
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
"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)
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
@ -1,92 +0,0 @@
|
|||||||
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)
|
|
||||||
v.intArray = Array(1,2,3,4,5)
|
|
||||||
|
|
||||||
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)
|
|
||||||
des.intArray must containAll(v.intArray)
|
|
||||||
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
"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)
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
Loading…
x
Reference in New Issue
Block a user