001: package gnu.mapping;
002:
003: import java.io.*;
004: import java.text.*;
005: import gnu.text.*;
006: import gnu.lists.*;
007:
008: /**
009: * An extended PrintWriter.
010: */
011:
012: public class OutPort extends java.io.PrintWriter implements Printable,
013: Consumer {
014: String name;
015: private Writer base;
016:
017: // To keep track of column-numbers, we use a helper class.
018: // Otherwise, it is too painful, as there is no documented
019: // interface that would allow PrintWriter to be cleanly extended ...
020: // The helper class also lets us make transparent use of WriterManager.
021: PrettyWriter bout;
022:
023: /** An index into the WriterManager's internal table. */
024: protected int index;
025:
026: OutPort(Writer base, PrettyWriter out, boolean autoflush) {
027: super (out, autoflush);
028: this .bout = out;
029: this .base = base;
030: index = WriterManager.instance.register(out);
031: }
032:
033: public OutPort(Writer base, boolean printPretty, boolean autoflush) {
034: this (base, new PrettyWriter(base, printPretty), autoflush);
035: }
036:
037: public OutPort(Writer base, boolean printPretty, boolean autoflush,
038: String name) {
039: this (base, new PrettyWriter(base, printPretty), autoflush);
040: this .name = name;
041: }
042:
043: public OutPort(OutputStream out) {
044: this (out, null);
045: }
046:
047: public OutPort(OutputStream out, String name) {
048: this (new OutputStreamWriter(out), true, name);
049: }
050:
051: public OutPort(Writer out) {
052: this (out, false, false);
053: }
054:
055: public OutPort(Writer base, String name) {
056: this (base, false, false);
057: this .name = name;
058: }
059:
060: public OutPort(Writer base, boolean autoflush, String name) {
061: this (base, false, autoflush);
062: this .name = name;
063: }
064:
065: public boolean printReadable;
066:
067: // For now, these are static. They should probably be thread-local.
068: private static OutPort outInitial = new OutPort(new LogWriter(
069: new BufferedWriter(new OutputStreamWriter(System.out))),
070: true, true, "<stdout>");
071: private static OutPort out = outInitial;
072:
073: private static OutPort errInitial = new OutPort(new LogWriter(
074: new OutputStreamWriter(System.err)), true, true, "<stderr>");
075: private static OutPort err = errInitial;
076:
077: static public OutPort outDefault() {
078: Thread thread = Thread.currentThread();
079: if (thread instanceof Future)
080: return ((Future) thread).out;
081: return out;
082: }
083:
084: static public void setOutDefault(OutPort o) {
085: Thread thread = Thread.currentThread();
086: if (thread instanceof Future)
087: ((Future) thread).out = o;
088: else
089: out = o;
090: }
091:
092: static public OutPort errDefault() {
093: Thread thread = Thread.currentThread();
094: if (thread instanceof Future)
095: return ((Future) thread).err;
096: return err;
097: }
098:
099: static public void setErrDefault(OutPort e) {
100: Thread thread = Thread.currentThread();
101: if (thread instanceof Future)
102: ((Future) thread).err = e;
103: else
104: err = e;
105: }
106:
107: public void echo(char[] buf, int off, int len)
108: throws java.io.IOException {
109: if (base instanceof LogWriter)
110: ((LogWriter) base).echo(buf, off, len);
111: }
112:
113: static Writer logFile;
114:
115: public static void closeLogFile() throws java.io.IOException {
116: if (logFile != null) {
117: logFile.close();
118: logFile = null;
119: }
120: if (outInitial.base instanceof LogWriter)
121: ((LogWriter) outInitial.base).setLogFile((Writer) null);
122: if (errInitial.base instanceof LogWriter)
123: ((LogWriter) errInitial.base).setLogFile((Writer) null);
124: }
125:
126: public static void setLogFile(String name)
127: throws java.io.IOException {
128: if (logFile != null)
129: closeLogFile();
130: logFile = new PrintWriter(new BufferedWriter(new FileWriter(
131: name)));
132: if (outInitial.base instanceof LogWriter)
133: ((LogWriter) outInitial.base).setLogFile(logFile);
134: if (errInitial.base instanceof LogWriter)
135: ((LogWriter) errInitial.base).setLogFile(logFile);
136: }
137:
138: /*
139: public void closeLogFile () throws java.io.IOException
140: {
141: if (base instanceof LogWriter)
142: ((LogWriter)base).closeLogFile();
143: }
144:
145: public void setLogFile (String name) throws java.io.IOException
146: {
147: if (base instanceof LogWriter)
148: ((LogWriter)base).setLogFile(name);
149: }
150: */
151:
152: protected static final int WORD = -2;
153: protected int prev = '\n';
154:
155: protected static final boolean isWordChar(char ch) {
156: return Character.isJavaIdentifierPart(ch) || ch == '-'
157: || ch == '+';
158: }
159:
160: private void startWord() {
161: /*
162: if (prev == WORD || isWordChar((char) prev))
163: {
164: super.write(' ');
165: }
166: */
167: prev = WORD;
168: }
169:
170: public void write(int c) {
171: // if (prev == WORD && isWordChar((char) c)) out.print(' ');
172: super .write(c);
173: prev = c;
174: }
175:
176: public void write(char[] buffer, int start, int count) {
177: if (count > 0) {
178: // if (prev == WORD && isWordChar(buffer[start])) out.print(' ');
179: super .write(buffer, start, count);
180: prev = buffer[start + count - 1];
181: }
182: }
183:
184: public void write(String v) {
185: int len = v.length();
186: if (len == 0)
187: return;
188: //if (prev == WORD && isWordChar(v.charAt(0))) out.write(' ');
189: prev = v.charAt(len - 1);
190: super .write(v);
191: }
192:
193: /**
194: * Write a character value to a byte-stream.
195: * The default transation generates UTF-8 multi-bytes.
196: * We support character values above 0xFFFF for future extension.
197: */
198: public void writeChar(int i) {
199: write(i);
200: }
201:
202: public void writeSchemeObject(Object obj, boolean readable) {
203: boolean saveReadable = printReadable;
204: try {
205: printReadable = readable;
206: SFormat.print(obj, this );
207: } finally {
208: printReadable = saveReadable;
209: }
210: }
211:
212: // java.text.FieldPosition fieldPosition;
213:
214: /** If non-null, use this to print numbers. */
215: java.text.NumberFormat numberFormat;
216:
217: public FormatToConsumer objectFormat;
218:
219: public void print(char v) {
220: /*
221: if (prev == WORD && isWordChar((char) v))
222: {
223: out.print(' ');
224: }
225: */
226: super .print(v);
227: prev = v;
228: }
229:
230: public void print(int v) {
231: startWord();
232: if (numberFormat == null)
233: super .print(v);
234: else
235: print(numberFormat.format((long) v));
236: }
237:
238: public void print(long v) {
239: startWord();
240: if (numberFormat == null)
241: super .print(v);
242: else
243: print(numberFormat.format(v));
244: }
245:
246: public void print(double v) {
247: startWord();
248: if (numberFormat == null)
249: super .print(v);
250: else
251: print(numberFormat.format(v));
252: }
253:
254: public void print(float v) {
255: startWord();
256: if (numberFormat == null)
257: super .print(v);
258: else
259: print(numberFormat.format((double) v));
260: }
261:
262: public void print(String v) {
263: write(v == null ? "(null)" : v);
264: }
265:
266: public void print(Object v) {
267: startWord();
268: if (objectFormat != null)
269: objectFormat.writeObject(v, this );
270: else if (v instanceof Consumable)
271: ((Consumable) v).consume(this );
272: else
273: super .print(v == null ? "null" : v);
274: }
275:
276: public void print(java.io.PrintWriter ps) {
277: ps.print("#<output-port");
278: if (name != null) {
279: ps.print(' ');
280: ps.print(name);
281: }
282: ps.print('>');
283: }
284:
285: //public void writeChar(int v);
286:
287: public void writeBoolean(boolean v) {
288: print(v);
289: }
290:
291: public void writeFloat(float v) {
292: print(v);
293: }
294:
295: public void writeDouble(double v) {
296: print(v);
297: }
298:
299: public void writeInt(int v) {
300: print(v);
301: }
302:
303: public void writeLong(long v) {
304: print(v);
305: }
306:
307: public void beginGroup(String typeName, Object type) {
308: if (objectFormat != null)
309: objectFormat.beginGroup(typeName, type, this );
310: else {
311: print('(');
312: print(typeName);
313: }
314: }
315:
316: public void endGroup(String typeName) {
317: if (objectFormat != null)
318: objectFormat.endGroup(typeName, this );
319: else
320: out.print(')');
321: prev = ')';
322: }
323:
324: /** Write a attribute for the current group.
325: * This is only allowed immediately after a beginGroup. */
326: public void beginAttribute(String attrName, Object attrType) {
327: print(' ');
328: print(attrName);
329: print(": ");
330: prev = WORD;
331: }
332:
333: /** No more attributes in this group. */
334: public void endAttribute() {
335: prev = WORD;
336: print(' '); // FIXME
337: }
338:
339: public void writeObject(Object v) {
340: print(v);
341: }
342:
343: /** True if consumer is ignoring rest of group.
344: * The producer can use this information to skip ahead. */
345: public boolean ignoring() {
346: return false;
347: }
348:
349: public void writeChars(String str) {
350: print(str);
351: }
352:
353: public void freshLine() {
354: int col = bout.getColumnNumber();
355: if (col != 0)
356: println();
357: }
358:
359: public int getColumnNumber() {
360: return bout.getColumnNumber();
361: }
362:
363: public void setColumnNumber(int column) {
364: bout.setColumnNumber(column);
365: }
366:
367: public void clearBuffer() {
368: bout.clearBuffer();
369: }
370:
371: public void close() {
372: super .close();
373: WriterManager.instance.unregister(index);
374: }
375:
376: public static void runCleanups() {
377: WriterManager.instance.run();
378: }
379:
380: public void startLogicalBlock(String prefix, boolean perLine,
381: String suffix) {
382: bout.startLogicalBlock(prefix, perLine, suffix);
383: }
384:
385: public void startLogicalBlock(String prefix, String suffix,
386: int indent) {
387: bout.startLogicalBlock(prefix, false, suffix);
388: bout.addIndentation(prefix == null ? indent : indent
389: - prefix.length(), false);
390: }
391:
392: public void endLogicalBlock(String suffix) {
393: bout.endLogicalBlock(suffix);
394: }
395:
396: public void writeBreak(int kind) {
397: bout.writeBreak(kind);
398: }
399:
400: public void writeSpaceLinear() {
401: write(' ');
402: writeBreak(PrettyWriter.NEWLINE_LINEAR);
403: }
404:
405: public void writeBreakLinear() {
406: writeBreak(PrettyWriter.NEWLINE_LINEAR);
407: }
408:
409: public void writeSpaceFill() {
410: write(' ');
411: writeBreak(PrettyWriter.NEWLINE_FILL);
412: }
413:
414: public void writeBreakFill() {
415: writeBreak(PrettyWriter.NEWLINE_FILL);
416: }
417:
418: public void setIndentation(int amount, boolean current) {
419: bout.addIndentation(amount, current);
420: }
421: }
|