package jane.core; import java.util.Collection; import java.util.Map; import java.util.Map.Entry; import java.util.Set; import java.util.TreeMap; /** * 用于表示动态字段的bean */ public final class DynBean extends Bean<DynBean> { private static final long serialVersionUID = 1L; public static final DynBean BEAN_STUB = new DynBean(); private int _type; // bean的类型(可用可不用,不影响序列化/反序列化) private final Map<Integer, Object> _fields = new TreeMap<>(); // key是字段ID. 为了方便格式化成字符串,使用有序的容器 public DynBean() { } public DynBean(int type) { _type = type; } /** * 使用BeanCodec接收到的RawBean来构造一个 DynBean<br> * 即RawBean的数据部分只是一个Bean的marshal数据,不含类型和长度 */ public DynBean(RawBean b) throws MarshalException { _type = b.getType(); unmarshal(OctetsStream.wrap(b.getData())); } public void setType(int type) { _type = type; } public Object getField(int id) { return _fields.get(id); } public Object setField(int id, Object o) { if(id < 1 || id > 190) throw new IllegalArgumentException("field id must be in [1,190]: " + id); return _fields.put(id, o); } public Set<Entry<Integer, Object>> fieldSet() { return _fields.entrySet(); } @Override public int type() { return _type; } @Override public String typeName() { return "DynBean"; } @Override public DynBean stub() { return BEAN_STUB; } @Override public DynBean create() { return new DynBean(); } @Override public void reset() { _type = 0; _fields.clear(); } @Override public OctetsStream marshal(OctetsStream os) { for(Entry<Integer, Object> e : _fields.entrySet()) os.marshalVar(e.getKey(), e.getValue()); return os.marshal1((byte)0); } @Override public OctetsStream unmarshal(OctetsStream os) throws MarshalException { for(_fields.clear();;) { int b = os.unmarshalInt1() & 0xff; if(b == 0) return os; if(b > 251) b += os.unmarshalInt1() << 2; _fields.put(b >> 2, os.unmarshalVar(b & 3)); } } @Override public DynBean clone() { DynBean b = new DynBean(_type); b._fields.putAll(_fields); return b; } @Override public int hashCode() { return _type + _fields.hashCode(); } @Override public boolean equals(Object o) { if(this == o) return true; if(!(o instanceof DynBean)) return false; DynBean rb = (DynBean)o; return _type == rb._type && _fields.equals(rb._fields); } @Override public String toString() { StringBuilder s = new StringBuilder(_fields.size() * 16 + 16); s.append("{t:").append(_type); for(Entry<Integer, Object> e : _fields.entrySet()) s.append(',').append(e.getKey()).append(':').append(e.getValue()); return s.append('}').toString(); } @Override public StringBuilder toJson(StringBuilder s) { if(s == null) s = new StringBuilder(_fields.size() * 16 + 16); s.append("{\"t\":").append(_type); for(Entry<Integer, Object> e : _fields.entrySet()) { s.append(',').append('"').append(e.getKey()).append('"').append(':'); Object o = e.getValue(); if(o instanceof Number || o instanceof Boolean) s.append(o.toString()); else if(o instanceof Octets) ((Octets)o).dumpJStr(s); else if(o instanceof Collection) Util.appendJson(s, (Collection<?>)o); else if(o instanceof Map) Util.appendJson(s, (Map<?, ?>)o); else Util.toJStr(s, o.toString()); } return s.append('}'); } @Override public StringBuilder toLua(StringBuilder s) { if(s == null) s = new StringBuilder(_fields.size() * 16 + 16); s.append("{t=").append(_type); for(Entry<Integer, Object> e : _fields.entrySet()) { s.append(',').append('[').append(e.getKey()).append(']').append('='); Object o = e.getValue(); if(o instanceof Number || o instanceof Boolean) s.append(o.toString()); else if(o instanceof Octets) ((Octets)o).dumpJStr(s); else if(o instanceof Collection) Util.appendLua(s, (Collection<?>)o); else if(o instanceof Map) Util.appendLua(s, (Map<?, ?>)o); else Util.toJStr(s, o.toString()); } return s.append('}'); } }