package com.owent.xresloader.data.dst;
import com.owent.xresloader.ProgramOptions;
import com.owent.xresloader.data.err.ConvException;
import com.owent.xresloader.scheme.SchemeConf;
import org.dom4j.Attribute;
import org.dom4j.Document;
import org.dom4j.DocumentHelper;
import org.dom4j.Element;
import org.dom4j.io.OutputFormat;
import org.dom4j.io.XMLWriter;
import java.io.ByteArrayOutputStream;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
/**
* Created by owentou on 2014/10/10.
*/
public class DataDstXml extends DataDstJava {
@Override
public boolean init() {
return true;
}
/**
* @return 协议处理器名字
*/
public String name() {
return "xml";
}
@Override
public final byte[] build(DataDstImpl compiler) throws ConvException {
// pretty print
OutputFormat of = null;
if (ProgramOptions.getInstance().prettyIndent <= 0) {
of = OutputFormat.createCompactFormat();
} else {
of = OutputFormat.createPrettyPrint();
of.setIndentSize(ProgramOptions.getInstance().prettyIndent);
}
// build data
DataDstObject data_obj = build_data(compiler);
// build xml tree
Document doc = DocumentHelper.createDocument();
String encoding = SchemeConf.getInstance().getKey().getEncoding();
if (null != encoding && false == encoding.isEmpty()) {
doc.setXMLEncoding(encoding);
of.setEncoding(encoding);
}
doc.setRootElement(DocumentHelper.createElement(ProgramOptions.getInstance().xmlRootName));
doc.getRootElement().addComment("this file is generated by xresloader, please don't edit it.");
Element header = DocumentHelper.createElement("header");
Element body = DocumentHelper.createElement("body");
writeData(header, data_obj.header, header.getName());
// body
for(Map.Entry<String, List<Object> > item: data_obj.body.entrySet()) {
for(Object obj: item.getValue()) {
Element xml_item = DocumentHelper.createElement(item.getKey());
writeData(xml_item, obj, item.getKey());
body.add(xml_item);
}
}
writeData(body, data_obj.body, body.getName());
doc.getRootElement().add(header);
doc.getRootElement().add(body);
try {
ByteArrayOutputStream bos = new ByteArrayOutputStream();
XMLWriter writer = new XMLWriter(bos, of);
writer.write(doc);
return bos.toByteArray();
} catch(Exception e) {
ProgramOptions.getLoger().error("write xml failed, %s", e.getMessage());
return null;
}
}
@Override
public final DataDstWriterNode compile() {
ProgramOptions.getLoger().error("lua can not be protocol description.");
return null;
}
private void writeData(Element sb, Object data, String wrapper_name) {
// null
if (null == data) {
return;
}
// 数字
// 枚举值已被转为Java Long,会在这里执行
if (data instanceof Number) {
sb.addText(data.toString());
return;
}
// 布尔
if (data instanceof Boolean) {
sb.addText(((Boolean) data) ? "true" : "false");
return;
}
// 字符串&二进制
if (data instanceof String) {
sb.addText(data.toString());
return;
}
// 列表
if (data instanceof List) {
List<Object> ls = (List<Object>)data;
int index = 0;
for(Object obj: ls) {
Element list_ele = DocumentHelper.createElement(wrapper_name);
Attribute index_attr = DocumentHelper.createAttribute(list_ele, "for", String.valueOf(index));
list_ele.add(index_attr);
writeData(list_ele, obj, wrapper_name);
sb.add(list_ele);
++ index;
}
return;
}
// Hashmap
if (data instanceof Map) {
Map<String, Object> mp = (Map<String, Object>)data;
for(Map.Entry<String, Object> item: mp.entrySet()) {
// 数据会多一层,这里去除
if (item.getValue() instanceof List) {
writeData(sb, item.getValue(), item.getKey());
} else {
Element xml_item = DocumentHelper.createElement(item.getKey());
writeData(xml_item, item.getValue(), item.getKey());
sb.add(xml_item);
}
}
return;
}
ProgramOptions.getLoger().error("%s not support.", data.toString());
}
/**
* 转储常量数据
* @return 常量数据,不支持的时候返回空
*/
public final byte[] dumpConst(HashMap<String, Object> data) {
// pretty print
OutputFormat of = null;
if (ProgramOptions.getInstance().prettyIndent <= 0) {
of= OutputFormat.createCompactFormat();
} else {
of = OutputFormat.createPrettyPrint();
of.setIndentSize(ProgramOptions.getInstance().prettyIndent);
}
// build xml tree
Document doc = DocumentHelper.createDocument();
String encoding = SchemeConf.getInstance().getKey().getEncoding();
if (null != encoding && false == encoding.isEmpty()) {
doc.setXMLEncoding(encoding);
of.setEncoding(encoding);
}
doc.setRootElement(DocumentHelper.createElement(ProgramOptions.getInstance().xmlRootName));
doc.getRootElement().addComment("this file is generated by xresloader, please don't edit it.");
writeData(doc.getRootElement(), data, "");
try {
ByteArrayOutputStream bos = new ByteArrayOutputStream();
XMLWriter writer = new XMLWriter(bos, of);
writer.write(doc);
return bos.toByteArray();
} catch(Exception e) {
ProgramOptions.getLoger().error("write xml failed, %s", e.getMessage());
return null;
}
}
}