package net.varkhan.base.conversion.serializer.composite; import net.varkhan.base.conversion.serializer.DecodingException; import net.varkhan.base.conversion.serializer.EncodingException; import net.varkhan.base.conversion.serializer.Serializer; import net.varkhan.base.conversion.serializer.primitives.StringSerializer; import net.varkhan.base.conversion.serializer.primitives.VariadicSerializer; import java.io.InputStream; import java.io.OutputStream; import java.nio.ByteBuffer; import java.util.HashMap; import java.util.Map; /** * <b>Generic data structure serializer</b>. * <p/> * Serializes a structure containing typed, named fields. * <p/> * * @author varkhan * @date 5/28/11 * @time 3:52 AM */ @SuppressWarnings( { "UnusedDeclaration" }) public class StructSerializer<C> implements Serializer<Map<String,Object>,C> { private final Map<String,Serializer<Object,C>> serializers=new HashMap<String,Serializer<Object,C>>(); public StructSerializer() { } @SuppressWarnings( { "unchecked" }) public void setSerializer(String field, Serializer<?,C> serializer) { serializers.put(field, (Serializer<Object, C>) serializer); } public void remSerializer(String field) { serializers.remove(field); } public Serializer<?,C> getSerializer(String field) { return serializers.get(field); } public Map<String,Object> decode(InputStream stm, C ctx) { long size=VariadicSerializer._decode(stm); Map<String,Object> rec=new HashMap<String,Object>(); for(long i=0;i<size;i++) { String key=StringSerializer._decode(stm); Serializer<Object,C> s = serializers.get(key); if(s==null) throw new DecodingException("Decoder not found for field \""+key+"\""); Object val=s.decode(stm, ctx); rec.put(key, val); } return rec; } public Map<String,Object> decode(ByteBuffer buf, C ctx) { long size=VariadicSerializer._decode(buf); Map<String,Object> rec=new HashMap<String,Object>(); for(long i=0;i<size;i++) { String key=StringSerializer._decode(buf); Serializer<Object,C> s = serializers.get(key); if(s==null) throw new DecodingException("Decoder not found for field \""+key+"\""); Object val=s.decode(buf, ctx); rec.put(key, val); } return rec; } public Map<String,Object> decode(byte[] dat, long pos, long len, C ctx) { long size=VariadicSerializer._decode(dat, pos, len); pos+=VariadicSerializer._length(size); Map<String,Object> rec=new HashMap<String,Object>(); for(long i=0;i<size;i++) { String key=StringSerializer._decode(dat, pos, len); pos+=StringSerializer._length(key); Serializer<Object,C> s = serializers.get(key); if(s==null) throw new DecodingException("Decoder not found for field \""+key+"\""); Object val=s.decode(dat, pos, len, ctx); pos+=s.length(val, ctx); rec.put(key, val); } return rec; } public long encode(Map<String,Object> obj, OutputStream stm, C ctx) { long c=VariadicSerializer._encode(obj.size(), stm); for(Map.Entry<String,Object> ent : obj.entrySet()) { String key=ent.getKey(); Serializer<Object,C> s = serializers.get(key); if(s==null) throw new EncodingException("Encoder not found for field \""+key+"\""); c+=StringSerializer._encode(key, stm); c+=s.encode(ent.getValue(), stm, ctx); } return c; } public long encode(Map<String,Object> obj, ByteBuffer buf, C ctx) { long c=VariadicSerializer._encode(obj.size(), buf); for(Map.Entry<String,Object> ent : obj.entrySet()) { String key=ent.getKey(); Serializer<Object,C> s = serializers.get(key); if(s==null) throw new EncodingException("Encoder not found for field \""+key+"\""); c+=StringSerializer._encode(key, buf); c+=s.encode(ent.getValue(), buf, ctx); } return c; } public long encode(Map<String,Object> obj, byte[] dat, long pos, long len, C ctx) { long c=VariadicSerializer._encode(obj.size(), dat, pos, len); for(Map.Entry<String,Object> ent : obj.entrySet()) { String key=ent.getKey(); Serializer<Object,C> s = serializers.get(key); if(s==null) throw new EncodingException("Encoder not found for field \""+key+"\""); c+=StringSerializer._encode(key, dat, pos+c, len-c); c+=s.encode(ent.getValue(), dat, pos+c, len-c, ctx); } return c; } public long length(Map<String,Object> obj, C ctx) { long c=VariadicSerializer._length(obj.size()); for(Map.Entry<String,Object> ent : obj.entrySet()) { String key=ent.getKey(); Serializer<Object,C> s = serializers.get(key); if(s==null) throw new EncodingException("Encoder not found for field \""+key+"\""); c+=StringSerializer._length(key); c+=s.length(ent.getValue(), ctx); } return c; } }