001: package com.xoetrope.io;
002:
003: import java.awt.Toolkit;
004: import java.awt.datatransfer.Clipboard;
005: import java.awt.datatransfer.ClipboardOwner;
006: import java.awt.datatransfer.StringSelection;
007: import java.awt.datatransfer.Transferable;
008: import java.io.IOException;
009: import java.io.OutputStreamWriter;
010: import java.io.Writer;
011: import java.util.Hashtable;
012: import java.util.Stack;
013:
014: import net.xoetrope.xui.XComponentFactory;
015: import net.xoetrope.xui.XPage;
016: import net.xoetrope.xui.XProject;
017: import net.xoetrope.xui.XProjectManager;
018:
019: /**
020: * <p>A helper class top assist in exporting data to various formats</p>
021: * <p>This class is the basis of all exporters.</p>
022: *
023: * <p> Copyright (c) Xoetrope Ltd., 2001-2006, This software is licensed under
024: * the GNU Public License (GPL), please see license.txt for more details. If
025: * you make commercial use of this software you must purchase a commercial
026: * license from Xoetrope.</p>
027: * <p> $Revision: 1.8 $</p>
028: * @deprecated use the com.xoetrope.export classes instead
029: */
030: public class XExportHelper implements ClipboardOwner {
031: /**
032: * Style name for the export/report header
033: */
034: public static final String HEADER_STYLE = "header";
035:
036: /**
037: * Style name for the export/report footer
038: */
039: public static final String FOOTER_STYLE = "footer";
040:
041: /**
042: * Style name for the export/report main title
043: */
044: public static final String TITLE_STYLE = "title";
045:
046: /**
047: * Style name for the export/report subTitle
048: */
049: public static final String SUB_TITLE_STYLE = "subTitle";
050:
051: /**
052: * Style name for the export/report section heading
053: */
054: public static final String SECTION_TITLE_STYLE = "section";
055:
056: /**
057: * Style name for the export/report subSection heading
058: */
059: public static final String SUB_SECTION_STYLE = "subSection";
060:
061: /**
062: * Style name for the export/report body text
063: */
064: public static final String BODY_STYLE = "body";
065:
066: /**
067: * Style name for the export/report captions
068: */
069: public static final String CAPTION_STYLE = "caption";
070:
071: /**
072: * Style name for the export/report table headers
073: */
074: public static final String TABLE_HEADER_STYLE = "tableHeader";
075:
076: /**
077: * Style name for the export/report table
078: */
079: public static final String TABLE_STYLE = "table";
080:
081: /**
082: * Style name for the export/report alternate rows in tables
083: */
084: public static final String ALT_TABLE_STYLE = "altTable";
085:
086: /**
087: * Style name for the export/report table bold elements
088: */
089: public static final String TABLE_BOLD_STYLE = "tableBold";
090:
091: /**
092: * Style name for the export/report alternate table bold elements
093: */
094: public static final String ALT_TABLE_BOLD_STYLE = "altTableBold";
095:
096: /**
097: * The left delimiter character
098: */
099: protected String leftDelimiter;
100:
101: /**
102: * The right delimiter character
103: */
104: protected String rightDelimiter;
105:
106: /**
107: * The start element e.g. <p> for the html exporter
108: */
109: protected String beginElement;
110:
111: /**
112: * The end or closing element, e.g. </p> for the html exporter
113: */
114: protected String endElement;
115:
116: /**
117: * An element used in closing some other element e.g. / for closing XML elements
118: */
119: protected String elementClosure;
120:
121: /**
122: * The field separator, e.g. ',' for CSV exports
123: */
124: protected String fieldSeparator;
125:
126: /**
127: * A separator for field names, used for CSV exports
128: */
129: protected String fieldNameSeparator;
130:
131: /**
132: * The line feed sequence
133: */
134: protected String lineFeed;
135:
136: /**
137: * The name of the last element
138: */
139: protected String lastElementName;
140:
141: /**
142: * A flag to indicate if an element is the first field to be output
143: */
144: protected boolean firstField;
145:
146: /**
147: * A flag to indicate if element names are to be output, some text formats do
148: * not output element names
149: */
150: protected boolean outputElementNames;
151:
152: /**
153: * A flag to indicate if field names are to be output, some text formats do
154: * not output field names
155: */
156: protected boolean outputFieldNames;
157:
158: /**
159: * The stack of nested element names being process
160: */
161: protected Stack elementNames;
162:
163: /**
164: * The component factory that is used for translation purposes
165: */
166: protected XComponentFactory factory;
167:
168: /**
169: * The default file extension
170: */
171: protected String defaultExtension;
172:
173: /**
174: * A common byte string used to initialize various tags and elements internally
175: */
176: protected static String emptyBytes = "";
177:
178: /**
179: * The output writer
180: */
181: protected Writer writer;
182:
183: /**
184: * The current project
185: */
186: protected XProject currentProject;
187:
188: /**
189: * A table of styles
190: */
191: protected Hashtable styles;
192:
193: protected Hashtable hints;
194:
195: /**
196: * Create a new export helper, with a default .txt file extension
197: */
198: public XExportHelper() {
199: this (".txt");
200: }
201:
202: /**
203: * Create a new export helper
204: * @param defExt the default file extension
205: */
206: public XExportHelper(String defExt) {
207: defaultExtension = defExt;
208: leftDelimiter = rightDelimiter = beginElement = endElement = elementClosure = emptyBytes;
209: fieldSeparator = fieldNameSeparator = lineFeed = emptyBytes;
210: setOutputElementNames(false);
211: setOutputFieldNames(false);
212: styles = new Hashtable();
213: hints = new Hashtable();
214: currentProject = XProjectManager.getCurrentProject();
215: }
216:
217: /**
218: * Create an output writer for the specified file
219: * @param fileName the fileName
220: * @return the writer or null if the file cannot be created
221: */
222: public Writer setupWriter(XPage owner, String fileName) {
223: if (fileName.indexOf(defaultExtension) < 0)
224: fileName += defaultExtension;
225:
226: writer = new OutputStreamWriter(currentProject
227: .getBufferedOutputStream(fileName, false));
228: lastElementName = "";
229: elementNames = new Stack();
230:
231: return writer;
232: }
233:
234: /**
235: * Set a new output writer. First flushes and closes any existing stream
236: * @param w the new output writer
237: */
238: public void setOutputWriter(Writer w) {
239: try {
240: if (w != writer)
241: close();
242: } catch (IOException ex) {
243: }
244:
245: writer = w;
246: lastElementName = "";
247: elementNames = new Stack();
248: }
249:
250: /**
251: * Add a style name for a particular section of the export
252: * @param sectionName the export section
253: * @param styleName the style name
254: */
255: public void addStyle(String sectionName, String styleName) {
256: styles.put(sectionName, styleName);
257: }
258:
259: /**
260: * Add a hint for the exporter
261: * @param name the hint name
262: * @param value the hint value
263: */
264: public void setHint(String name, String value) {
265: hints.remove(name);
266: hints.put(name, value);
267: }
268:
269: /**
270: * Remove a hint for the exporter
271: * @param name the hint name
272: */
273: public void removeHint(String name) {
274: hints.remove(name);
275: }
276:
277: /**
278: * Flushes and closes any existing stream
279: * @throws java.io.IOException thrown if the stream is not ready or if it is in an invalid state
280: */
281: public void close() throws IOException {
282: if (writer != null) {
283: writer.flush();
284: writer.close();
285: }
286: }
287:
288: /**
289: * Output element names as in XML
290: * @param doOutput true to output element names
291: */
292: public void setOutputElementNames(boolean doOutput) {
293: outputElementNames = doOutput;
294: }
295:
296: /**
297: * Output field names as in XML
298: * @param doOutput true to output element names
299: */
300: public void setOutputFieldNames(boolean doOutput) {
301: outputFieldNames = doOutput;
302: }
303:
304: /**
305: * Set the field delimiter preceeding the field value
306: * @param delimStr the delimiter string
307: */
308: public void setLeftDelimiter(String delimStr) {
309: leftDelimiter = delimStr;
310: }
311:
312: /**
313: * Set the field delimiter following the field value
314: * @param delimStr the delimiter string
315: */
316: public void setRightDelimiter(String delimStr) {
317: rightDelimiter = delimStr;
318: }
319:
320: /**
321: * Set the separator between field names and field values
322: * @param separatorStr the separator string
323: */
324: public void setFieldNameSeparator(String separatorStr) {
325: fieldNameSeparator = separatorStr;
326: }
327:
328: /**
329: * Set the separator character for the fields
330: * @param separatorStr the separator string
331: */
332: public void setFieldSeparator(String separatorStr) {
333: fieldSeparator = separatorStr;
334: }
335:
336: /**
337: * Set the component factory. This factory is used for translation of values
338: * and names
339: * @param cf the component factory
340: */
341: public void setComponentFactory(XComponentFactory cf) {
342: factory = cf;
343: }
344:
345: /**
346: * Write the text and terminate with a line feed, new line as appropriate
347: * @param text the text to output
348: * @throws IOException thrown if the stream is not ready or if it is in an invalid state
349: */
350: public void writeLine(String text) throws IOException {
351: writer.write(leftDelimiter);
352: writer.write(text);
353: writer.write(rightDelimiter);
354: writer.write(lineFeed);
355: }
356:
357: /**
358: * Write the opening of a document
359: * @throws IOException thrown if the stream is not ready or if it is in an invalid state
360: */
361: public void startDocument() throws IOException {
362: }
363:
364: /**
365: * Write the ending of a document
366: * @throws IOException thrown if the stream is not ready or if it is in an invalid state
367: */
368: public void endDocument() throws IOException {
369: }
370:
371: /**
372: * Write the opening of a table
373: * @throws IOException thrown if the stream is not ready or if it is in an invalid state
374: */
375: public void startTable() throws IOException {
376: }
377:
378: /**
379: * Write the ending of a table
380: * @throws IOException thrown if the stream is not ready or if it is in an invalid state
381: */
382: public void endTable() throws IOException {
383: }
384:
385: /**
386: * Write the opening of a table record
387: * @throws IOException thrown if the stream is not ready or if it is in an invalid state
388: */
389: public void startRecord() throws IOException {
390: }
391:
392: /**
393: * Write the ending of a table record
394: * @throws IOException thrown if the stream is not ready or if it is in an invalid state
395: */
396: public void endRecord() throws IOException {
397: writer.write(lineFeed);
398: }
399:
400: /**
401: * Write the opening of a table record
402: * @throws IOException thrown if the stream is not ready or if it is in an invalid state
403: */
404: public void startHeader() throws IOException {
405: }
406:
407: /**
408: * Write the ending of a table record
409: * @throws IOException thrown if the stream is not ready or if it is in an invalid state
410: */
411: public void endHeader() throws IOException {
412: }
413:
414: /**
415: * Write the begining/opening of an element
416: * @param elementName the element name
417: * @throws IOException thrown if the stream is not ready or if it is in an invalid state
418: */
419: public void startElement(String elementName) throws IOException {
420: if (!firstField)
421: writer.write(lineFeed);
422: firstField = true;
423: }
424:
425: /**
426: * Write the begining/opening of an element
427: * @param elementName the element name
428: * @param styleName the style of the section title, or the section name e.g. TITLE_SECTION
429: * @throws IOException thrown if the stream is not ready or if it is in an invalid state
430: */
431: public void startElement(String elementName, String styleName)
432: throws IOException {
433: startElement(elementName);
434: }
435:
436: /**
437: * Write the end of an element opening
438: * @throws IOException thrown if the stream is not ready or if it is in an invalid state
439: */
440: public void endElement() throws IOException {
441: }
442:
443: /**
444: * Write the end of an element opening
445: * @param styleName the style of the section title, or the section name e.g. TITLE_SECTION
446: * @throws IOException thrown if the stream is not ready or if it is in an invalid state
447: */
448: public void endElement(String styleName) throws IOException {
449: endElement();
450: }
451:
452: /**
453: * Write the closing of an element
454: * @throws IOException thrown if the stream is not ready or if it is in an invalid state
455: */
456: public void closeElement() throws IOException {
457: }
458:
459: /**
460: * Write the matching ending element
461: * @throws IOException thrown if the stream is not ready or if it is in an invalid state
462: */
463: public void matchElement() throws IOException {
464: }
465:
466: /**
467: * Write the text and terminate with a line feed, new line as appropriate
468: * @param elementName the element name
469: * @param name the field or attribute name
470: * @param value the field or attribute value
471: * @throws IOException thrown if the stream is not ready or if it is in an invalid state
472: */
473: public void writeElement(String elementName, String name,
474: String value) throws IOException {
475: startElement(elementName);
476: writeField(name, value);
477: closeElement();
478: }
479:
480: /**
481: * Write the text and terminate with a line feed, new line as appropriate
482: * @param elementName the element name
483: * @param names the field or attribute names
484: * @param values the field or attribute value
485: * @throws IOException thrown if the stream is not ready or if it is in an invalid state
486: */
487: public void writeElement(String elementName, String[] names,
488: String[] values) throws IOException {
489: startElement(elementName);
490: for (int i = 0; i < names.length; i++)
491: writeField(names[i], values[i]);
492:
493: closeElement();
494: }
495:
496: /**
497: * Write a field
498: * @param name the field name
499: * @param value the field value
500: * @throws IOException thrown if the stream is not ready or if it is in an invalid state
501: */
502: public void writeField(String name, String value)
503: throws IOException {
504: if (!firstField)
505: writer.write(fieldSeparator);
506: else
507: firstField = false;
508: if (outputFieldNames) {
509: writer.write(leftDelimiter);
510: writer.write(prepareFieldName(name));
511: writer.write(rightDelimiter);
512: writer.write(fieldNameSeparator);
513: }
514: writer.write(leftDelimiter);
515: if (value != null)
516: writer.write(value);
517: writer.write(rightDelimiter);
518: }
519:
520: /**
521: * Write a field
522: * @param name the field name
523: * @param value the field value
524: * @param styleName the style to apply
525: * @throws IOException thrown if the stream is not ready or if it is in an invalid state
526: */
527: public void writeText(String name, String value, String styleName)
528: throws IOException {
529: if (!firstField)
530: writer.write(fieldSeparator);
531: else
532: firstField = false;
533: if (outputFieldNames) {
534: writer.write(leftDelimiter);
535: writer.write(prepareFieldName(name));
536: writer.write(rightDelimiter);
537: writer.write(fieldNameSeparator);
538: }
539: writer.write(leftDelimiter);
540: if (value != null)
541: writer.write(value);
542: writer.write(rightDelimiter);
543: }
544:
545: /**
546: * Output an image
547: * @param imageName the file name
548: * @param altText the alternative text
549: */
550: public void writeImage(String imageName, String altText)
551: throws IOException {
552:
553: }
554:
555: /**
556: * Prepare the field name for export
557: * @param name the raw name
558: * @return the prepared value
559: */
560: protected String prepareFieldName(String name) {
561: if (factory != null)
562: name = factory.translate(name);
563: return name;
564: }
565:
566: /**
567: * Write the section title and terminate with a line feed, new line as appropriate
568: * @param text the text to output
569: * @throws IOException thrown if the stream is not ready or if it is in an invalid state
570: */
571: public void writeSectionTitle(String text) throws IOException {
572: writeLine(prepareFieldName(text));
573: firstField = true;
574: }
575:
576: /**
577: * Write the section title and terminate with a line feed, new line as appropriate
578: * @param text the text to output
579: * @param styleName the style of the section title, or the section name e.g. TITLE_SECTION
580: * @throws IOException thrown if the stream is not ready or if it is in an invalid state
581: */
582: public void writeSectionTitle(String text, String styleName)
583: throws IOException {
584: writeSectionTitle(text);
585: }
586:
587: /**
588: * Write the end of a section
589: * @throws IOException thrown if the stream is not ready or if it is in an invalid state
590: */
591: public void writeSectionEnd() throws IOException {
592: }
593:
594: /**
595: * Output a blank line
596: * @throws IOException thrown if the stream is not ready or if it is in an invalid state
597: */
598: public void writeBlankLine() throws IOException {
599: writer.write(lineFeed);
600: writer.write(lineFeed);
601: }
602:
603: /**
604: * Output a line break
605: * @throws IOException thrown if the stream is not ready or if it is in an invalid state
606: */
607: public void writeBreak() throws IOException {
608: writer.write(lineFeed);
609: }
610:
611: /**
612: * Output a line/ruler
613: * @throws IOException thrown if the stream is not ready or if it is in an invalid state
614: */
615: public void writeHorizontalLine() throws IOException {
616: }
617:
618: /**
619: * Use Microsoft Windows style line ends
620: * @param use true for window line endings, otherwise false.
621: */
622: public void setUseWindowsLineEnd(boolean use) {
623: if (use)
624: lineFeed = "\r\n";
625: else
626: lineFeed = "\n";
627: }
628:
629: /**
630: * Empty implementation of the ClipboardOwner interface.
631: */
632: public void lostOwnership(Clipboard aClipboard,
633: Transferable aContents) {
634: //do nothing
635: }
636:
637: /**
638: * Place a String on the clipboard, and make this class the
639: * owner of the Clipboard's contents.
640: */
641: public void setClipboardContents(String aString) {
642: StringSelection stringSelection = new StringSelection(aString);
643: Clipboard clipboard = Toolkit.getDefaultToolkit()
644: .getSystemClipboard();
645: clipboard.setContents(stringSelection, this);
646: }
647: }
|