package open.dolphin.stampbox;
import java.io.BufferedWriter;
import java.io.IOException;
import java.io.StringWriter;
import java.util.Date;
import java.util.LinkedList;
import open.dolphin.delegater.StampDelegater;
import open.dolphin.infomodel.ModuleInfoBean;
import open.dolphin.infomodel.StampModel;
import open.dolphin.project.Project;
import open.dolphin.util.HexBytesTool;
/**
* stampBytesも含めたStampTreeXmlBuilder
*
* based on DefaultStampTreeXmlBuilder.java
* @author masuda, Masuda Naika
*/
public class ExtendedStampTreeXmlBuilder {
//private static final String[] MATCHES = new String[] { "<", ">", "&", "'","\""};
private static final String[] MATCHES = new String[] { "&", "<", ">", "'","\""};
//private static final String[] REPLACES = new String[] { "<", ">", "&" ,"'", """};
private static final String[] REPLACES = new String[] { "&" ,"<", ">", "'", """};
/** Control staffs */
private LinkedList<StampTreeNode> linkedList;
private BufferedWriter writer;
private StringWriter stringWriter;
private StampTreeNode rootNode;
// Logger
private static final boolean DEBUG=false;
private static final java.util.logging.Logger logger;
static {
logger = java.util.logging.Logger.getLogger(ExtendedStampTreeXmlBuilder.class.getName());
logger.setLevel(DEBUG ? java.util.logging.Level.FINE : java.util.logging.Level.INFO);
}
// Creates new ExtendedStampTreeXmlBuilder
public ExtendedStampTreeXmlBuilder() {
}
/**
* Returns the product of this builder
* @return vector that contains StampTree instances
*/
public String getProduct() {
String result = stringWriter.toString();
if (DEBUG) {
logger.fine(result);
}
return result;
}
/**
* Return the product of this builder
* @throws java.io.IOException
*/
public void buildStart() throws IOException {
if (DEBUG) {
logger.fine("StampTree Build start");
}
stringWriter = new StringWriter();
writer = new BufferedWriter(stringWriter);
writer.write("<?xml version=\"1.0\" encoding=\"UTF-8\" ?>\n");
writer.write(makeComment());
writer.write("<extendedStampTree project=");
writer.write(addQuote("open.dolphin"));
writer.write(" version=");
writer.write(addQuote("1.0"));
writer.write(">\n");
}
private String makeComment() {
StringBuilder sb = new StringBuilder();
sb.append("<!-- StampBox Export Data, Creator: ");
sb.append(Project.getUserModel().getFacilityModel().getFacilityName());
sb.append(", Created on: ");
sb.append(new Date().toString());
sb.append(" -->\n");
return sb.toString();
}
public void buildRoot(StampTreeNode root) throws IOException {
if (DEBUG) {
logger.fine("Build Root Node: " + root.toString());
}
rootNode = root;
TreeInfo treeInfo = (TreeInfo)rootNode.getUserObject();
writer.write("<root name=");
writer.write(addQuote(treeInfo.getName()));
writer.write(" entity=");
writer.write(addQuote(treeInfo.getEntity()));
writer.write(">\n");
linkedList = new LinkedList<>();
linkedList.addFirst(rootNode);
}
public void buildNode(StampTreeNode node) throws IOException {
if ( node.isLeaf() ) {
buildLeafNode(node);
} else {
buildDirectoryNode(node);
}
}
private void buildDirectoryNode(StampTreeNode node) throws IOException {
// 子ノードを持たないディレクトリノードは書き出さない
if (node.getChildCount() != 0) {
if (DEBUG) {
logger.fine("Build Directory Node: " + node.toString());
}
StampTreeNode myParent = (StampTreeNode) node.getParent();
StampTreeNode curNode = getCurrentNode();
if (myParent != curNode) {
closeBeforeMyParent(myParent);
}
linkedList.addFirst(node);
writer.write("<node name=");
// 特殊文字を変換する
String val = toXmlText(node.toString());
writer.write(addQuote(val));
writer.write(">\n");
}
}
private void buildLeafNode(StampTreeNode node) throws IOException {
if (DEBUG) {
logger.fine("Build Leaf Node: " + node.toString());
}
StampTreeNode myParent = (StampTreeNode) node.getParent();
StampTreeNode curNode = getCurrentNode();
if (myParent != curNode) {
closeBeforeMyParent(myParent);
}
// 特殊文字を変換する
writer.write("<stampInfo name=");
String val = toXmlText(node.toString());
writer.write(addQuote(val));
ModuleInfoBean info = (ModuleInfoBean) node.getUserObject();
writer.write(" role=");
writer.write(addQuote(info.getStampRole()));
writer.write(" entity=");
writer.write(addQuote(info.getEntity()));
writer.write(" editable=");
val = String.valueOf(info.isEditable());
writer.write(addQuote(val));
val = info.getStampMemo();
if (val != null) {
writer.write(" memo=");
val = toXmlText(val);
writer.write(addQuote(val));
}
if (info.isSerialized()) {
val = info.getStampId();
writer.write(" stampId=");
writer.write(addQuote(val));
// ここで対応するstampBytesをデータベースから読み込み登録する。
String stampHexBytes = getHexStampBytes(val);
// 実態のないスタンプの場合があった。なぜゾンビができたのだろう??
if (stampHexBytes != null) {
//writer.write(" stampId=");
//writer.write(addQuote(val));
writer.write(" stampBytes=");
writer.write(addQuote(stampHexBytes));
}
}
writer.write("/>\n");
}
// StampIdから対応するStampModelを取得してstampBytesのHex文字列を作成する
private String getHexStampBytes(String stampId){
StampDelegater del = StampDelegater.getInstance();
// スタンプの実体を取得
StampModel model = null;
try {
model = del.getStamp(stampId);
//System.err.println("!=ゾンビ");
} catch (Exception e) {
//throw new RuntimeException("Stamp fetch error");
//e.printStackTrace(System.err);
System.err.println("ゾンビ");
}
// データベースにない場合はnullを返す
if (model == null){
return null;
}
// stampBytesを返す
byte[] stampBytes = model.getStampBytes();
return HexBytesTool.bytesToHex(stampBytes);
}
public void buildRootEnd() throws IOException {
if (DEBUG) {
logger.fine("Build Root End");
}
closeBeforeMyParent(rootNode);
writer.write("</root>\n");
}
public void buildEnd() throws IOException {
if (DEBUG) {
logger.fine("Build end");
}
writer.write("</extendedStampTree>\n");
writer.flush();
}
private StampTreeNode getCurrentNode() {
return linkedList.getFirst();
}
private void closeBeforeMyParent(StampTreeNode parent) throws IOException {
int index = linkedList.indexOf(parent);
if (DEBUG) {
logger.fine("Close before my parent: " + index);
}
for (int j = 0; j < index; j++) {
writer.write("</node>\n");
linkedList.removeFirst();
}
}
private String addQuote(String s) {
StringBuilder buf = new StringBuilder();
buf.append("\"");
buf.append(s);
buf.append("\"");
return buf.toString();
}
/**
* 特殊文字を変換する。
*/
private String toXmlText(String text) {
for (int i = 0; i < REPLACES.length; i++) {
text = text.replaceAll(MATCHES[i], REPLACES[i]);
}
return text;
}
}