| RtfUtil.java |
/**
Christopher Scaglione
SW409
Midterm
*/
package rtf;
import java.io.*;
import java.util.StringTokenizer;
import futils.ReaderUtil;
import futils.WriterUtil;
public class RtfUtil implements JavaText {
public static final String HEADER = "{\\rtf1\\ansi\\ansicpg1252\\deff0\\deflang1033" +
"{\\fonttbl{\\f0\\fswiss\\fcharset0 Arial;}}" +
"\\viewkind4\\uc1\\pard\\f0\\fs20";
private boolean javaDocComment = false;
private boolean cStyleComment = false;
private boolean cppStyleComment = false;
private int quoteCount = 0;
private BufferedWriter bw = null;
/**
Converts a Java source file to a RTF file.
@author Christopher Scaglione
@param br is the BufferedReader to read from.
@param _bw is the BufferedWriter to write to.
*/
public void javaToRtf(BufferedReader br, BufferedWriter _bw) {
String line = null;
try {
bw = _bw;
write(HEADER);
while ((line = ReaderUtil.readLine(br)) != null) {
processLine(line);
}
write("}");
bw.flush();
ReaderUtil.close(br);
} catch (IOException e) {
e.printStackTrace();
}
}
/**
Converts a Java source file to a RTF file.
@author Christopher Scaglione
@param javaFile is the Java source file to convert.
@param rtfFile is the RTF file to convert to.
*/
public void javaToRtf(File javaFile, File rtfFile) {
javaToRtf(ReaderUtil.getBufferedReader(javaFile),
WriterUtil.getBufferedWriter(rtfFile));
}
/**
Converts a line of Java source to RTF format.
@author Christopher Scaglione
@param line is the line of Java source to convert.
*/
private void processLine(String line) {
String token = null;
// The delimiters have special codes in RTF, so we want
// them to be returned by the StringTokenizer.
StringTokenizer st = new StringTokenizer(line, " \t\n\r\f", true);
try
{
while (st.hasMoreTokens()) {
token = st.nextToken();
if (token.equals(" ")) {
write(" ");
}
else {
if (token.equals("\t")) {
write(getTab());
} else {
if (token.equals("\n") ||
token.equals("\r") ||
token.equals("\f")) {
write(getPar());
} else {
processToken(token);
}
}
}
}
write(getPar());
// C++-style comments can only span a single line,
// so reset the flag after the line is parsed.
cppStyleComment = false;
} catch (Exception e) {
e.printStackTrace();
}
}
/**
Converts a token of Java source to RTF format.
@author Christopher Scaglione
@param _token is the token of Java source to convert.
*/
private void processToken(String _token) {
boolean reservedWord = false;
String token = null;
String previousToken = null;
String previousPreviousToken = null;
// The token needs to be parsed again to determine if it is a reserved
// word since reserved words may be right next to other characters.
// For example, "for(i = 0", "boolean b = true;".
StringTokenizer st = new StringTokenizer(_token, "\";><=&|!(){}[],\\.:", true);
try {
while (st.hasMoreTokens()) {
reservedWord = false;
token = st.nextToken();
checkForStartComment(token);
// JavaDoc comments will be italic.
if (javaDocComment == true) {
write(getItalic(token));
// Check if we have reached the end of the
// JavaDoc comment. If we have, reset the
// flag.
if (checkForEndComment(token) == true) {
javaDocComment = false;
}
} else {
// C-style comments will be plain.
if (cStyleComment == true) {
write(getPlain(token));
// Check if we have reached the end of the
// C-style comment. If we have, reset the
// flag.
if (checkForEndComment(token) == true) {
cStyleComment = false;
}
} else {
// C++-style comments will be plain.
if (cppStyleComment == true) {
write(getPlain(token));
} else {
if (checkForStringQuote(previousPreviousToken, previousToken, token) == true) {
quoteCount++;
}
// If quoteCount is 1, then we are within a string
// and reserved words do not need to be made bold.
if (quoteCount != 1) {
// Check if this token is a reserved word.
if (isJavaReservedWord(token) == true) {
reservedWord = true;
write(getBold(token));
}
}
if (reservedWord == false) {
write(getPlain(token));
}
// If quoteCount is 2, we have found the
// start and end parentheses for a string,
// so reset quoteCount.
if (quoteCount == 2) {
quoteCount = 0;
}
}
}
}
// Keep track of the 2 previous tokens.
// This is needed to determine a string quote.
previousPreviousToken = previousToken;
previousToken = token;
}
} catch (Exception e) {
e.printStackTrace();
}
}
/**
Determines if the token contains the start of comment
designator for a JavaDoc comment, C-style comment, or
C++-style comment and sets the appropriate flag.
@author Christopher Scaglione
@param The token to search.
*/
private void checkForStartComment(String token) {
// If the quote count is 1, then we are currently
// inside a string and we do not care if we find
// the start of comment designator since it is part
// of the string.
if (quoteCount != 1) {
if (token.indexOf("/**") != -1) {
javaDocComment = true;
} else {
if (token.indexOf("/*") != -1) {
cStyleComment = true;
} else {
if (token.indexOf("//") != -1) {
cppStyleComment = true;
}
}
}
}
}
/**
Determines if the token contains the end of comment
designator.
@author Christopher Scaglione
@param The token to search.
@return True if the end of comment designator was found,
false otherwise.
*/
private boolean checkForEndComment(String token) {
boolean endComment = false;
// If the quote count is 1, then we are currently
// inside a string and we do not care if we find
// the end of comment designator since it is part
// of the string.
if (quoteCount != 1) {
if (token.indexOf("*/") != -1) {
endComment = true;
}
}
return endComment;
}
/**
Determines if the token contains a string quote. To make
this determination requires the 2 previous tokens.
@author Christopher Scaglione
@param previousPreviousToken is the token immediately
before previousToken.
@param previousToken is the token immediately before token.
@param token is the token to search.
*/
private boolean checkForStringQuote(String previousPreviousToken, String previousToken, String token) {
boolean stringQuote = false;
// If one of the comment flags is true, then
// the quote is part of the comment.
if (javaDocComment == false &&
cStyleComment == false &&
cppStyleComment == false) {
if (token.indexOf("\"") != -1) {
stringQuote = true;
if (previousToken != null) {
// Check if the quote is preceded by a backslash.
// If it is, then this could be a quote within
// a string (\").
if (previousToken.equals("\\") == true) {
stringQuote = false;
if (previousPreviousToken != null) {
// Check if the backslash is preceded by another
// backslash. If it is, then this is a quote since
// the 2 previous tokens make up a backslash in
// a string.
if (previousPreviousToken.equals("\\") == true) {
stringQuote = true;
}
}
}
}
}
}
return stringQuote;
}
/**
Checks if the given token is a Java reserved word.
@author Christopher Scaglione
@param The token to check.
@return True if the token is a reserved word,
false otherwise.
*/
private boolean isJavaReservedWord(String token) {
boolean reservedWord = false;
for (int i = 0; i < javaReservedWords.length; i++) {
if (token.compareTo(javaReservedWords[i]) == 0) {
reservedWord = true;
break;
}
}
return reservedWord;
}
/**
Writes a string to the BufferedWriter.
@author Christopher Scaglione
@param s is the string to write to the BufferedWriter.
*/
private void write(String s) {
try {
bw.write(s, 0, s.length());
} catch (IOException e) {
e.printStackTrace();
}
}
/**
Returns a string in italic RTF format.
@author Christopher Scaglione
@param s is the string to format.
@return A string in italic RTF format.
*/
public static String getItalic(String s) {
return "{\\i " + formatCurlyBracesAndBackslashes(s) + "}";
}
/**
Returns a string in bold RTF format.
@author Christopher Scaglione
@param s is the string to format.
@return A string in bold RTF format.
*/
public static String getBold(String s) {
return "{\\b " + formatCurlyBracesAndBackslashes(s) + "}";
}
/**
Returns a string in plain RTF format.
@author Christopher Scaglione
@param s is the string to format.
@return A string in plain RTF format.
*/
public static String getPlain(String s) {
return "{" + formatCurlyBracesAndBackslashes(s) + "}";
}
/**
Returns a paragraph break in RTF format.
@author Christopher Scaglione
@return A paragraph break in RTF format.
*/
public static String getPar() {
return "{\\par}";
}
/**
Returns a tab in RTF format.
@author Christopher Scaglione
@return A tab in RTF format.
*/
public static String getTab() {
return "{\\tab}";
}
/**
Returns a string with curly braces and backslashes in RTF format.
Any displayed curly braces or backslashes in RTF must be preceded by
a "\" since "{", "}", and "\" are used for control characters.
@author Christopher Scaglione
@param s is the string to format.
@return A string with curly braces in RTF format.
*/
public static String formatCurlyBracesAndBackslashes(String s) {
String formattedString = "";
char ch;
for (int i = 0; i < s.length(); i++) {
ch = s.charAt(i);
if (ch == '{' || ch == '}' || ch == '\\') {
formattedString = formattedString.concat("\\");
}
formattedString = formattedString.concat(String.valueOf(ch));
}
return formattedString;
}
}