Skip to content

Instantly share code, notes, and snippets.

@frsyuki
Created September 25, 2010 08:16
Show Gist options
  • Save frsyuki/596611 to your computer and use it in GitHub Desktop.
Save frsyuki/596611 to your computer and use it in GitHub Desktop.
// Tempalteインタフェース
public interface Tempalte {
public Object convert(MessagePackObject from);
}
// 標準提供のテンプレート群(コンテナ型)
public class ListTemplate {
public ListTemplate(Template elementTemplate);
public Object convert(MessagePackObject from);
}
public class MapTemplate {
public MapTemplate(Template keyTemplate, Tempalte valueTempalte);
public Object convert(MessagePackObject from);
}
// 標準提供のテンプレート群(非コンテナ型)
public class StringTemplate {
public Object convert(MessagePackObject from);
static final StringTemplate instance = new StringTemplate();
static {
CustomConverter.register(String.class, instance);
}
private StringTemplate() { }
}
public class ByteArrayTemplate {
public Object convert(MessagePackObject from);
static final ByteArrayTemplate instance = new ByteArrayTemplate();
static {
CustomConverter.register(byte[].class, instance);
}
private ByteArrayTemplate() { }
}
// 他にも標準提供色々...
// LongTemplate
// BigIntegerTemplate
// アノテーションに対応するテンプレート群
// @MessagePackMessageアノテーションに対応
// PackerではMessagePackMessagePackerに相当
public abstract class ClassTemplate {
public static ClassTemplate createTempalte(Class target); // ClassTemplateを継承したクラスを生成して返す
public Object convert(MessagePackObject from);
}
// @MessagePackDelegateアノテーションに対応
// PackerではDelegatePackerに相当
public abstract class DelegateTemplate {
public static DelegateTemplate createTempalte(Class target, String memberName);
public Object convert(MessagePackObject from);
}
// @MessagePackOrdinalEnumアノテーションに対応
// PackerではOrdinalEnumPackerに相当
public abstract class OrdinalEnumTemplate {
public static OrdinalEnumTemplate createTempalte(Class targetEnumClass);
public Object convert(MessagePackObject from);
}
// MessagePackObjectにconvertメソッドを追加
public abstract class MessagePackObject {
public Object convert(Template tmpl) {
return tmpl.convert(this); // これだけ。
}
}
// ラッパメソッド群
public class Templates {
public static Template tClass(Class target) {
if(CustomConverter.isRegistered(target)) {
return CustomConverter.getRegistered(target);
}
if(/* @MessagePackMessageアノテーションが付いているなら */) {
Template tmpl = MessagePackMessageTemplate.createTemplate(target);
CustomConverter.register(target, tmpl);
return tmpl;
} else if(/* @MessagePackDelegateアノテーションが付いているなら */) {
Template tmpl = DelegateTemplate.createTemplate(obj.getClass(), memberName);
CustomPacker.register(obj.getClass(), tmpl);
return tmpl;
} else if(/* @MessagePackOrdinalEnumアノテーションが付いているなら */) {
Template tmpl = OrdinalEnumTemplate.createTemplate(obj.getClass());
CustomPacker.register(obj.getClass(), tmpl);
return tmpl;
}
// エラー
}
// 標準提供のテンプレート(コンテナ型)
public static Tempalte tList(Template elementTemplate) {
return new ListTemplate(elementTemplate);
}
public static Tempalte tMap(Template keyTemplate, Template valueTemplate) {
return new MapTemplate(keyTemplate, valueTemplate);
}
// 標準提供のテンプレート(非コンテナ型)
public static Tempalte tString() {
return new tClass(String.class);
// これと等価(こっちの方が速い):return StringTemplate.instance;
}
public static Tempalte tByteArray() {
return new tClass(byte[].class);
// これと等価(こっちの方が速い):return ByteArrayTemplate.instance;
}
}
// 使い方
// 標準提供されたクラスだけ使う
import static org.msgpack.Templates.*;
MessagePackObject obj = ...;
Map<String,byte[]> converted = (Map<String,byte[]>)tMap(tString(), tByteArray()).convert(obj);
// 自分が定義したクラスを使う
@MessagePackMessage
public class MyClass {
public int field1;
}
MessagePackObject obj = ...;
List<MyClass> converted = (List<MyClass>)tList(tClass(MyClass.class));
// 他人のクラスを使う
public class OthersClass { // アノテーションは付いていないし付けられない
public int field1;
}
// 事前にregisterしておく
CustomConverter.register(OthersClass.class, MessagePackMessageTemplate.createTemplate(OthersClass.class));
// ↑長いのでラッパがあった方が良いかも:CustomConverter.registerMessage(OthersClass.class);
OthersClass converted = (OthersClass)tClass(OthersClass.class);
//
// 使い方:
//
//
// ・自分で定義したクラスを型変換したい
// 1. @MessagePackMessageアノテーションを付ける
//
// ・自分で定義したクラスを型変換したい(独自の型変換方法で)
// 1. MessageConvertableインタフェースをimplementsする
//
// ・自分で定義したクラスを型変換したい(メンバ変数1つを直接型変換するように委譲)
// 1. @MessagePackaDelegate("memberName")アノテーションを付ける
//
//
// ・他人が定義したクラスを型変換したい
// 1. CustomConverter.register(ThatClass.class, MessagePackMessageTemplate.createTemplate(ThatClass.class)); を実行する
//
// ・他人が定義したクラスを型変換したい(独自の型変換方法で)
// 1. Templateインタフェースをimplementsしたクラスを作る
// 2. CustomConverter.register(ThatClass.class, new YourTemplateClass()); を実行する
//
// ・他人が定義したクラスを型変換したい(メンバ変数1つを直接型変換するように委譲)
// 2. CustomConverter.register(ThatClass.class, DelegateTemplate.createTemplate(ThatClass.class)); を実行する
//
//
// ・自分で定義したEnumを型変換したい
// 1. enumの定義で、値を表現するメンバ変数を持たせる
// 2. @MessagePackDelegate("memberName")アノテーションを付ける
//
// ・自分で定義したEnumを型変換したい(宣言する順番が変えたときに互換性が無くなってもいいよ)
// 1. @MessagePackOrdinalEnumアノテーションを付ける
//
//
// ・他人が定義したEnumを型変換したい
// 1. enumの定義で、値を表現するメンバ変数を持っていることを確認する
// 2. CustomConverter.register(ThatEnum.class, DelegateTempalte.createTempalte(ThatEnum.class, "memberName")); を実行する
//
// ・他人が定義したEnumを型変換したい(宣言する順番が変えたときに互換性が無くなってもいいよ)
// 1. CustomConverter.register(ThatEnum.class, OrdinalEnumTemplate.createTempalte(ThatEnum.class)); を実行する
//
// 所感:本当に命名にはセンスが無いので要検討。
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment