001: /*
002: * <copyright>
003: *
004: * Copyright 2000-2004 BBNT Solutions, LLC
005: * under sponsorship of the Defense Advanced Research Projects
006: * Agency (DARPA).
007: *
008: * You can redistribute this software and/or modify it under the
009: * terms of the Cougaar Open Source License as published on the
010: * Cougaar Open Source Website (www.cougaar.org).
011: *
012: * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
013: * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
014: * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
015: * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
016: * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
017: * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
018: * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
019: * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
020: * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
021: * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
022: * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
023: *
024: * </copyright>
025: */
026:
027: package org.cougaar.tools.csmart.ui.console;
028:
029: import org.cougaar.tools.csmart.ui.viewer.CSMART;
030: import org.cougaar.util.log.Logger;
031:
032: import javax.swing.event.DocumentListener;
033: import javax.swing.event.UndoableEditListener;
034: import javax.swing.text.AttributeSet;
035: import javax.swing.text.BadLocationException;
036: import javax.swing.text.DefaultStyledDocument;
037: import java.io.BufferedWriter;
038: import java.io.FileWriter;
039:
040: /**
041: * This is the document that contains the content of the Node output.
042: * By extending <code>DefaultStyledDocument</code>, we get access to
043: * search and highlight support. Note however that this is relatively
044: * heavyweight. It includes support for undo listeners, all sorts of
045: * SGML type strutures, etc. Also note that it uses a <code>GapContent</code>
046: * for underlying storage - which automatically grows at twice the required
047: * speed, and never shrinks. So this extension goes to some pains to
048: * remove text from the document before adding additional content,
049: * to avoid growing the document uncontrollably.
050: */
051: public class ConsoleStyledDocument extends DefaultStyledDocument {
052: // DefaultStyledDocument buffer size is 4096
053: int bufferSize;
054: int minRemoveSize; // remove characters in this increment size
055:
056: private transient Logger log;
057:
058: public ConsoleStyledDocument() {
059: bufferSize = DefaultStyledDocument.BUFFER_SIZE_DEFAULT * 4;
060: minRemoveSize = (int) (bufferSize * .2);
061: createLogger();
062: // We dont need undo support
063: UndoableEditListener[] uelists = getUndoableEditListeners();
064: for (int i = 0; i < uelists.length; i++)
065: removeUndoableEditListener(uelists[i]);
066: }
067:
068: private void createLogger() {
069: log = CSMART.createLogger(this .getClass().getName());
070: }
071:
072: /**
073: * Append a string to the display buffer.
074: * If we are limiting the buffer size, trim the buffer as necessary
075: * to keep under the limit, possibly including some of the addition
076: * being added here. This is in part necessary because the underlying
077: * storage, a <code>GapContent</code>, never shrinks in size --
078: * and when it increases in size, it does so by double the necessary
079: * amount (to maintain a gap).<br>
080: * Note that this means that notifications / etc may miss things
081: * if we were unable to add the entire new String.
082: * @param s string to append to the styled document
083: * @param a attribute set to use in the styled document
084: */
085: public void appendString(String s, AttributeSet a) {
086: if (s == null || s.length() == 0)
087: return;
088: try {
089: // If the buffer size is not -1, we must trim it
090: if (bufferSize > 0) {
091: int slen = s.length();
092: int blen = getLength();
093: int nremove = blen + slen - bufferSize; // amt to remove from doc
094: int nskip = 0; // amount in new string to skip
095: if (nremove > blen) {
096: nskip = nremove - blen;
097: nremove = blen;
098: } else if (nremove > 0) {
099: // remove at least the min chunk
100: nremove = Math.max(nremove, minRemoveSize);
101: } else {
102: nremove = 0;
103: }
104: // OK, remove from the document
105: if (nremove > 0) {
106: remove(0, nremove);
107: }
108: // and trim from the input string so it will fit
109: if (nskip > 0) {
110: s = s.substring(nskip); // And keep only what fits
111: }
112: }
113: // Now insert the new amount into the buffer
114: super .insertString(getLength(), s, a);
115: } catch (BadLocationException ble) {
116: if (log.isErrorEnabled()) {
117: log.error("appendString: Bad location exception: "
118: + ble + " " + ble.offsetRequested(), ble);
119: }
120: }
121: }
122:
123: /**
124: * Set the number of characters displayed. A value of -1 means
125: * display all characters (no limit). Values of 0 and other negative
126: * numbers are ignored.
127: */
128: public void setBufferSize(int bufferSize) {
129: if (bufferSize == -1)
130: this .bufferSize = bufferSize;
131: else if (bufferSize >= 1) {
132: this .bufferSize = bufferSize;
133: this .minRemoveSize = Math.min((int) (bufferSize * .2), 1);
134: }
135: }
136:
137: /**
138: * Get the number of characters displayed. A value of -1 means
139: * display all characters (no limit).
140: */
141: public int getBufferSize() {
142: return bufferSize;
143: }
144:
145: /**
146: * When completely done with this document, get rid of all listeners,
147: * and set the internal buffer variable to null
148: **/
149: public void cleanUp() {
150: // if (log.isDebugEnabled())
151: // log.debug("ConsoleDoc.cleanUp about to remove listeners");
152: // remove listeners
153: DocumentListener[] lists = getDocumentListeners();
154: for (int i = 0; i < lists.length; i++)
155: removeDocumentListener(lists[i]);
156: UndoableEditListener[] uelists = getUndoableEditListeners();
157: for (int i = 0; i < uelists.length; i++)
158: removeUndoableEditListener(uelists[i]);
159:
160: // clear buffer (underlying storage)
161: buffer = null;
162: }
163:
164: public static void main(String[] args) {
165: ConsoleStyledDocument doc = new ConsoleStyledDocument();
166: AttributeSet a = new javax.swing.text.SimpleAttributeSet();
167: Logger log = CSMART
168: .createLogger("org.cougaar.tools.csmart.ui.console.ConsoleStyledDocument");
169: // with MAX_CHARACTER = 5 this prints:
170: // abc, abcde, fghij, vwxyz
171: doc.setBufferSize(5);
172: try {
173: BufferedWriter logFile = new BufferedWriter(new FileWriter(
174: "tmp"));
175: logFile.write("abc");
176: doc.appendString("abc", a);
177: if (log.isDebugEnabled()) {
178: log.debug(doc.getText(0, doc.getLength()));
179: }
180: logFile.write("de");
181: doc.appendString("de", a);
182: if (log.isDebugEnabled()) {
183: log.debug(doc.getText(0, doc.getLength()));
184: }
185: logFile.write("fghij");
186: doc.appendString("fghij", a);
187: if (log.isDebugEnabled()) {
188: log.debug(doc.getText(0, doc.getLength()));
189: }
190: logFile.write("klmnopqrstuvwxyz");
191: doc.appendString("klmnopqrstuvwxyz", a);
192: if (log.isDebugEnabled()) {
193: log.debug(doc.getText(0, doc.getLength()));
194: }
195: logFile.close();
196: logFile = new BufferedWriter(new FileWriter("tmp", true));
197: logFile.write("12345");
198: doc.appendString("12345", a);
199: if (log.isDebugEnabled()) {
200: log.debug("Final document");
201: log.debug(doc.getText(0, doc.getLength()));
202: }
203: logFile.close();
204: } catch (Exception e) {
205: if (log.isErrorEnabled()) {
206: log.error("Exception", e);
207: }
208: }
209: }
210:
211: } // ConsoleStyledDocument
|