package com.owent.xresloader.data.dst; import com.owent.xresloader.ProgramOptions; import com.owent.xresloader.data.err.ConvException; import com.owent.xresloader.data.src.DataContainer; import com.owent.xresloader.data.src.DataSrcImpl; import com.owent.xresloader.scheme.SchemeConf; import java.nio.charset.Charset; import java.util.ArrayList; import java.util.HashMap; import java.util.List; import java.util.Map; import static com.google.protobuf.Descriptors.FieldDescriptor.JavaType.MESSAGE; /** * Created by owentou on 2015/04/29. */ public abstract class DataDstJava extends DataDstImpl { private class DataEntry { public boolean valid = false; public Object value = null; public <T> void set(DataContainer<T> v) { valid = v.valid; value = v.value; } } private String systemEndl = null; public String getSystemEndl() { if (null != systemEndl) { return systemEndl; } systemEndl = System.getProperty("line.separator", "\n"); if (null == systemEndl || systemEndl.isEmpty()) { systemEndl = "\r\n"; } return systemEndl; } /** * @return 协议处理器名字 */ public String name() { return "java"; } public class DataDstObject { public HashMap<String, Object> header = new HashMap<String, Object>(); public HashMap<String, List<Object> > body = new HashMap<String, List<Object>>(); } protected DataDstObject build_data(DataDstImpl compiler) throws ConvException { DataDstObject ret = new DataDstObject(); ret.header.put("xres_ver", ProgramOptions.getInstance().getVersion()); ret.header.put("data_ver", ProgramOptions.getInstance().getVersion()); ret.header.put("count", DataSrcImpl.getOurInstance().getRecordNumber()); ret.header.put("hash_code", "no hash code"); List<Object> item_list = new ArrayList<Object>(); ret.body.put(SchemeConf.getInstance().getProtoName(), item_list); while (DataSrcImpl.getOurInstance().next_table()) { // 生成描述集 DataDstWriterNode desc = compiler.compile(); while(DataSrcImpl.getOurInstance().next_row()) { HashMap<String, Object> msg = new HashMap<String, Object>(); if(dumpMessage(msg, desc)) { item_list.add(msg); } } } return ret; } private void dumpDefault(HashMap<String, Object> builder, DataDstWriterNode desc, String field_name, DataDstWriterNode.DataDstChildrenNode as_child) { Object val = null; switch (desc.getType()) { case INT: val = Integer.valueOf(0); break; case LONG: val = Long.valueOf(0); break; case BOOLEAN: val = Boolean.FALSE; break; case STRING: val = ""; break; case BYTES: val = new byte[0]; break; case FLOAT: val = Float.valueOf(0); break; case DOUBLE: val = Double.valueOf(0); break; case MESSAGE: { HashMap<String, Object> sub_msg = new HashMap<String, Object>(); for(Map.Entry<String, DataDstWriterNode.DataDstChildrenNode> sub_item: desc.getChildren().entrySet()) { for (DataDstWriterNode sub_desc : sub_item.getValue().nodes) { dumpDefault(sub_msg, sub_desc, sub_item.getKey(), sub_item.getValue()); } } break; } } if (null == val) { ProgramOptions.getLoger().error("serialize failed. %s is not supported for java default value", desc.getType().toString()); return; } if (as_child.isList) { ArrayList<Object> old = (ArrayList<Object>)builder.getOrDefault(field_name,null); if (null == old) { old = new ArrayList<Object>(); builder.put(field_name, old); } old.add(val); } else { builder.put(field_name, val); } } /** * 转储数据到builder * @param builder 转储目标 * @param node message的描述结构 * @return 有数据则返回true * @throws ConvException */ private boolean dumpMessage(HashMap<String, Object> builder, DataDstWriterNode node) throws ConvException { boolean ret = false; for (Map.Entry<String, DataDstWriterNode.DataDstChildrenNode> c : node.getChildren().entrySet()) { for (DataDstWriterNode child: c.getValue().nodes) { if (dumpField(builder, child, c.getKey(), c.getValue())) { ret = true; } } } return ret; } private boolean dumpField(HashMap<String, Object> builder, DataDstWriterNode desc, String field_name, DataDstWriterNode.DataDstChildrenNode as_child) throws ConvException { if (null == desc.identify && DataDstWriterNode.JAVA_TYPE.MESSAGE != desc.getType()) { dumpDefault(builder, desc, field_name, as_child); return false; } Object val = null; switch (desc.getType()) { case INT: { DataContainer<Integer> ret = DataSrcImpl.getOurInstance().getValue(desc.identify, Integer.valueOf(0)); if (null != ret && ret.valid) { val = ret.value; } break; } case LONG:{ DataContainer<Long> ret = DataSrcImpl.getOurInstance().getValue(desc.identify, Long.valueOf(0)); if (null != ret && ret.valid) { val = ret.value; } break; } case FLOAT:{ DataContainer<Float> ret = DataSrcImpl.getOurInstance().getValue(desc.identify, Float.valueOf(0)); if (null != ret && ret.valid) { val = ret.value; } break; } case DOUBLE:{ DataContainer<Double> ret = DataSrcImpl.getOurInstance().getValue(desc.identify, Double.valueOf(0)); if (null != ret && ret.valid) { val = ret.value; } break; } case BOOLEAN:{ DataContainer<Boolean> ret = DataSrcImpl.getOurInstance().getValue(desc.identify, Boolean.FALSE); if (null != ret && ret.valid) { val = ret.value; } break; } case STRING: { DataContainer<String> ret = DataSrcImpl.getOurInstance().getValue(desc.identify, ""); if (null != ret && ret.valid) { val = ret.value; } break; } case BYTES: { DataContainer<String> res = DataSrcImpl.getOurInstance().getValue(desc.identify, ""); if(null != res && res.valid) { String encoding = SchemeConf.getInstance().getKey().getEncoding(); if (null == encoding || encoding.isEmpty()) { val = com.google.protobuf.ByteString.copyFrom(res.value.getBytes()); } else { val = com.google.protobuf.ByteString.copyFrom(res.value.getBytes(Charset.forName(encoding))); } } break; } case MESSAGE: { HashMap<String, Object> node = new HashMap<String, Object>(); if (dumpMessage(node, desc)) { val = node; } break; } default: break; } if (null == val) { if (as_child.isRequired) { dumpDefault(builder, desc, field_name, as_child); } return false; } if (as_child.isList) { ArrayList<Object> old = (ArrayList<Object>)builder.getOrDefault(field_name,null); if (null == old) { old = new ArrayList<Object>(); builder.put(field_name, old); } old.add(val); } else { builder.put(field_name, val); } return true; } }