001: package gnu.mapping;
002:
003: import java.io.*;
004: import gnu.text.*;
005: import gnu.lists.*;
006:
007: /**
008: * An extended PrintWriter.
009: */
010:
011: public class OutPort extends PrintConsumer implements Printable {
012: Path path;
013: private Writer base;
014:
015: // To keep track of column-numbers, we use a helper class.
016: // Otherwise, it is too painful, as there is no documented
017: // interface that would allow PrintWriter to be cleanly extended ...
018: // The helper class also lets us make transparent use of WriterManager.
019: protected PrettyWriter bout;
020:
021: /** An index into the WriterManager's internal table.
022: * The value zero means it is unregistered. */
023: protected Object unregisterRef;
024:
025: protected OutPort(Writer base, PrettyWriter out, boolean autoflush) {
026: super (out, autoflush);
027: this .bout = out;
028: this .base = base;
029: if (closeOnExit())
030: unregisterRef = WriterManager.instance.register(out);
031: }
032:
033: protected OutPort(OutPort out, boolean autoflush) {
034: this (out, out.bout, autoflush);
035: }
036:
037: protected OutPort(Writer out, boolean autoflush) {
038: this (out, (out instanceof OutPort ? ((OutPort) out).bout
039: : new PrettyWriter(out, true)), autoflush);
040: }
041:
042: public OutPort(Writer base, boolean printPretty, boolean autoflush) {
043: this (base, new PrettyWriter(base, printPretty), autoflush);
044: }
045:
046: public OutPort(Writer base, boolean printPretty, boolean autoflush,
047: Path path) {
048: this (base, new PrettyWriter(base, printPretty), autoflush);
049: this .path = path;
050: }
051:
052: public OutPort(OutputStream out) {
053: this (out, null);
054: }
055:
056: public OutPort(OutputStream out, Path path) {
057: this (new OutputStreamWriter(out), true, path);
058: }
059:
060: public OutPort(Writer out) {
061: this (out, out instanceof OutPort ? ((OutPort) out).bout
062: : new PrettyWriter(out, false), false);
063: }
064:
065: public OutPort(Writer base, Path path) {
066: this (base, false, false);
067: this .path = path;
068: }
069:
070: public OutPort(Writer base, boolean autoflush, Path path) {
071: this (base, false, autoflush);
072: this .path = path;
073: }
074:
075: public boolean printReadable;
076:
077: static OutPort outInitial = new OutPort(new LogWriter(
078: new BufferedWriter(new OutputStreamWriter(System.out))),
079: true, true, Path.valueOf("/dev/stdout"));
080:
081: private static OutPort errInitial = new OutPort(new LogWriter(
082: new OutputStreamWriter(System.err)), true, true, Path
083: .valueOf("/dev/stderr"));
084:
085: public static final ThreadLocation outLocation = new ThreadLocation(
086: "out-default");
087: static {
088: outLocation.setGlobal(outInitial);
089: }
090: public static final ThreadLocation errLocation = new ThreadLocation(
091: "err-default");
092: static {
093: errLocation.setGlobal(errInitial);
094: }
095:
096: static public OutPort outDefault() {
097: return (OutPort) outLocation.get();
098: }
099:
100: static public void setOutDefault(OutPort o) {
101: outLocation.set(o);
102: }
103:
104: static public OutPort errDefault() {
105: return (OutPort) errLocation.get();
106: }
107:
108: static public void setErrDefault(OutPort e) {
109: errLocation.set(e);
110: }
111:
112: public static OutPort openFile(Object fname)
113: throws java.io.IOException {
114: Object conv = Environment.user().get("port-char-encoding");
115: Path path = Path.valueOf(fname);
116: java.io.OutputStream strm = path.openOutputStream();
117: strm = new java.io.BufferedOutputStream(strm);
118: java.io.Writer wr;
119: if (conv == null || conv == Boolean.TRUE)
120: wr = new java.io.OutputStreamWriter(strm);
121: else {
122: if (conv == Boolean.FALSE)
123: conv = "8859_1";
124: wr = new java.io.OutputStreamWriter(strm, conv.toString());
125: }
126: return new OutPort(wr, path);
127: }
128:
129: public void echo(char[] buf, int off, int len)
130: throws java.io.IOException {
131: if (base instanceof LogWriter)
132: ((LogWriter) base).echo(buf, off, len);
133: }
134:
135: static Writer logFile;
136:
137: public static void closeLogFile() throws java.io.IOException {
138: if (logFile != null) {
139: logFile.close();
140: logFile = null;
141: }
142: if (outInitial.base instanceof LogWriter)
143: ((LogWriter) outInitial.base).setLogFile((Writer) null);
144: if (errInitial.base instanceof LogWriter)
145: ((LogWriter) errInitial.base).setLogFile((Writer) null);
146: }
147:
148: public static void setLogFile(String name)
149: throws java.io.IOException {
150: if (logFile != null)
151: closeLogFile();
152: logFile = new PrintWriter(new BufferedWriter(new FileWriter(
153: name)));
154: if (outInitial.base instanceof LogWriter)
155: ((LogWriter) outInitial.base).setLogFile(logFile);
156: if (errInitial.base instanceof LogWriter)
157: ((LogWriter) errInitial.base).setLogFile(logFile);
158: }
159:
160: /*
161: public void closeLogFile () throws java.io.IOException
162: {
163: if (base instanceof LogWriter)
164: ((LogWriter)base).closeLogFile();
165: }
166:
167: public void setLogFile (String name) throws java.io.IOException
168: {
169: if (base instanceof LogWriter)
170: ((LogWriter)base).setLogFile(name);
171: }
172: */
173:
174: protected static final boolean isWordChar(char ch) {
175: return Character.isJavaIdentifierPart(ch) || ch == '-'
176: || ch == '+';
177: }
178:
179: // java.text.FieldPosition fieldPosition;
180:
181: /** If non-null, use this to print numbers. */
182: java.text.NumberFormat numberFormat;
183:
184: public AbstractFormat objectFormat;
185:
186: public void print(int v) {
187: if (numberFormat == null)
188: super .print(v);
189: else
190: print(numberFormat.format((long) v));
191: }
192:
193: public void print(long v) {
194: if (numberFormat == null)
195: super .print(v);
196: else
197: print(numberFormat.format(v));
198: }
199:
200: public void print(double v) {
201: if (numberFormat == null)
202: super .print(v);
203: else
204: print(numberFormat.format(v));
205: }
206:
207: public void print(float v) {
208: if (numberFormat == null)
209: super .print(v);
210: else
211: print(numberFormat.format((double) v));
212: }
213:
214: public void print(String v) {
215: write(v == null ? "(null)" : v);
216: }
217:
218: public void print(Object v) {
219: if (objectFormat != null)
220: objectFormat.writeObject(v, this );
221: else if (v instanceof Consumable)
222: ((Consumable) v).consume(this );
223: else
224: super .print(v == null ? "null" : v);
225: }
226:
227: public void print(Consumer out) {
228: out.write("#<output-port");
229: if (path != null) {
230: out.write(' ');
231: out.write(path.toString());
232: }
233: out.write('>');
234: }
235:
236: public void startElement(Object type) {
237: if (objectFormat != null)
238: objectFormat.startElement(type, this );
239: else {
240: print('(');
241: print(type);
242: }
243: }
244:
245: public void endElement() {
246: if (objectFormat != null)
247: objectFormat.endElement(this );
248: else
249: print(')');
250: }
251:
252: /** Write a attribute for the current element.
253: * This is only allowed immediately after a startElement. */
254: public void startAttribute(Object attrType) {
255: if (objectFormat != null)
256: objectFormat.startAttribute(attrType, this );
257: else {
258: print(' ');
259: print(attrType);
260: print(": ");
261: }
262: }
263:
264: /** No more attributes in this element. */
265: public void endAttribute() {
266: if (objectFormat != null)
267: objectFormat.endAttribute(this );
268: else
269: print(' ');
270: }
271:
272: /** Note the end of a "word". See {@link #writeWordStart}. */
273: public void writeWordEnd() {
274: bout.writeWordEnd();
275: }
276:
277: /** Maybe write a word-separating space.
278: * Specifically, write a space if the previous output
279: * was {@link #writeWordEnd}. Otherwise, do nothing.
280: */
281: public void writeWordStart() {
282: bout.writeWordStart();
283: }
284:
285: public void freshLine() {
286: int col = bout.getColumnNumber();
287: if (col != 0)
288: println();
289: }
290:
291: public int getColumnNumber() {
292: return bout.getColumnNumber();
293: }
294:
295: public void setColumnNumber(int column) {
296: bout.setColumnNumber(column);
297: }
298:
299: public void clearBuffer() {
300: bout.clearBuffer();
301: }
302:
303: public void close() {
304: try {
305: if (base instanceof OutPort
306: && ((OutPort) base).bout == bout)
307: base.close();
308: else
309: out.close();
310: } catch (IOException ex) {
311: setError();
312: }
313: WriterManager.instance.unregister(unregisterRef);
314: }
315:
316: /** True if the port should be automatically closed on exit.
317: * (If so, it will be registered by WriterManager. */
318: protected boolean closeOnExit() {
319: return true;
320: }
321:
322: public static void runCleanups() {
323: WriterManager.instance.run();
324: }
325:
326: public void startLogicalBlock(String prefix, boolean perLine,
327: String suffix) {
328: bout.startLogicalBlock(prefix, perLine, suffix);
329: }
330:
331: public void startLogicalBlock(String prefix, String suffix,
332: int indent) {
333: bout.startLogicalBlock(prefix, false, suffix);
334: bout.addIndentation(prefix == null ? indent : indent
335: - prefix.length(), false);
336: }
337:
338: public void endLogicalBlock(String suffix) {
339: bout.endLogicalBlock(suffix);
340: }
341:
342: public void writeBreak(int kind) {
343: bout.writeBreak(kind);
344: }
345:
346: public void writeSpaceLinear() {
347: write(' ');
348: writeBreak(PrettyWriter.NEWLINE_LINEAR);
349: }
350:
351: /** Write a new-line iff the containing section cannot be printed
352: * on one line. Either all linear-style newlines in a logical
353: * block becomes spaces (if it all fits in a line), or none
354: * of them do. */
355: public void writeBreakLinear() {
356: writeBreak(PrettyWriter.NEWLINE_LINEAR);
357: }
358:
359: /** Write a new-line if needed, space otherwise. */
360: public void writeSpaceFill() {
361: write(' ');
362: writeBreak(PrettyWriter.NEWLINE_FILL);
363: }
364:
365: public void writeBreakFill() {
366: writeBreak(PrettyWriter.NEWLINE_FILL);
367: }
368:
369: public void setIndentation(int amount, boolean current) {
370: bout.addIndentation(amount, current);
371: }
372: }
|