001: package jimm.datavision.layout;
002:
003: import jimm.datavision.*;
004: import jimm.datavision.field.*;
005: import java.io.*;
006:
007: /**
008: * <code>CharSepLE</code> is a layout engine that outputs text data files.
009: * Output is one line per row of data. Column data is separated by a
010: * user-specified character.
011: *
012: * @author Jim Menard, <a href="mailto:jimm@io.com">jimm@io.com</a>
013: */
014: public class CharSepLE extends SortedLayoutEngine {
015:
016: protected char sepChar;
017: protected boolean first;
018:
019: /**
020: * Constructor.
021: *
022: * @param out the output writer
023: * @param sepChar the character used to separate column data
024: */
025: public CharSepLE(PrintWriter out, char sepChar) {
026: super (out);
027: this .sepChar = sepChar;
028: }
029:
030: /**
031: * This override handles output of a section.
032: *
033: * @param sect section
034: */
035: protected void doOutputSection(Section sect) {
036: first = true;
037: super .doOutputSection(sect);
038: out.println();
039: }
040:
041: /**
042: * This override handles output of a field.
043: *
044: * @param field a field
045: */
046: protected void doOutputField(Field field) {
047: String fieldAsString = field.toString();
048: if (fieldAsString == null)
049: fieldAsString = "";
050:
051: if (first)
052: first = false;
053: else
054: out.print(sepChar);
055:
056: // Make fieldAsString safe for comma- or tab-separated data
057: out.print(asSafeSepString(fieldAsString));
058: }
059:
060: protected void doOutputImage(ImageField image) {
061: doOutputField(image);
062: }
063:
064: /**
065: * Ignores line output.
066: *
067: * @param line a line
068: */
069: protected void doOutputLine(Line line) {
070: }
071:
072: /**
073: * Return a string that's safe to use in a comma-delimited data file.
074: * Returns a new string with all double quotes replaced by two double
075: * quotes. If there are any double quotes, commas, or newlines in the
076: * string, the returned string will be surrounded by double quotes.
077: *
078: * @param str a string to be used in a comma-delimited data file
079: * @return a new string that's safe for use in a comma-delimited data file
080: */
081: protected String asSafeSepString(String str) {
082: if (str == null)
083: return "";
084:
085: StringBuffer buf = new StringBuffer();
086: boolean needsToBeQuoted = false;
087: int len = str.length();
088: for (int i = 0; i < len; ++i) {
089: char c = str.charAt(i);
090: switch (c) {
091: case '"':
092: buf.append("\"\"");
093: needsToBeQuoted = true;
094: break;
095: case '\n':
096: case '\r':
097: buf.append(c);
098: needsToBeQuoted = true;
099: break;
100: default:
101: buf.append(c);
102: if (c == sepChar)
103: needsToBeQuoted = true;
104: break;
105: }
106: }
107:
108: if (needsToBeQuoted) {
109: buf.insert(0, '"');
110: buf.append('"');
111: }
112: return buf.toString();
113: }
114:
115: }
|