/* * To change this template, choose Tools | Templates * and open the template in the editor. */ package open.dolphin.letter; import com.lowagie.text.Element; import java.awt.Color; import java.awt.Desktop; import java.awt.Dimension; import java.awt.Graphics; import java.awt.Image; import java.awt.image.BufferedImage; import java.io.BufferedReader; import java.io.ByteArrayOutputStream; import java.io.File; import java.io.FileInputStream; import java.io.FileNotFoundException; import java.io.IOException; import java.io.StringReader; import java.net.URI; import java.util.ArrayList; import java.util.Collection; import java.util.Collections; import java.util.Date; import java.util.Iterator; import java.util.StringTokenizer; import java.util.logging.Level; import java.util.logging.Logger; import javax.imageio.ImageIO; import javax.print.Doc; import javax.print.DocFlavor; import javax.print.DocPrintJob; import javax.print.PrintException; import javax.print.PrintService; import javax.print.PrintServiceLookup; import javax.print.ServiceUI; import javax.print.SimpleDoc; import javax.print.attribute.DocAttributeSet; import javax.print.attribute.HashDocAttributeSet; import javax.print.attribute.HashPrintRequestAttributeSet; import javax.print.attribute.PrintRequestAttributeSet; import javax.swing.ImageIcon; import open.dolphin.client.ClientContext; import open.dolphin.impl.lbtest.LaboTestOutputPDF; import open.dolphin.infomodel.AttachmentModel; import open.dolphin.infomodel.BundleDolphin; import open.dolphin.infomodel.DocumentModel; import open.dolphin.infomodel.IInfoModel; import open.dolphin.infomodel.ModuleModel; import open.dolphin.infomodel.ProgressCourse; import open.dolphin.project.Project; import org.jdom.JDOMException; import org.jdom.input.SAXBuilder; /** * * @author S.Oh@Life Sciences Computing Corporation. */ public class KartePDFImpl { private final DocumentModel model; private ArrayList<ModuleModel> stamps; private final KartePDFMaker2 pdfMarker; // PDF Marker private static final String COMPONENT_ELEMENT_NAME = "component"; private static final String STAMP_HOLDER = "stampHolder"; private static final String SCHEMA_HOLDER = "schemaHolder"; private static final String ATTACHMENT_HOLDER = "attachmentHolder"; // Attachment追加 private static final int TT_SECTION = 0; private static final int TT_PARAGRAPH = 1; private static final int TT_CONTENT = 2; private static final int TT_ICON = 3; private static final int TT_COMPONENT = 4; private static final int TT_PROGRESS_COURSE = 5; private static final String SECTION_NAME = "section"; private static final String PARAGRAPH_NAME = "paragraph"; private static final String CONTENT_NAME = "content"; private static final String COMPONENT_NAME = "component"; private static final String ICON_NAME = "icon"; private static final String ALIGNMENT_NAME = "Alignment"; private static final String FOREGROUND_NAME = "foreground"; private static final String SIZE_NAME = "size"; private static final String BOLD_NAME = "bold"; private static final String ITALIC_NAME = "italic"; private static final String UNDERLINE_NAME = "underline"; private static final String TEXT_NAME = "text"; private static final String NAME_NAME = "name"; // private static final String LOGICAL_STYLE_NAME = "logicalStyle"; private static final String PROGRESS_COURSE_NAME = "kartePane"; //private static final String[] REPLACES = new String[] { "<", ">", "&", "'" ,"\""}; private static final String[] REPLACES = new String[] { "&", "<", ">", "'" ,"\""}; //private static final String[] MATCHES = new String[] { "<", ">", "&", "'", """ }; private static final String[] MATCHES = new String[] { "&", "<", ">", "'", """ }; // private static final String NAME_STAMP_HOLDER = "name=\"stampHolder\""; /** * コンストラクタ * @param valPath フォルダパス * @param valDocID * @param valPatID * @param valPatName * @param valTitle * @param valDate 保存時刻 * @param model * @param docNo */ public KartePDFImpl(String valPath, String valDocID, String valPatID, String valPatName, String valTitle, Date valDate, DocumentModel model, String docNo) { // SOA // Plan this.model = model; // PDF Marker pdfMarker = new KartePDFMaker2(valPatID, valPatName, valTitle, valDate, valDocID, docNo); pdfMarker.setDocumentDir(valPath); } /** * SOAカルテ用PDFの作成 */ public void createKarteSOAToPDF() { Collection<ModuleModel> modules = model.getModules(); stamps = new ArrayList<>(); String soaSpec = null; String pSpec = null; for (ModuleModel bean : modules) { String role = bean.getModuleInfoBean().getStampRole(); if (role.equals(IInfoModel.ROLE_SOA)) { } else if (role.equals(IInfoModel.ROLE_SOA_SPEC)) { soaSpec = ((ProgressCourse) bean.getModel()).getFreeText(); } else if (role.equals(IInfoModel.ROLE_P)) { stamps.add(bean); } else if (role.equals(IInfoModel.ROLE_P_SPEC)) { pSpec = ((ProgressCourse) bean.getModel()).getFreeText(); } else if (bean.getModel() instanceof ProgressCourse) { if (soaSpec==null) { soaSpec = ((ProgressCourse) bean.getModel()).getFreeText(); } else if (pSpec==null) { pSpec = ((ProgressCourse) bean.getModel()).getFreeText(); } }else { stamps.add(bean); } } Collections.sort(stamps); pdfMarker.setKarteMode(KartePDFMaker2.KM_SOA); renderPDF(soaSpec); pdfMarker.setKarteMode(KartePDFMaker2.KM_PLAN); renderPDF(pSpec); } /** * TextPane Dump の XML を解析する。 * @param xml 作成したカルテのXML情報 */ private void renderPDF(String xml) { SAXBuilder docBuilder = new SAXBuilder(); try { StringReader sr = new StringReader(xml); org.jdom.Document doc = docBuilder.build(new BufferedReader(sr)); org.jdom.Element root = (org.jdom.Element) doc.getRootElement(); writeChildren(root); } // indicates a well-formedness error catch (JDOMException e) { e.printStackTrace(System.err); } catch (IOException e) { e.printStackTrace(System.err); } } /** * 子要素をパースする。 * @param current 要素 */ private void writeChildren(org.jdom.Element current) { int eType = -1; String eName = current.getName(); if (eName.equals(PARAGRAPH_NAME)) { eType = TT_PARAGRAPH; startParagraph(current.getAttributeValue(ALIGNMENT_NAME)); } else if (eName.equals(CONTENT_NAME) && (current.getChild(TEXT_NAME) != null)) { eType = TT_CONTENT; startContent(current.getAttributeValue(FOREGROUND_NAME), current.getAttributeValue(SIZE_NAME), current.getAttributeValue(BOLD_NAME), current.getAttributeValue(ITALIC_NAME), current.getAttributeValue(UNDERLINE_NAME), current.getChildText(TEXT_NAME)); } else if (eName.equals(COMPONENT_NAME)) { eType = TT_COMPONENT; startComponent(current.getAttributeValue(NAME_NAME), // compoenet=number current.getAttributeValue(COMPONENT_ELEMENT_NAME)); } else if (eName.equals(ICON_NAME)) { eType = TT_ICON; } else if (eName.equals(PROGRESS_COURSE_NAME)) { eType = TT_PROGRESS_COURSE; } else if (eName.equals(SECTION_NAME)) { eType = TT_SECTION; } // 子を探索するのはパラグフとトップ要素のみ if (eType == TT_PARAGRAPH || eType == TT_PROGRESS_COURSE || eType == TT_SECTION) { java.util.List children = (java.util.List) current.getChildren(); Iterator iterator = children.iterator(); while (iterator.hasNext()) { org.jdom.Element child = (org.jdom.Element) iterator.next(); writeChildren(child); } if(eType == TT_PARAGRAPH) { pdfMarker.addDataEnd(); } } } /** * Paragraph内の要素の解析 * @param alignStr 行揃え情報 */ private void startParagraph(String alignStr) { int align = Element.ALIGN_LEFT; if (alignStr != null) { if (alignStr.equals("0")) { align = Element.ALIGN_LEFT; } else if (alignStr.equals("1")) { align = Element.ALIGN_CENTER; } else if (alignStr.equals("2")) { align = Element.ALIGN_RIGHT; } } pdfMarker.addDataStart(align); } /** * Contentの解析 * @param foreground foreground属性 * @param size サイズ * @param bold ボールド * @param italic イタリック * @param underline 下線 * @param text テキスト */ private void startContent(String foreground, String size, String bold, String italic, String underline, String text) { int r = 0; int g = 0; int b = 0; //s.oh^ 2013/09/12 PDF印刷文字サイズ //int fontSize = 12; String textSize = Project.getString(Project.KARTE_PRINT_PDF_TEXTSIZE); int fontSize = 12; if(textSize != null && textSize.length() >= 1 && !textSize.startsWith("0")) { fontSize = Integer.parseInt(textSize); } //s.oh$ int style = style = 0; // 特殊文字を戻す for (int i = 0; i < REPLACES.length; i++) { text = text.replaceAll(MATCHES[i], REPLACES[i]); } // このコンテントに設定する AttributeSet //MutableAttributeSet atts = new SimpleAttributeSet(); // foreground 属性を設定する if (foreground != null) { StringTokenizer stk = new StringTokenizer(foreground, ","); if (stk.hasMoreTokens()) { r = Integer.parseInt(stk.nextToken()); g = Integer.parseInt(stk.nextToken()); b = Integer.parseInt(stk.nextToken()); //StyleConstants.setForeground(atts, new Color(r, g, b)); } } // size 属性を設定する if (size != null) { //s.oh^ 2013/09/12 PDF印刷文字サイズ //fontSize = Integer.parseInt(size); int diffSize = Integer.parseInt(size) - 12; fontSize = fontSize + diffSize; if(fontSize <= 0) { fontSize = 1; } //s.oh$ //StyleConstants.setFontSize(atts, Integer.parseInt(size)); } // bold 属性を設定する if (bold != null) { style = com.lowagie.text.Font.BOLD; //StyleConstants.setBold(atts, Boolean.valueOf(bold).booleanValue()); } // italic 属性を設定する if (italic != null) { style = com.lowagie.text.Font.ITALIC; //StyleConstants.setItalic(atts, Boolean.valueOf(italic) //.booleanValue()); } // underline 属性を設定する if (underline != null) { style = com.lowagie.text.Font.UNDERLINE; //StyleConstants.setUnderline(atts, Boolean.valueOf(underline) //.booleanValue()); } // テキストを挿入する //thePane.insertFreeString(text, atts); if(text != null && text.length() > 0) { //PDF_MARKER.addKartePDFData(text, align, fontSize, style, new Color(r,g,b)); pdfMarker.addData(text, fontSize, style, new Color(r,g,b)); } } /** * Componentの開始 * @param name 名前 * @param number 番号 */ private void startComponent(String name, String number) { try { if (name != null && name.equals(STAMP_HOLDER)) { int idx = Integer.parseInt(number); if(stamps != null && stamps.size() > idx && stamps.get(idx).getModel() instanceof BundleDolphin) { BundleDolphin bd = (BundleDolphin)stamps.get(idx).getModel(); //PDF_MARKER.addKartePDFData(bd.toString(), align, PDF_MARKER.getBodyFontSize(), com.lowagie.text.Font.NORMAL, new Color(0,0,0)); //s.oh^ 2013/09/12 PDF印刷文字サイズ //pdfMarker.addData(bd.toString(), pdfMarker.getBodyFontSize(), com.lowagie.text.Font.NORMAL, new Color(0,0,0)); String textSize = Project.getString(Project.KARTE_PRINT_PDF_TEXTSIZE); int fontSize = pdfMarker.getBodyFontSize(); if(textSize != null && textSize.length() >= 1 && !textSize.startsWith("0")) { fontSize = Integer.parseInt(textSize); } pdfMarker.addData(bd.toString(), fontSize, com.lowagie.text.Font.NORMAL, new Color(0,0,0)); //s.oh$ } } else if (name != null && name.equals(SCHEMA_HOLDER)) { int idx = Integer.parseInt(number); if(model.getSchema() != null && model.getSchema().size() > idx) { //Image img = new Image.getInstance(schema[idx].getJpegByte()); //PDF_MARKER.addKartePDFImage(schema[idx].getJpegByte(), align); //s.oh^ 2013/03/27 不具合修正(保存前のシェーマが作成されない) //pdfMarker.addImage(schema[idx].getJpegByte()); if(model.getSchema(idx).getJpegByte() != null) { pdfMarker.addImage(model.getSchema(idx).getJpegByte()); }else{ int maxImageWidth = ClientContext.getInt("image.max.width"); int maxImageHeight = ClientContext.getInt("image.max.height"); Dimension maxSImageSize = new Dimension(maxImageWidth, maxImageHeight); ImageIcon icon = model.getSchema(idx).getIcon(); icon = adjustImageSize(icon, maxSImageSize); byte[] jpegByte = getJPEGByte(icon.getImage()); pdfMarker.addImage(jpegByte); } //s.oh$ } // Attachment追加 } else if (name != null && name.equals(ATTACHMENT_HOLDER)) { int idx = Integer.parseInt(number); AttachmentModel attachment = (model.getAttachment() != null && model.getAttachment().size() > idx) ? model.getAttachment(idx) : null; if(attachment != null) { startContent(null, null, null, null, null, java.text.MessageFormat.format(ClientContext.getMyBundle(KartePDFImpl.class).getString("messageFormat.attachment"), new Object[] {attachment.getTitle(), attachment.getContentType()})); } } } catch (Exception e) { e.printStackTrace(System.err); } } /** * Planカルテ用PDFの作成 */ public void createKartePlanToPDF() { } /** * 作成 * @return String */ public String create() { String path; pdfMarker.initKartePDF(); createKarteSOAToPDF(); createKartePlanToPDF(); path = pdfMarker.create(); return path; } //s.oh^ 2013/02/07 印刷対応 public void printPDF(ArrayList<String> pdfFileNames) { if(pdfFileNames == null || pdfFileNames.size() <= 0) return; //s.oh^ 2013/06/24 印刷対応 if(Project.getBoolean(Project.KARTE_PRINT_SHOWPDF)) { for(String pdfFileName : pdfFileNames) { File file = new File(pdfFileName); URI uri = file.toURI(); try { Desktop.getDesktop().browse(uri); } catch (IOException ex) { Logger.getLogger(KartePDFImpl.class.getName()).log(Level.SEVERE, null, ex); } } //s.oh$ }else if(Project.getBoolean(Project.KARTE_PRINT_DIRECT)) { // ダイアログ非表示 //// docフレーバを設定 //DocFlavor flavor = DocFlavor.INPUT_STREAM.AUTOSENSE; //// 印刷要求属性を設定 //PrintRequestAttributeSet requestAttributes = new HashPrintRequestAttributeSet(); //requestAttributes.add(new Copies(3)); //requestAttributes.add(MediaSizeName.ISO_A4); //// 印刷サービスを検出 //PrintService service = PrintServiceLookup.lookupDefaultPrintService(); //// 印刷ジョブを作成 //DocPrintJob job = service.createPrintJob(); PrintRequestAttributeSet pras = new HashPrintRequestAttributeSet(); DocFlavor flavor = DocFlavor.INPUT_STREAM.AUTOSENSE; PrintService printService[] = PrintServiceLookup.lookupPrintServices(flavor, pras); PrintService defaultService = PrintServiceLookup.lookupDefaultPrintService(); for(String pdfFileName : pdfFileNames) { DocPrintJob job = (defaultService == null) ? null : defaultService.createPrintJob(); if(job == null) { if(printService.length > 0) { job = printService[0].createPrintJob(); } } if(job == null) continue; try { // docオブジェクトを生成 FileInputStream data = new FileInputStream(pdfFileName); DocAttributeSet docAttributes = new HashDocAttributeSet(); Doc doc = new SimpleDoc(data, flavor, docAttributes); // 印刷 job.print(doc, pras); }catch (IOException | PrintException e) { e.printStackTrace(); } try{ Thread.sleep(100); }catch(InterruptedException ex) {} } }else{ // ダイアログ表示(プロパティ等は選択できない) PrintRequestAttributeSet pras = new HashPrintRequestAttributeSet(); DocFlavor flavor = DocFlavor.INPUT_STREAM.AUTOSENSE; PrintService printService[] = PrintServiceLookup.lookupPrintServices(flavor, pras); PrintService defaultService = PrintServiceLookup.lookupDefaultPrintService(); if(printService.length > 0) { PrintService service = ServiceUI.printDialog(null, 200, 200, printService, defaultService, flavor, pras); if(service != null) { for(String pdfFileName : pdfFileNames) { DocPrintJob job = service.createPrintJob(); //DocPrintJob job = defaultService.createPrintJob(); //FileOutputStream fis; FileInputStream fis; try { fis = new FileInputStream(pdfFileName); DocAttributeSet das = new HashDocAttributeSet(); Doc doc = new SimpleDoc(fis, flavor, das); //Doc doc = new SimpleDoc(fis, flavor, null); job.print(doc, pras); //job.print(doc, null); } catch (FileNotFoundException ex) { Logger.getLogger(LaboTestOutputPDF.class.getName()).log(Level.SEVERE, null, ex); } catch (PrintException ex) { Logger.getLogger(LaboTestOutputPDF.class.getName()).log(Level.SEVERE, null, ex); } try{ Thread.sleep(100); }catch(InterruptedException ex) {} } } } } } //s.oh$ private ImageIcon adjustImageSize(ImageIcon icon, Dimension dim) { if ((icon.getIconHeight() > dim.height) || (icon.getIconWidth() > dim.width)) { Image img = icon.getImage(); float hRatio = (float) icon.getIconHeight() / dim.height; float wRatio = (float) icon.getIconWidth() / dim.width; int h,w; if (hRatio > wRatio) { h = dim.height; w = (int) (icon.getIconWidth() / hRatio); } else { w = dim.width; h = (int) (icon.getIconHeight() / wRatio); } img = img.getScaledInstance(w, h, Image.SCALE_SMOOTH); return new ImageIcon(img); } else { return icon; } } private byte[] getJPEGByte(Image image) { byte[] ret = null; try { Dimension d = new Dimension(image.getWidth(null), image.getHeight(null)); BufferedImage bf = new BufferedImage(d.width, d.height, BufferedImage.TYPE_INT_RGB); Graphics g = bf.getGraphics(); g.setColor(Color.white); g.drawImage(image, 0, 0, d.width, d.height, null); ByteArrayOutputStream bo = new ByteArrayOutputStream(); ImageIO.write(bf, "jpeg", bo); ret = bo.toByteArray(); } catch (IOException e) { e.printStackTrace(System.err); } return ret; } }