
org.msgpack.template.builder.ScalaBuildContext.scala Maven / Gradle / Ivy
The newest version!
//
// 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) = {}
/* 0.6.1
def loadTemplate(targetClass: Class[_]) = {
this.originalClass = targetClass
load(originalClassName)
}*/
def loadTemplate(targetClass: Class[_],
entries: Array[ScalaFieldEntry],
templates: Array[Template[_]]) = {
this.originalClass = targetClass
this.templates = templates
this.entries = entries
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 if(classOf[Enumeration].isAssignableFrom(e.getType)){
writeEnumValueMethod(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))
}
protected def writeEnumValueMethod(builder : StringBuilder,index : Int, entry : ScalaFieldEntry) = {
builder.append(""" if(_$$_t.%s() == null){
throw new %s();
}else{
$1.int(_$$_t.%s().id());
}
""".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 if(classOf[Enumeration].isAssignableFrom(e.getType)){
readEnumValue(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 =>
case e : NoSuchFieldException =>
}
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 }")
readAnyRef(builder,index,entry)
}
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()))
}
def readEnumValue(builder : StringBuilder , index : Int , entry : ScalaFieldEntry) = {
builder.append("""
try{
_$$_t.%s_$eq( %s.apply($1.int()));
}catch(Exception e)
_$$_t.%s_$eq(null);
}""".format(entry.getName,entry.getType.getName,entry.getName))
}
}
© 2015 - 2025 Weber Informatics LLC | Privacy Policy