選択できるのは25トピックまでです。 トピックは、先頭が英数字で、英数字とダッシュ('-')を使用した35文字以内のものにしてください。

RtfElement.java 11KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350
  1. /*
  2. * Licensed to the Apache Software Foundation (ASF) under one or more
  3. * contributor license agreements. See the NOTICE file distributed with
  4. * this work for additional information regarding copyright ownership.
  5. * The ASF licenses this file to You under the Apache License, Version 2.0
  6. * (the "License"); you may not use this file except in compliance with
  7. * the License. You may obtain a copy of the License at
  8. *
  9. * http://www.apache.org/licenses/LICENSE-2.0
  10. *
  11. * Unless required by applicable law or agreed to in writing, software
  12. * distributed under the License is distributed on an "AS IS" BASIS,
  13. * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  14. * See the License for the specific language governing permissions and
  15. * limitations under the License.
  16. */
  17. /* $Id$ */
  18. package org.apache.fop.render.rtf.rtflib.rtfdoc;
  19. /*
  20. * This file is part of the RTF library of the FOP project, which was originally
  21. * created by Bertrand Delacretaz <bdelacretaz@codeconsult.ch> and by other
  22. * contributors to the jfor project (www.jfor.org), who agreed to donate jfor to
  23. * the FOP project.
  24. */
  25. import java.io.IOException;
  26. import java.io.Writer;
  27. import java.util.Iterator;
  28. /**
  29. * <p>Base class for all elements of an RTF file.</p>
  30. *
  31. * <p>This work was authored by Bertrand Delacretaz (bdelacretaz@codeconsult.ch)
  32. * and Andreas Putz (a.putz@skynamics.com).</p>
  33. */
  34. public abstract class RtfElement {
  35. /** Writer to be used */
  36. protected final Writer writer;
  37. /** parent element */
  38. protected final RtfContainer parent;
  39. /** attributes of the element */
  40. protected final RtfAttributes attrib;
  41. private boolean written;
  42. private boolean closed;
  43. private final int id;
  44. private static int idCounter;
  45. /** Create an RTF element as a child of given container */
  46. RtfElement(RtfContainer parent, Writer w) throws IOException {
  47. this(parent, w, null);
  48. }
  49. /** Create an RTF element as a child of given container with given attributes */
  50. RtfElement(RtfContainer parent, Writer w, RtfAttributes attr) throws IOException {
  51. // @SuppressFBWarnings("ST_WRITE_TO_STATIC_FROM_INSTANCE_METHOD")
  52. id = idCounter++;
  53. this.parent = parent;
  54. attrib = (attr != null ? attr : new RtfAttributes());
  55. if (this.parent != null) {
  56. this.parent.addChild(this);
  57. }
  58. writer = w;
  59. written = false;
  60. }
  61. /**
  62. * Does nothing, meant to allow elements to write themselves without waiting
  63. * for write(), but not implemented yet
  64. * @throws IOException for I/O problems
  65. */
  66. public final void close() throws IOException {
  67. closed = true;
  68. }
  69. /**
  70. * Write the RTF code of this element to our Writer
  71. * @throws IOException for I/O problems
  72. */
  73. public final void writeRtf() throws IOException {
  74. if (!written) {
  75. written = true;
  76. if (okToWriteRtf()) {
  77. writeRtfPrefix();
  78. writeRtfContent();
  79. writeRtfSuffix();
  80. }
  81. }
  82. }
  83. /**
  84. * Starts a new line in the RTF file being written. This is only to format
  85. * the RTF file itself (for easier debugging), not its content.
  86. * @throws IOException in case of an I/O problem
  87. */
  88. public void newLine() throws IOException {
  89. writer.write("\n");
  90. }
  91. /**
  92. * Write an RTF control word to our Writer
  93. * @param word RTF control word to write
  94. * @throws IOException for I/O problems
  95. */
  96. protected final void writeControlWord(String word)
  97. throws IOException {
  98. writer.write('\\');
  99. writer.write(word);
  100. writer.write(' ');
  101. }
  102. /**
  103. * Write an RTF control word to our Writer, preceeded by a star '*'
  104. * meaning "ignore this if you don't know what it means"
  105. * @param word RTF control word to write
  106. * @throws IOException for I/O problems
  107. */
  108. protected final void writeStarControlWord(String word)
  109. throws IOException {
  110. writer.write("\\*\\");
  111. writer.write(word);
  112. writer.write(' ');
  113. }
  114. /**
  115. * Same as writeStarControlWord(String word), except with no space behind it
  116. * @param word RTF control word to write
  117. * @throws IOException for I/O problems
  118. */
  119. protected final void writeStarControlWordNS(String word)
  120. throws IOException {
  121. writer.write("\\*\\");
  122. writer.write(word);
  123. }
  124. /**
  125. * Write rtf control word without the space behind it
  126. * @param word RTF control word to write
  127. * @throws IOException for I/O problems
  128. */
  129. protected final void writeControlWordNS(String word)
  130. throws IOException {
  131. writer.write('\\');
  132. writer.write(word);
  133. }
  134. /**
  135. * Called before writeRtfContent()
  136. * @throws IOException for I/O problems
  137. */
  138. protected void writeRtfPrefix() throws IOException {
  139. }
  140. /**
  141. * Must be implemented to write RTF content to m_writer
  142. * @throws IOException for I/O problems
  143. */
  144. protected abstract void writeRtfContent() throws IOException;
  145. /**
  146. * Called after writeRtfContent()
  147. * @throws IOException for I/O problems
  148. */
  149. protected void writeRtfSuffix() throws IOException {
  150. }
  151. /**
  152. * Write a start or end group mark
  153. * @param isStart set to true if this is a start mark
  154. * @throws IOException for I/O problems
  155. */
  156. protected final void writeGroupMark(boolean isStart)
  157. throws IOException {
  158. writer.write(isStart ? "{" : "}");
  159. }
  160. /**
  161. * Write given attribute values to our Writer
  162. * @param attr RtfAttributes to be written
  163. * @param nameList if given, only attribute names from this list are considered
  164. * @throws IOException for I/O problems
  165. */
  166. protected void writeAttributes(RtfAttributes attr, String [] nameList)
  167. throws IOException {
  168. if (attr == null) {
  169. return;
  170. }
  171. if (nameList != null) {
  172. // process only given attribute names
  173. for (final String name : nameList) {
  174. if (attr.isSet(name)) {
  175. writeOneAttribute(name, attr.getValue(name));
  176. }
  177. }
  178. } else {
  179. // process all defined attributes
  180. for (Iterator it = attr.nameIterator(); it.hasNext();) {
  181. final String name = (String)it.next();
  182. if (attr.isSet(name)) {
  183. writeOneAttribute(name, attr.getValue(name));
  184. }
  185. }
  186. }
  187. }
  188. /**
  189. * Write one attribute to our Writer
  190. * @param name name of attribute to write
  191. * @param value value of attribute to be written
  192. * @throws IOException for I/O problems
  193. */
  194. protected void writeOneAttribute(String name, Object value)
  195. throws IOException {
  196. String cw = name;
  197. if (value instanceof Integer) {
  198. // attribute has integer value, must write control word + value
  199. cw += value;
  200. } else if (value instanceof String) {
  201. cw += value;
  202. } else if (value instanceof RtfAttributes) {
  203. writeControlWord(cw);
  204. writeAttributes((RtfAttributes) value, null);
  205. return;
  206. }
  207. writeControlWord(cw);
  208. }
  209. /**
  210. * Write one attribute to our Writer without a space
  211. * @param name name of attribute to write
  212. * @param value value of attribute to be written
  213. * @throws IOException for I/O problems
  214. */
  215. protected void writeOneAttributeNS(String name, Object value)
  216. throws IOException {
  217. String cw = name;
  218. if (value instanceof Integer) {
  219. // attribute has integer value, must write control word + value
  220. cw += value;
  221. } else if (value instanceof String) {
  222. cw += value;
  223. } else if (value instanceof RtfAttributes) {
  224. writeControlWord(cw);
  225. writeAttributes((RtfAttributes) value, null);
  226. return;
  227. }
  228. writeControlWordNS(cw);
  229. }
  230. /**
  231. * can be overridden to suppress all RTF output
  232. * @return true if this object can be written into the RTF
  233. */
  234. protected boolean okToWriteRtf() {
  235. return true;
  236. }
  237. /** debugging to given PrintWriter */
  238. void dump(Writer w, int indent)
  239. throws IOException {
  240. for (int i = 0; i < indent; i++) {
  241. w.write(' ');
  242. }
  243. w.write(this.toString());
  244. w.write('\n');
  245. w.flush();
  246. }
  247. /**
  248. * minimal debugging display
  249. * @return String representation of object
  250. */
  251. public String toString() {
  252. return (this == null) ? "null" : (this.getClass().getName() + " #" + id);
  253. }
  254. /** true if close() has been called */
  255. boolean isClosed() {
  256. return closed;
  257. }
  258. /** access our RtfFile, which is always the topmost parent */
  259. RtfFile getRtfFile() {
  260. // go up the chain of parents until we find the topmost one
  261. RtfElement result = this;
  262. while (result.parent != null) {
  263. result = result.parent;
  264. }
  265. // topmost parent must be an RtfFile
  266. // a ClassCastException here would mean that the parent-child structure is not as expected
  267. return (RtfFile)result;
  268. }
  269. /** find the first parent where c.isAssignableFrom(parent.getClass()) is true
  270. * @return null if not found
  271. */
  272. public RtfElement getParentOfClass(Class c) {
  273. RtfElement result = null;
  274. RtfElement current = this;
  275. while (current.parent != null) {
  276. current = current.parent;
  277. if (c.isAssignableFrom(current.getClass())) {
  278. result = current;
  279. break;
  280. }
  281. }
  282. return result;
  283. }
  284. /**
  285. * @return true if this element would generate no "useful" RTF content
  286. */
  287. public abstract boolean isEmpty();
  288. /**
  289. * Make a visible entry in the RTF for an exception
  290. * @param ie Exception to flag
  291. * @throws IOException for I/O problems
  292. */
  293. protected void writeExceptionInRtf(Exception ie)
  294. throws IOException {
  295. writeGroupMark(true);
  296. writeControlWord("par");
  297. // make the exception message stand out so that the problem is visible
  298. writeControlWord("fs48");
  299. // RtfStringConverter.getInstance().writeRtfString(m_writer,
  300. // JForVersionInfo.getShortVersionInfo() + ": ");
  301. RtfStringConverter.getInstance().writeRtfString(writer, ie.getClass().getName());
  302. writeControlWord("fs20");
  303. RtfStringConverter.getInstance().writeRtfString(writer, " " + ie.toString());
  304. writeControlWord("par");
  305. writeGroupMark(false);
  306. }
  307. /**
  308. * Added by Normand Masse
  309. * Used for attribute inheritance
  310. * @return RtfAttributes
  311. */
  312. public RtfAttributes getRtfAttributes() {
  313. return attrib;
  314. }
  315. }