001: package com.xoetrope.export;
002:
003: import java.io.BufferedReader;
004: import java.io.File;
005: import java.io.FileNotFoundException;
006: import java.io.IOException;
007: import java.io.UnsupportedEncodingException;
008: import java.net.URL;
009: import java.util.ArrayList;
010: import java.util.Vector;
011: import javax.swing.SwingUtilities;
012: import net.xoetrope.xml.XmlElement;
013: import net.xoetrope.xml.XmlSource;
014: import net.xoetrope.xui.XProject;
015: import net.xoetrope.xui.data.XModel;
016: import net.xoetrope.xui.helper.SwingWorker;
017: import net.xoetrope.xui.helper.XuiUtilities;
018:
019: /**
020: * <p>
021: * Preprocessor for substituting variables intoa document before export. For
022: * example the XML element
023: * <code><Replaceable>Address</Replaceable></code> becomes
024: * <code>Rathfarnham, Dublin, Ireland</code> becomes if the <code>eventNode</code>
025: * passed to the <code>printDocument</code> method contains an element with the
026: * <code>id</code> of <code>Address</code> containing the value, in the above
027: * example. Similarly the
028: * <code><Replaceable>xui_state/Address</Replaceable></code> becomes
029: * <code>Rathfarnham, Dublin, Ireland</code> becomes if the <code>stateNode</code>
030: * passed to the <code>printDocument</code> method contains an element with the
031: * <code>id</code> of <code>Address</code> containing the value, in the above
032: * example. The use of two nodes allows you to distinguish between input values
033: * and the output or state values saved by the data bindings - the results of
034: * user input and selections.
035: * </p>
036: * <p>
037: * The TemplatePreprocessor first makes the substitutions described above and
038: * the passes the processed XML to an instance of the <code>TemplateExporter</code>
039: * class, and once the export file has been generated the document is either
040: * saved, previewed or printed.
041: * </p>
042: * <p>
043: * In preview mode an attempt is made to find a document with the suffix
044: * <code>Preview</code>, such that a document name <code>myDocument</code> is
045: * replaced with <code>myDocumentPreview</code>. If the preview document is not
046: * found then the original document name is used. A file extension of
047: * <code>.xml</code> is assumed. The preview mode is designed to allow a
048: * different view of a document to be displayed, for example when previewing a
049: * letter that may be printed of headed paper. The preview version of the
050: * document may then contain the information that is on the pre-printed paper.
051: * </p>
052: *
053: * <p> Copyright (c) Xoetrope Ltd., 2001-2006, This software is licensed under
054: * the GNU Public License (GPL), please see license.txt for more details. If
055: * you make commercial use of this software you must purchase a commercial
056: * license from Xoetrope.</p>
057: * <p> $Revision: 1.2 $</p>
058: */
059: public class TemplatePreprocessor {
060: public static final String dateSeparator = " ";
061: public static final String fieldSeparator = ":";
062:
063: public static final int SAVE = 0;
064: public static final int PRINT = 1;
065: public static final int PREVIEW = 2;
066:
067: private XProject currentProject;
068: private TemplateExporter exporter;
069:
070: private ArrayList marginList;
071:
072: /**
073: * Creates a new instance of TemplatePreprocessor
074: */
075: public TemplatePreprocessor(XProject project) {
076: currentProject = project;
077: }
078:
079: /**
080: * Output the document in (PDF/Excel/Html) form and preview or print with the
081: * default viewer
082: * @param templateFile the letter template file
083: * @param action true to attempt use of a preview template
084: * @param exportType the export format e.g. Exporter.PDF_EXPORTER
085: * @param eventNode a node from which Replaceable elements can be substituted
086: * @param stateNode a node from which Replaceable elements prefixed with the
087: * xui_state/ string can be substituted
088: */
089: public String printDocument(String templateFile, int action,
090: int exportType, XModel eventNode, XModel stateNode) {
091: try {
092: if (action == PREVIEW) {
093: URL templateURL = currentProject
094: .findResource(templateFile + "Preview.xml");
095: if (templateURL != null) {
096: File f = new File(templateURL.toURI());
097: if (f.exists())
098: templateFile += "Preview";
099: }
100: }
101: BufferedReader reader = currentProject
102: .getBufferedReader(templateFile + ".xml");
103: XmlSource xmlSrc = new XmlSource();
104: XmlElement rootElement = xmlSrc.read(reader);
105: if (rootElement != null) {
106: doReplacement(rootElement, eventNode, stateNode);
107:
108: File fOut = File.createTempFile("print", ".pdf");
109: String outputFileName = fOut.getCanonicalPath();
110:
111: exporter = new TemplateExporter(currentProject, this ,
112: rootElement, exportType, marginList);
113:
114: exporter.writeToFile(outputFileName);
115:
116: if (action != SAVE) {
117: String os = System.getProperty("os.name");
118: if (os.toLowerCase().indexOf("windows") >= 0) {
119: if (action == PREVIEW)
120: XuiUtilities.exec(new String[] {
121: "rundll32",
122: "url.dll,FileProtocolHandler",
123: outputFileName });
124: else {
125: // FOR WINDOWS 95 AND 98 USE COMMAND.COM
126: String commanProcessor;
127: if (os.equals("Windows 95")
128: || os.equals("Windows 98"))
129: commanProcessor = "command.com";
130: else
131: commanProcessor = "cmd.exe";
132:
133: String acrord32 = XuiUtilities
134: .getRegistryEntry("HKEY_CLASSES_ROOT\\acrobat\\shell\\open\\command");
135: acrord32 = acrord32.substring(acrord32
136: .indexOf("REG_SZ") + 6);
137: acrord32 = acrord32.substring(0, acrord32
138: .indexOf("/u"));
139: acrord32 = acrord32.trim();
140:
141: final String programName = acrord32;
142: final String fileName = outputFileName;
143: SwingWorker worker = new SwingWorker() {
144: public Object construct() {
145: XuiUtilities.exec(new String[] {
146: "\"" + programName + "\"",
147: "/t",
148: "\"" + fileName + "\"" });
149: return "null";
150: }
151:
152: public void finished() {
153: SwingUtilities
154: .invokeLater(new Runnable() {
155: public void run() {
156: System.out
157: .print("Print job complete");
158: }
159: });
160: }
161: };
162: worker.start();
163: }
164: } else if (os.toLowerCase().indexOf("linux") >= 0) {
165: Runtime.getRuntime().exec(
166: new String[] {
167: (action == PREVIEW ? "acroread"
168: : "lpr"),
169: outputFileName });
170: } else
171: XuiUtilities.exec(new String[] {
172: action == PREVIEW ? "open" : "print",
173: outputFileName });
174: }
175:
176: return outputFileName;
177: }
178: } catch (Exception e) {
179: e.printStackTrace();
180: }
181:
182: return null;
183: }
184:
185: // 19-10-06 Sets the margin prperties of the pdf
186: public void setPdfProperties(ArrayList marginList) {
187: this .marginList = marginList;
188: }
189:
190: public void doReplacement(XmlElement xmlElement, XModel eventNode,
191: XModel stateNode) throws IOException,
192: FileNotFoundException, UnsupportedEncodingException {
193: Vector children = xmlElement.getChildren();
194: int numChildren = children.size();
195: for (int i = 0; i < numChildren; i++) {
196: XmlElement xmlChild = (XmlElement) children.elementAt(i);
197: String name = xmlChild.getName();
198: if ((name != null) && name.equals("Replaceable"))
199: replace(xmlChild, eventNode, stateNode);
200: doReplacement(xmlChild, eventNode, stateNode);
201: }
202: }
203:
204: private void replace(XmlElement xmlChild, XModel eventNode,
205: XModel stateNode) {
206: String content = xmlChild.getContent();
207: String nodeValue;
208: if (content.startsWith("xui_state"))
209: nodeValue = stateNode.getValueAsString(content
210: .substring(10));
211: else
212: nodeValue = eventNode.getValueAsString(content);
213:
214: if (nodeValue == null)
215: xmlChild.setContent("");
216: else {
217: String part = xmlChild.getAttribute("part");
218: if ("date".equals(part))
219: xmlChild.setContent(nodeValue.substring(0,
220: nodeValue.indexOf(dateSeparator)).trim());
221: else if ("time".equals(part))
222: xmlChild.setContent(nodeValue.substring(
223: nodeValue.indexOf(dateSeparator)).trim());
224: else {
225: if (part != null) {
226: String[] tokens = nodeValue.split(fieldSeparator);
227: int idx = Integer.parseInt(part);
228: if (idx < tokens.length)
229: nodeValue = tokens[idx];
230: else
231: nodeValue = "";
232: }
233: xmlChild.setContent(nodeValue);
234: }
235: }
236: }
237: }
|