Skip to content

Instantly share code, notes, and snippets.

@frsyuki
Created September 26, 2010 17:20
Show Gist options
  • Save frsyuki/598124 to your computer and use it in GitHub Desktop.
Save frsyuki/598124 to your computer and use it in GitHub Desktop.
// カスタムシリアライザ(自分をシリアライズ):直接使うことはまず無い
public interface MessagePackable {
public void messagePack(Packer);
}
// カスタムデシリアライザ(自分にマージ):直接使うことはまず無い
public interface MessageUnpackable {
public void messageUnpack(Unpacker);
}
// カスタム型変換(自分にマージ):直接使うことはまず無い
public interface MessageConvertable {
public void messageConvert(MessagePackObject);
}
// カスタムシリアライザ:シリアライズ時に使う人もいるかも知れない
public interface MessagePacker {
public void pack(Packer, Object);
}
// カスタムデシリアライザ:直接使うことはまず無い
public interface MessageUnpacker {
public Object unpack(Unpacker);
}
// カスタム型変換:直接使うことはまず無い
public interface MessageConverter {
public Object convert(MessagePackObject obj);
}
// 型情報を表現する:デシリアライズ・型変換時に使う
public interface Template extends MessageUnpacker, MessageConverter {
}
public abstract class AbstractTemplate implements MessageUnpacker {
public Object unpack(Unpacker pac) {
return convert(pac.unpackObject());
}
public Object convert(MessagePackObject from);
}
// 直接使うことはまずない。CustomMessageを経由して使う
class CustomOperatorRegistry<E> {
public static void register(Class target, E converter) {
map.put(target, converter);
}
public static E get(Class target) {
return map.get(target);
}
public static boolean isRegistered(Class target) {
return map.containsKey(target);
}
private static Map<Class, E> map = new HashMap<Class, E>();
}
// 直接使うことはまずない。CustomMessageを経由して使う
public class CustomPacker extends CustomOperatorRegistry<MessagePacker> {
}
// 直接使うことはまずない。CustomMessageを経由して使う
public class CustomUnpacker extends CustomOperatorRegistry<MessageUnpacker> {
}
// 直接使うことはまずない。CustomMessageを経由して使う
public class CustomConverter extends CustomOperatorRegistry<MessageConverter> {
}
// カスタムシリアライザ・デシリアライザ・型変換を登録するクラス
public class CustomMessage {
public static void registerPacker(Class target, MessagePacker packer) {
CustomPacker.register(target, packer);
}
public static void registerTemplate(Class target, Template tmpl) {
CustomUnpacker.register(target, packer);
CustomConverter.register(target, packer);
}
}
// Packer
public void pack(Object obj) {
// primitive types...
if(obj instanceof MessagePackable) {
obj.messagePack(this);
return;
}
MessagePacker packer = CustomPacker.getRegistered(obj.getClass());
if(packer != null) {
packer.pack(this, obj);
return;
}
Class klass = obj.getClass();
if(/*@MessagePackMessageアノテーションをチェック*/) {
MessagePacker packer = FieldPacker.create(klass); // リフレクションでシリアライズするpackerを作成
CustomMessage.register(klass, packer);
packer.pack(this, obj);
return;
}
// @MessagePackDelegateアノテーションをチェック => DelegatePacker.create(klass)
// @MessagePackOrdinalEnumアノテーションをチェック => OrdinalEnumPacker.create(klass)
// エラー
}
// Unpacker
public Object unpack(MessageUnpacker unpacker) {
return unpacker.unpack(this);
}
public Object unpack(MessageUnpackable obj) {
return obj.messageUnpack(this);
}
public Object unpack(Class klass) {
if(klass.isAssignableFrom(MessageUnpackable)) {
Object obj = klass.newInstance();
((MessageUnpackable)obj).messageUnpack(this);
return obj;
}
MessageUnpacker unpacker = CustomUnpacker.get(klass);
if(unpacker != null) {
return unpacker.unpack(this);
}
if(/*@MessagePackMessageアノテーションをチェック*/) {
Template tmpl = FieldTemplate.create(klass); // リフレクションでデシリアライズ・型変換するtemplateを作成
CustomMessage.register(klass, tmpl);
return tmpl.unpack(this);
}
// @MessagePackDelegateアノテーションをチェック => DelegateTemplate.create(klass)
// @MessagePackOrdinalEnumアノテーションをチェック => OrdinalEnumTemplate.create(klass)
// エラー
}
public class ClassTemplate implements Template {
private Class klass;
public ClassTemplate(Class klass) {
this.klass = klass;
}
public Object unpack(Unpacker pac) {
return pac.unpack(klass);
}
public Object convert(MessagePackObject from) {
MessageConverter converter = CustomConverter.get(klass);
if(converter != null) {
return converter.convert(from);
}
if(/* @MessagePackMessageアノテーションをチェック*/) {
Template tmpl = FieldTemplate.createTemplate(klass);
CustomMessage.register(klass, tmpl);
return tmpl;
}
// @MessagePackDelegateアノテーションをチェック => DelegateTemplate.create(klass)
// @MessagePackOrdinalEnumアノテーションをチェック => OrdinalEnumTemplate.create(klass)
// エラー
}
}
// MessagePackObject
public Object convert(Template tmpl) {
return tmpl.convert(this);
}
// import static Templates.*;用
public class Templates {
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 final TString = StringTemplate.instance;
public static Tempalte tString() {
return TString;
}
public static final TByteArray = ByteArrayTemplate.instance;
public static Tempalte tByteArray() {
return TByteArray;
}
// ...
}
// 標準提供Template群
public class ListTemplate implements Template {
private Template elementTemplate;
public ListTemplate(Template elementTemplate) {
this.elementTemplate = elementTemplate;
}
public Object unpack(Unpacker pac) {
int length = pac.unpackArray();
List<Object> list = new ArrayList(length);
for(; length > 0; length--) {
list.add( elementTemplate.unpack(pack) );
}
return list;
}
public Object convert(MessagePackObject from) {
MessagePackObject[] array = from.asArray();
List<Object> list = new ArrayList(array.length);
for(MessagePackObject element : array) {
list.add( elementTemplate.convert(element) );
}
return list;
}
}
public class StringTemplate implements Template {
public Object unpack(Unpacker pac) {
pac.asString();
}
public Object convert(MessagePackObject from) {
return from.asString();
}
static final StringTemplate instance = new StringTemplate();
static {
CustomMessage.registerTemplate(String.class, instance);
}
private StringTemplate() { }
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment