org.apache.fop.render.rtf.rtflib.rtfdoc.RtfElement Maven / Gradle / Ivy
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
/* $Id: RtfElement.java 1805173 2017-08-16 10:50:04Z ssteiner $ */
package org.apache.fop.render.rtf.rtflib.rtfdoc;
/*
* This file is part of the RTF library of the FOP project, which was originally
* created by Bertrand Delacretaz [email protected] and by other
* contributors to the jfor project (www.jfor.org), who agreed to donate jfor to
* the FOP project.
*/
import java.io.IOException;
import java.io.Writer;
import java.util.Iterator;
/**
* Base class for all elements of an RTF file.
*
* This work was authored by Bertrand Delacretaz ([email protected])
* and Andreas Putz ([email protected]).
*/
public abstract class RtfElement {
/** Writer to be used */
protected final Writer writer;
/** parent element */
protected final RtfContainer parent;
/** attributes of the element */
protected final RtfAttributes attrib;
private boolean written;
private boolean closed;
private final int id;
private static int idCounter;
/** Create an RTF element as a child of given container */
RtfElement(RtfContainer parent, Writer w) throws IOException {
this(parent, w, null);
}
/** Create an RTF element as a child of given container with given attributes */
RtfElement(RtfContainer parent, Writer w, RtfAttributes attr) throws IOException {
// @SuppressFBWarnings("ST_WRITE_TO_STATIC_FROM_INSTANCE_METHOD")
id = idCounter++;
this.parent = parent;
attrib = (attr != null ? attr : new RtfAttributes());
if (this.parent != null) {
this.parent.addChild(this);
}
writer = w;
written = false;
}
/**
* Does nothing, meant to allow elements to write themselves without waiting
* for write(), but not implemented yet
* @throws IOException for I/O problems
*/
public final void close() throws IOException {
closed = true;
}
/**
* Write the RTF code of this element to our Writer
* @throws IOException for I/O problems
*/
public final void writeRtf() throws IOException {
if (!written) {
written = true;
if (okToWriteRtf()) {
writeRtfPrefix();
writeRtfContent();
writeRtfSuffix();
}
}
}
/**
* Starts a new line in the RTF file being written. This is only to format
* the RTF file itself (for easier debugging), not its content.
* @throws IOException in case of an I/O problem
*/
public void newLine() throws IOException {
writer.write("\n");
}
/**
* Write an RTF control word to our Writer
* @param word RTF control word to write
* @throws IOException for I/O problems
*/
protected final void writeControlWord(String word)
throws IOException {
writer.write('\\');
writer.write(word);
writer.write(' ');
}
/**
* Write an RTF control word to our Writer, preceeded by a star '*'
* meaning "ignore this if you don't know what it means"
* @param word RTF control word to write
* @throws IOException for I/O problems
*/
protected final void writeStarControlWord(String word)
throws IOException {
writer.write("\\*\\");
writer.write(word);
writer.write(' ');
}
/**
* Same as writeStarControlWord(String word), except with no space behind it
* @param word RTF control word to write
* @throws IOException for I/O problems
*/
protected final void writeStarControlWordNS(String word)
throws IOException {
writer.write("\\*\\");
writer.write(word);
}
/**
* Write rtf control word without the space behind it
* @param word RTF control word to write
* @throws IOException for I/O problems
*/
protected final void writeControlWordNS(String word)
throws IOException {
writer.write('\\');
writer.write(word);
}
/**
* Called before writeRtfContent()
* @throws IOException for I/O problems
*/
protected void writeRtfPrefix() throws IOException {
}
/**
* Must be implemented to write RTF content to m_writer
* @throws IOException for I/O problems
*/
protected abstract void writeRtfContent() throws IOException;
/**
* Called after writeRtfContent()
* @throws IOException for I/O problems
*/
protected void writeRtfSuffix() throws IOException {
}
/**
* Write a start or end group mark
* @param isStart set to true if this is a start mark
* @throws IOException for I/O problems
*/
protected final void writeGroupMark(boolean isStart)
throws IOException {
writer.write(isStart ? "{" : "}");
}
/**
* Write given attribute values to our Writer
* @param attr RtfAttributes to be written
* @param nameList if given, only attribute names from this list are considered
* @throws IOException for I/O problems
*/
protected void writeAttributes(RtfAttributes attr, String [] nameList)
throws IOException {
if (attr == null) {
return;
}
if (nameList != null) {
// process only given attribute names
for (final String name : nameList) {
if (attr.isSet(name)) {
writeOneAttribute(name, attr.getValue(name));
}
}
} else {
// process all defined attributes
for (Iterator it = attr.nameIterator(); it.hasNext();) {
final String name = (String)it.next();
if (attr.isSet(name)) {
writeOneAttribute(name, attr.getValue(name));
}
}
}
}
/**
* Write one attribute to our Writer
* @param name name of attribute to write
* @param value value of attribute to be written
* @throws IOException for I/O problems
*/
protected void writeOneAttribute(String name, Object value)
throws IOException {
String cw = name;
if (value instanceof Integer) {
// attribute has integer value, must write control word + value
cw += value;
} else if (value instanceof String) {
cw += value;
} else if (value instanceof RtfAttributes) {
writeControlWord(cw);
writeAttributes((RtfAttributes) value, null);
return;
}
writeControlWord(cw);
}
/**
* Write one attribute to our Writer without a space
* @param name name of attribute to write
* @param value value of attribute to be written
* @throws IOException for I/O problems
*/
protected void writeOneAttributeNS(String name, Object value)
throws IOException {
String cw = name;
if (value instanceof Integer) {
// attribute has integer value, must write control word + value
cw += value;
} else if (value instanceof String) {
cw += value;
} else if (value instanceof RtfAttributes) {
writeControlWord(cw);
writeAttributes((RtfAttributes) value, null);
return;
}
writeControlWordNS(cw);
}
/**
* can be overridden to suppress all RTF output
* @return true if this object can be written into the RTF
*/
protected boolean okToWriteRtf() {
return true;
}
/** debugging to given PrintWriter */
void dump(Writer w, int indent)
throws IOException {
for (int i = 0; i < indent; i++) {
w.write(' ');
}
w.write(this.toString());
w.write('\n');
w.flush();
}
/**
* minimal debugging display
* @return String representation of object
*/
public String toString() {
return (this == null) ? "null" : (this.getClass().getName() + " #" + id);
}
/** true if close() has been called */
boolean isClosed() {
return closed;
}
/** access our RtfFile, which is always the topmost parent */
RtfFile getRtfFile() {
// go up the chain of parents until we find the topmost one
RtfElement result = this;
while (result.parent != null) {
result = result.parent;
}
// topmost parent must be an RtfFile
// a ClassCastException here would mean that the parent-child structure is not as expected
return (RtfFile)result;
}
/** find the first parent where c.isAssignableFrom(parent.getClass()) is true
* @return null if not found
*/
public RtfElement getParentOfClass(Class c) {
RtfElement result = null;
RtfElement current = this;
while (current.parent != null) {
current = current.parent;
if (c.isAssignableFrom(current.getClass())) {
result = current;
break;
}
}
return result;
}
/**
* @return true if this element would generate no "useful" RTF content
*/
public abstract boolean isEmpty();
/**
* Make a visible entry in the RTF for an exception
* @param ie Exception to flag
* @throws IOException for I/O problems
*/
protected void writeExceptionInRtf(Exception ie)
throws IOException {
writeGroupMark(true);
writeControlWord("par");
// make the exception message stand out so that the problem is visible
writeControlWord("fs48");
// RtfStringConverter.getInstance().writeRtfString(m_writer,
// JForVersionInfo.getShortVersionInfo() + ": ");
RtfStringConverter.getInstance().writeRtfString(writer, ie.getClass().getName());
writeControlWord("fs20");
RtfStringConverter.getInstance().writeRtfString(writer, " " + ie.toString());
writeControlWord("par");
writeGroupMark(false);
}
/**
* Added by Normand Masse
* Used for attribute inheritance
* @return RtfAttributes
*/
public RtfAttributes getRtfAttributes() {
return attrib;
}
}