package open.dolphin.client; import java.awt.Color; import java.io.BufferedWriter; import java.io.IOException; import java.io.StringWriter; import java.io.Writer; import java.util.ArrayList; import java.util.Enumeration; import java.util.logging.Level; import javax.swing.text.AttributeSet; import javax.swing.text.BadLocationException; import javax.swing.text.DefaultStyledDocument; import javax.swing.text.StyleConstants; import open.dolphin.infomodel.AttachmentModel; import open.dolphin.infomodel.ModuleModel; import open.dolphin.infomodel.SchemaModel; /** * KartePane の dumper * * @author Kazushi Minagawa, Digital Globe, Inc. */ public final class KartePaneDumper_2 { private static final String[] MATCHES = new String[] { "&", "<", ">", "'","\""}; private static final String[] REPLACES = new String[] { "&" ,"<", ">", "'", """}; private ArrayList<ModuleModel> moduleList; private ArrayList<SchemaModel> schemaList; private ArrayList<AttachmentModel> attachmentList; private String spec; // Logger private static final boolean DEBUG = false; private static final java.util.logging.Logger logger; static { logger = java.util.logging.Logger.getLogger(KartePaneDumper_2.class.getName()); logger.setLevel(DEBUG ? Level.FINE : Level.INFO); } /** Creates a new instance of TextPaneDumpBuilder */ public KartePaneDumper_2() { } /** * ダンプした Document の XML 定義を返す。 * * @return Documentの内容を XML で表したもの */ public String getSpec() { logger.fine(spec); //System.err.println(spec); return spec; } /** * ダンプした Documentに含まれている ModuleModelを返す。 * * @return ModuleModel配列 */ public ModuleModel[] getModule() { ModuleModel[] ret = null; if ((moduleList != null) && (moduleList.size() > 0)) { ret = moduleList.toArray(new ModuleModel[moduleList.size()]); } return ret; } /** * ダンプした Documentに含まれている SchemaModel を返す。 * * @return SchemaModel配列 */ public SchemaModel[] getSchema() { SchemaModel[] schemas = null; if ((schemaList != null) && (schemaList.size() > 0)) { schemas = schemaList.toArray(new SchemaModel[schemaList.size()]); } return schemas; } /** * ダンプした Documentに含まれている AttachmentModel を返す。 * * @return AttachmentModel配列 */ public AttachmentModel[] getAttachment() { AttachmentModel[] ret = null; if ((attachmentList != null) && (attachmentList.size() > 0)) { ret = attachmentList.toArray(new AttachmentModel[attachmentList.size()]); } return ret; } /** * 引数の Document をダンプする。 * * @param doc ダンプするドキュメント */ public void dump(DefaultStyledDocument doc) { StringWriter sw = new StringWriter(); BufferedWriter writer = new BufferedWriter(sw); try { // ルート要素から再帰的にダンプする javax.swing.text.Element root = (javax.swing.text.Element) doc.getDefaultRootElement(); writeElemnt(root, writer); // 出力バッファーをフラッシュしペインのXML定義を生成する writer.flush(); writer.close(); spec = sw.toString(); } catch (IOException | BadLocationException e) { e.printStackTrace(System.err); } } /** * 要素を再帰的にダンプする。 * @param element 要素 * @param writer 出力ライター * @throws IOException * @throws BadLocationException */ private void writeElemnt(javax.swing.text.Element element, Writer writer) throws IOException, BadLocationException { // 要素の開始及び終了のオフセット値を保存する int start = element.getStartOffset(); int end = element.getEndOffset(); logger.log(Level.FINE, "start = {0}", start); logger.log(Level.FINE, "end = {0}", end); // このエレメントの属性セットを得る AttributeSet atts = element.getAttributes().copyAttributes(); // 属性値の文字列表現 String asString = ""; // 属性を調べる if (atts != null) { StringBuilder retBuffer = new StringBuilder(); // 全ての属性を列挙する Enumeration names = atts.getAttributeNames(); while (names.hasMoreElements()) { // 属性の名前を得る Object nextName = names.nextElement(); if (nextName != StyleConstants.ResolveAttribute) { logger.log(Level.FINE, "attribute name = {0}", nextName.toString()); // $enameは除外する if (nextName.toString().startsWith("$")) { continue; } //s.oh^ 2014/05/08 Google日本語入力対応 if (nextName.toString().startsWith("composed text")) { continue; } //s.oh$ // 属性= の形を準備する retBuffer.append(" "); retBuffer.append(nextName); retBuffer.append("="); // foreground 属性の場合は再構築の際に利用しやすい形に分解する if (nextName.toString().equals("foreground")) { Color c = (Color) atts.getAttribute(StyleConstants.Foreground); logger.log(Level.FINE, "color = {0}", c.toString()); StringBuilder buf = new StringBuilder(); buf.append(String.valueOf(c.getRed())); buf.append(","); buf.append(String.valueOf(c.getGreen())); buf.append(","); buf.append(String.valueOf(c.getBlue())); retBuffer.append(addQuote(buf.toString())); } else { // 属性セットから名前をキーにして属性オブジェクトを取得する Object attObject = atts.getAttribute(nextName); logger.log(Level.FINE, "attribute object = {0}", attObject.toString()); if (attObject instanceof StampHolder) { // スタンプの場合 if (moduleList == null) { moduleList = new ArrayList<>(); } StampHolder sh = (StampHolder) attObject; moduleList.add((ModuleModel) sh.getStamp()); String value = String.valueOf(moduleList.size() - 1); // ペインに出現する順番をこの属性の値とする retBuffer.append(addQuote(value)); } else if (attObject instanceof SchemaHolder) { // シュェーマの場合 if (schemaList == null) { schemaList = new ArrayList<>(); } SchemaHolder ch = (SchemaHolder)attObject; schemaList.add(ch.getSchema()); String value = String.valueOf(schemaList.size() - 1); // ペインに出現する順番をこの属性の値とする retBuffer.append(addQuote(value)); } else if (attObject instanceof AttachmentHolder) { // アタッチメントの場合 if (attachmentList == null) { attachmentList = new ArrayList<>(); } AttachmentHolder ah = (AttachmentHolder)attObject; attachmentList.add(ah.getAttachment()); String value = String.valueOf(attachmentList.size() - 1); // ペインに出現する順番をこの属性の値とする retBuffer.append(addQuote(value)); } else { // それ以外の属性についてはそのまま記録する retBuffer.append(addQuote(attObject.toString())); } } } } asString = retBuffer.toString(); } // <要素名 start="xx" end="xx" + asString> writer.write("<"); writer.write(element.getName()); writer.write(" start="); writer.write(addQuote(start)); writer.write(" end="); writer.write(addQuote(end)); writer.write(asString); writer.write(">"); // content要素の場合はテキストを抽出する if (element.getName().equals("content")) { writer.write("<text>"); int len = end - start; String text = element.getDocument().getText(start, len); logger.log(Level.FINE, "text = {0}", text); // 特定の文字列を置換する for (int i = 0; i < REPLACES.length; i++) { text = text.replaceAll(MATCHES[i], REPLACES[i]); } writer.write(text); writer.write("</text>"); } // 子要素について再帰する int children = element.getElementCount(); for (int i = 0; i < children; i++) { writeElemnt(element.getElement(i), writer); } // この属性を終了する // </属性名> writer.write("</"); writer.write(element.getName()); writer.write(">"); } private String addQuote(String str) { StringBuilder buf = new StringBuilder(); buf.append("\""); buf.append(str); buf.append("\""); return buf.toString(); } private String addQuote(int str) { StringBuilder buf = new StringBuilder(); buf.append("\""); buf.append(str); buf.append("\""); return buf.toString(); } //s.oh^ 2014/07/22 一括カルテPDF出力 public void setSpec(String spec) { this.spec = spec; } public void setModuleList(ArrayList<ModuleModel> list) { this.moduleList = list; } public void setSchemaList(ArrayList<SchemaModel> list) { this.schemaList = list; } public void setAttachmentList(ArrayList<AttachmentModel> list) { this.attachmentList = list; } //s.oh$ }