You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

RtfElement.java 12KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365
  1. /*
  2. * $Id$
  3. * ============================================================================
  4. * The Apache Software License, Version 1.1
  5. * ============================================================================
  6. *
  7. * Copyright (C) 1999-2003 The Apache Software Foundation. All rights reserved.
  8. *
  9. * Redistribution and use in source and binary forms, with or without modifica-
  10. * tion, are permitted provided that the following conditions are met:
  11. *
  12. * 1. Redistributions of source code must retain the above copyright notice,
  13. * this list of conditions and the following disclaimer.
  14. *
  15. * 2. Redistributions in binary form must reproduce the above copyright notice,
  16. * this list of conditions and the following disclaimer in the documentation
  17. * and/or other materials provided with the distribution.
  18. *
  19. * 3. The end-user documentation included with the redistribution, if any, must
  20. * include the following acknowledgment: "This product includes software
  21. * developed by the Apache Software Foundation (http://www.apache.org/)."
  22. * Alternately, this acknowledgment may appear in the software itself, if
  23. * and wherever such third-party acknowledgments normally appear.
  24. *
  25. * 4. The names "FOP" and "Apache Software Foundation" must not be used to
  26. * endorse or promote products derived from this software without prior
  27. * written permission. For written permission, please contact
  28. * apache@apache.org.
  29. *
  30. * 5. Products derived from this software may not be called "Apache", nor may
  31. * "Apache" appear in their name, without prior written permission of the
  32. * Apache Software Foundation.
  33. *
  34. * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED WARRANTIES,
  35. * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
  36. * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
  37. * APACHE SOFTWARE FOUNDATION OR ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
  38. * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLU-
  39. * DING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
  40. * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
  41. * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
  42. * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
  43. * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  44. * ============================================================================
  45. *
  46. * This software consists of voluntary contributions made by many individuals
  47. * on behalf of the Apache Software Foundation and was originally created by
  48. * James Tauber <jtauber@jtauber.com>. For more information on the Apache
  49. * Software Foundation, please see <http://www.apache.org/>.
  50. */
  51. /*
  52. * This file is part of the RTF library of the FOP project, which was originally
  53. * created by Bertrand Delacretaz <bdelacretaz@codeconsult.ch> and by other
  54. * contributors to the jfor project (www.jfor.org), who agreed to donate jfor to
  55. * the FOP project.
  56. */
  57. package org.apache.fop.render.rtf.rtflib.rtfdoc;
  58. import java.io.Writer;
  59. import java.io.IOException;
  60. import java.util.Iterator;
  61. //import org.apache.fop.render.rtf.rtflib.jfor.main.JForVersionInfo;
  62. /** Base class for all elements of an RTF file.
  63. * @author Bertrand Delacretaz bdelacretaz@codeconsult.ch
  64. * @author Andreas Putz a.putz@skynamics.com
  65. */
  66. public abstract class RtfElement {
  67. /** Writer to be used */
  68. protected final Writer writer;
  69. /** parent element */
  70. protected final RtfContainer parent;
  71. /** attributes of the element */
  72. protected final RtfAttributes attrib;
  73. private boolean written;
  74. private boolean closed;
  75. private final int id;
  76. private static int idCounter;
  77. /** Create an RTF element as a child of given container */
  78. RtfElement(RtfContainer parent, Writer w) throws IOException {
  79. this(parent, w, null);
  80. }
  81. /** Create an RTF element as a child of given container with given attributes */
  82. RtfElement(RtfContainer parent, Writer w, RtfAttributes attr) throws IOException {
  83. id = idCounter++;
  84. this.parent = parent;
  85. attrib = (attr != null ? attr : new RtfAttributes());
  86. if (this.parent != null) {
  87. this.parent.addChild(this);
  88. }
  89. writer = w;
  90. written = false;
  91. }
  92. /**
  93. * Does nothing, meant to allow elements to write themselves without waiting
  94. * for write(), but not implemented yet
  95. * @throws IOException for I/O problems
  96. */
  97. public final void close() throws IOException {
  98. closed = true;
  99. }
  100. /**
  101. * Write the RTF code of this element to our Writer
  102. * @throws IOException for I/O problems
  103. */
  104. public final void writeRtf() throws IOException {
  105. if (!written) {
  106. written = true;
  107. if (okToWriteRtf()) {
  108. writeRtfPrefix();
  109. writeRtfContent();
  110. writeRtfSuffix();
  111. }
  112. }
  113. }
  114. /**
  115. * Write an RTF control word to our Writer
  116. * @param word RTF control word to write
  117. * @throws IOException for I/O problems
  118. */
  119. protected final void writeControlWord(String word)
  120. throws IOException {
  121. writer.write('\\');
  122. writer.write(word);
  123. writer.write(' ');
  124. }
  125. /**
  126. * Write an RTF control word to our Writer, preceeded by a star '*'
  127. * meaning "ignore this if you don't know what it means"
  128. * @param word RTF control word to write
  129. * @throws IOException for I/O problems
  130. */
  131. protected final void writeStarControlWord(String word)
  132. throws IOException {
  133. writer.write("\\*\\");
  134. writer.write(word);
  135. writer.write(' ');
  136. }
  137. /**
  138. * Same as writeStarControlWord(String word), except with no space behind it
  139. * @param word RTF control word to write
  140. * @throws IOException for I/O problems
  141. */
  142. protected final void writeStarControlWordNS(String word)
  143. throws IOException {
  144. writer.write("\\*\\");
  145. writer.write(word);
  146. }
  147. /**
  148. * Write rtf control word without the space behind it
  149. * @param word RTF control word to write
  150. * @throws IOException for I/O problems
  151. */
  152. protected final void writeControlWordNS(String word)
  153. throws IOException {
  154. writer.write('\\');
  155. writer.write(word);
  156. }
  157. /**
  158. * Called before writeRtfContent()
  159. * @throws IOException for I/O problems
  160. */
  161. protected void writeRtfPrefix() throws IOException {
  162. }
  163. /**
  164. * Must be implemented to write RTF content to m_writer
  165. * @throws IOException for I/O problems
  166. */
  167. protected abstract void writeRtfContent() throws IOException;
  168. /**
  169. * Called after writeRtfContent()
  170. * @throws IOException for I/O problems
  171. */
  172. protected void writeRtfSuffix() throws IOException {
  173. }
  174. /**
  175. * Write a start or end group mark
  176. * @param isStart set to true if this is a start mark
  177. * @throws IOException for I/O problems
  178. */
  179. protected final void writeGroupMark(boolean isStart)
  180. throws IOException {
  181. writer.write(isStart ? "{" : "}");
  182. }
  183. /**
  184. * Write given attribute values to our Writer
  185. * @param attr RtfAttributes to be written
  186. * @param nameList if given, only attribute names from this list are considered
  187. * @throws IOException for I/O problems
  188. */
  189. protected void writeAttributes(RtfAttributes attr, String [] nameList)
  190. throws IOException {
  191. if (attr == null) {
  192. return;
  193. }
  194. if (nameList != null) {
  195. // process only given attribute names
  196. for (int i = 0; i < nameList.length; i++) {
  197. final String name = nameList[i];
  198. if (attr.isSet(name)) {
  199. writeOneAttribute(name, attr.getValue(name));
  200. }
  201. }
  202. } else {
  203. // process all defined attributes
  204. for (Iterator it = attr.nameIterator(); it.hasNext();) {
  205. final String name = (String)it.next();
  206. if (attr.isSet(name)) {
  207. writeOneAttribute(name, attr.getValue(name));
  208. }
  209. }
  210. }
  211. }
  212. /**
  213. * Write one attribute to our Writer
  214. * @param name name of attribute to write
  215. * @param value value of attribute to be written
  216. * @throws IOException for I/O problems
  217. */
  218. protected void writeOneAttribute(String name, Object value)
  219. throws IOException {
  220. String cw = name;
  221. if (value instanceof Integer) {
  222. // attribute has integer value, must write control word + value
  223. cw += value;
  224. } else if (value instanceof String) {
  225. cw += value;
  226. }
  227. writeControlWord(cw);
  228. }
  229. /**
  230. * Write one attribute to our Writer without a space
  231. * @param name name of attribute to write
  232. * @param value value of attribute to be written
  233. * @throws IOException for I/O problems
  234. */
  235. protected void writeOneAttributeNS(String name, Object value)
  236. throws IOException {
  237. String cw = name;
  238. if (value instanceof Integer) {
  239. // attribute has integer value, must write control word + value
  240. cw += value;
  241. } else if (value instanceof String) {
  242. cw += value;
  243. }
  244. writeControlWordNS(cw);
  245. }
  246. /**
  247. * can be overridden to suppress all RTF output
  248. * @return true if this object can be written into the RTF
  249. */
  250. protected boolean okToWriteRtf() {
  251. return true;
  252. }
  253. /** debugging to given PrintWriter */
  254. void dump(Writer w, int indent)
  255. throws IOException {
  256. for (int i = 0; i < indent; i++) {
  257. w.write(' ');
  258. }
  259. w.write(this.toString());
  260. w.write('\n');
  261. w.flush();
  262. }
  263. /**
  264. * minimal debugging display
  265. * @return String representation of object
  266. */
  267. public String toString() {
  268. return (this == null) ? "null" : (this.getClass().getName() + " #" + id);
  269. }
  270. /** true if close() has been called */
  271. boolean isClosed() {
  272. return closed;
  273. }
  274. /** access our RtfFile, which is always the topmost parent */
  275. RtfFile getRtfFile() {
  276. // go up the chain of parents until we find the topmost one
  277. RtfElement result = this;
  278. while (result.parent != null) {
  279. result = result.parent;
  280. }
  281. // topmost parent must be an RtfFile
  282. // a ClassCastException here would mean that the parent-child structure is not as expected
  283. return (RtfFile)result;
  284. }
  285. /** find the first parent where c.isAssignableFrom(parent.getClass()) is true
  286. * @return null if not found
  287. */
  288. RtfElement getParentOfClass(Class c) {
  289. RtfElement result = null;
  290. RtfElement current = this;
  291. while (current.parent != null) {
  292. current = current.parent;
  293. if (c.isAssignableFrom(current.getClass())) {
  294. result = current;
  295. break;
  296. }
  297. }
  298. return result;
  299. }
  300. /**
  301. * @return true if this element would generate no "useful" RTF content
  302. */
  303. public abstract boolean isEmpty();
  304. /**
  305. * Make a visible entry in the RTF for an exception
  306. * @param ie Exception to flag
  307. * @throws IOException for I/O problems
  308. */
  309. protected void writeExceptionInRtf(Exception ie)
  310. throws IOException {
  311. writeGroupMark(true);
  312. writeControlWord("par");
  313. // make the exception message stand out so that the problem is visible
  314. writeControlWord("fs48");
  315. // RtfStringConverter.getInstance().writeRtfString(m_writer,
  316. // JForVersionInfo.getShortVersionInfo() + ": ");
  317. RtfStringConverter.getInstance().writeRtfString(writer, ie.getClass().getName());
  318. writeControlWord("fs20");
  319. RtfStringConverter.getInstance().writeRtfString(writer, " " + ie.toString());
  320. writeControlWord("par");
  321. writeGroupMark(false);
  322. }
  323. /**
  324. * Added by Normand Masse
  325. * Used for attribute inheritance
  326. * @return RtfAttributes
  327. */
  328. public RtfAttributes getRtfAttributes() {
  329. return attrib;
  330. }
  331. }