Clover coverage report - DrJava Test Coverage (drjava-20120422-r5456)
Coverage timestamp: Sun Apr 22 2012 03:13:25 CDT
file stats: LOC: 377   Methods: 39
NCLOC: 181   Classes: 2
 
 Source file Conditionals Statements Methods TOTAL
ConsoleDocument.java 50% 67% 71.8% 65.2%
coverage coverage
 1    /*BEGIN_COPYRIGHT_BLOCK
 2    *
 3    * Copyright (c) 2001-2010, JavaPLT group at Rice University (drjava@rice.edu)
 4    * All rights reserved.
 5    *
 6    * Redistribution and use in source and binary forms, with or without
 7    * modification, are permitted provided that the following conditions are met:
 8    * * Redistributions of source code must retain the above copyright
 9    * notice, this list of conditions and the following disclaimer.
 10    * * Redistributions in binary form must reproduce the above copyright
 11    * notice, this list of conditions and the following disclaimer in the
 12    * documentation and/or other materials provided with the distribution.
 13    * * Neither the names of DrJava, the JavaPLT group, Rice University, nor the
 14    * names of its contributors may be used to endorse or promote products
 15    * derived from this software without specific prior written permission.
 16    *
 17    * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
 18    * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
 19    * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
 20    * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
 21    * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
 22    * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
 23    * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
 24    * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
 25    * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
 26    * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
 27    * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 28    *
 29    * This software is Open Source Initiative approved Open Source Software.
 30    * Open Source Initative Approved is a trademark of the Open Source Initiative.
 31    *
 32    * This file is part of DrJava. Download the current version of this project
 33    * from http://www.drjava.org/ or http://sourceforge.net/projects/drjava/
 34    *
 35    * END_COPYRIGHT_BLOCK*/
 36   
 37    package edu.rice.cs.util.text;
 38   
 39    import java.io.*;
 40    import java.awt.EventQueue;
 41    import java.awt.print.*;
 42    import java.awt.EventQueue;
 43   
 44    import edu.rice.cs.drjava.model.print.DrJavaBook;
 45   
 46    import edu.rice.cs.drjava.model.FileSaveSelector;
 47    import edu.rice.cs.util.UnexpectedException;
 48    import edu.rice.cs.util.OperationCanceledException;
 49    import edu.rice.cs.util.swing.Utilities;
 50    import edu.rice.cs.util.text.ConsoleDocumentInterface;
 51    import edu.rice.cs.util.text.DocumentEditCondition;
 52    import edu.rice.cs.util.text.EditDocumentException;
 53    import edu.rice.cs.util.FileOps;
 54   
 55    /** A GUI-toolkit agnostic interface to a console document. This class assumes that the embedded document supports
 56    * readers/writers locking and uses that locking protocol to ensure the integrity of the data added in this class
 57    * WHY is prompt considered part of a console document rather than an interactions document?
 58    * @version $Id: ConsoleDocument.java 5236 2010-04-27 01:43:36Z mgricken $ */
 59    public class ConsoleDocument implements ConsoleDocumentInterface {
 60   
 61    /** The default prompt to use in the console. */
 62    public static final String DEFAULT_CONSOLE_PROMPT = "";
 63   
 64    /** Default text style. */
 65    public static final String DEFAULT_STYLE = "default";
 66   
 67    /** Style for System.out */
 68    public static final String SYSTEM_OUT_STYLE = "System.out";
 69   
 70    /** Style for System.err */
 71    public static final String SYSTEM_ERR_STYLE = "System.err";
 72   
 73    /** Style for System.in */
 74    public static final String SYSTEM_IN_STYLE = "System.in";
 75   
 76    /** The embedded document storing the text and _hasPrompt property for this console model. */
 77    protected final ConsoleDocumentInterface _document;
 78   
 79    /** A runnable command to use for a notification beep. */
 80    protected volatile Runnable _beep;
 81   
 82    /** Index in the document of the first place that is editable. */
 83    private volatile int _promptPos;
 84   
 85    /** String to use for the prompt. */
 86    protected volatile String _prompt;
 87   
 88    /** The book object used for printing that represents several pages */
 89    protected volatile DrJavaBook _book;
 90   
 91    /** Creates a new ConsoleDocument with the given embedded ConsoleDocumentInterface (a SwingDocument in native DrJava).
 92    * @param doc the embedded ConsoleDocumentInterface object
 93    */
 94  355 public ConsoleDocument(ConsoleDocumentInterface doc) {
 95  355 _document = doc;
 96   
 97  0 _beep = new Runnable() { public void run() { } };
 98  355 _prompt = DEFAULT_CONSOLE_PROMPT;
 99  355 _promptPos = DEFAULT_CONSOLE_PROMPT.length();
 100  355 _document.setHasPrompt(false);
 101  355 _document.setEditCondition(new ConsoleEditCondition()); // Prevent any edits before the prompt!
 102    }
 103   
 104    /** @return true iff this document has a prompt and is ready to accept input. */
 105  4 public boolean hasPrompt() { return _document.hasPrompt(); }
 106   
 107  32 public void setHasPrompt(boolean val) { _document.setHasPrompt(val); }
 108   
 109    /** Accessor for the string used for the prompt. */
 110  28 public String getPrompt() { return _prompt; }
 111   
 112    /** Sets the string to use for the prompt.
 113    * @param prompt String to use for the prompt.
 114    */
 115  1 public void setPrompt(String prompt) { _prompt = prompt; }
 116   
 117    /** Returns the length of the prompt string. */
 118  0 public int getPromptLength() { return _prompt.length(); }
 119   
 120    /** Gets the object which determines whether an insert/remove edit should be applied based on the inputs.
 121    * @return the DocumentEditCondition to determine legality of inputs
 122    */
 123  0 public DocumentEditCondition getEditCondition() { return _document.getEditCondition(); }
 124   
 125    /** Provides an object which can determine whether an insert or remove edit should be applied, based on the inputs.
 126    * @param condition Object to determine legality of inputs
 127    */
 128  2 public void setEditCondition(DocumentEditCondition condition) { _document.setEditCondition(condition); }
 129   
 130    /** Returns the first location in the document where editing is allowed. */
 131  23 public int getPromptPos() { return _promptPos; }
 132   
 133    /** Sets the prompt position. Only used in tests.
 134    * @param newPos the new position.
 135    */
 136  226 public void setPromptPos(int newPos) {
 137  226 _promptPos = newPos;
 138    }
 139   
 140    /** Sets a runnable action to use as a beep.
 141    * @param beep Runnable beep command
 142    */
 143  205 public void setBeep(Runnable beep) { _beep = beep; }
 144   
 145    /** Resets the document to a clean state. Only runs in the event thread. */
 146  6 public void reset(String banner) {
 147  6 assert EventQueue.isDispatchThread();
 148  6 try {
 149  6 forceRemoveText(0, _document.getLength());
 150  6 forceInsertText(0, banner, DEFAULT_STYLE);
 151  6 _promptPos = banner.length();
 152    }
 153  0 catch (EditDocumentException e) { throw new UnexpectedException(e); }
 154    }
 155   
 156    /** Prints a prompt for a new input. */
 157  270 public void insertPrompt() {
 158  270 try {
 159  270 int len = _document.getLength();
 160    // Update _promptPos before updating _document because insertText runs insertUpdate to adjust caret
 161  270 _promptPos = len + _prompt.length();
 162  270 forceInsertText(len, _prompt, DEFAULT_STYLE); // need forceAppend!
 163  270 _document.setHasPrompt(true);
 164    }
 165  0 catch (EditDocumentException e) { throw new UnexpectedException(e); }
 166    }
 167   
 168    /** Disables the prompt in this document. */
 169  0 public void disablePrompt() {
 170  0 _document.setHasPrompt(false);
 171  0 _promptPos = _document.getLength();
 172    }
 173   
 174    /** Inserts a new line at the given position.
 175    * @param pos Position to insert the new line
 176    */
 177  3 public void insertNewline(int pos) {
 178    // Correct the position if necessary
 179  3 try {
 180  3 int len = _document.getLength();
 181  0 if (pos > len) pos = len;
 182  0 else if (pos < 0) pos = 0;
 183   
 184  3 String newLine = "\n"; // Was StringOps.EOL; but Swing uses '\n' for newLine
 185  3 insertText(pos, newLine, DEFAULT_STYLE);
 186    }
 187  0 catch (EditDocumentException e) { throw new UnexpectedException(e); }
 188    }
 189   
 190    /** Gets the position immediately before the prompt, or the doc length if there is no prompt. Only runs in the event
 191    * thread. */
 192  51 private int _getPositionBeforePrompt() {
 193  51 int len = _document.getLength();
 194  51 if (_document.hasPrompt()) {
 195  29 int promptStart = _promptPos - _prompt.length();
 196  29 return (promptStart < len && promptStart >= 0) ? promptStart : len; // ensure position is within document
 197    }
 198  22 return len;
 199    }
 200   
 201    /** Inserts the given string with the given attributes just before the most recent prompt.
 202    * @param text String to insert
 203    * @param style name of style to format the string
 204    */
 205  51 public void insertBeforeLastPrompt(String text, String style) {
 206  51 /* */ assert Utilities.TEST_MODE || EventQueue.isDispatchThread();
 207  51 try {
 208  51 int pos = _getPositionBeforePrompt();
 209    // System.err.println("_promptPos before update = " + _promptPos);
 210  51 _promptPos = _promptPos + text.length();
 211  51 forceInsertText(pos, text, style);
 212    }
 213  0 catch (EditDocumentException ble) { throw new UnexpectedException(ble); }
 214    }
 215   
 216    /** Inserts a string into the document at the given offset and named style, if the edit condition allows it.
 217    * @param offs Offset into the document
 218    * @param str String to be inserted
 219    * @param style Name of the style to use. Must have been added using addStyle.
 220    * @throws EditDocumentException if the offset is illegal
 221    */
 222  250 public void insertText(int offs, String str, String style) throws EditDocumentException {
 223  2 if (offs < _promptPos) _beep.run();
 224    else {
 225  248 _addToStyleLists(offs, str, style);
 226  248 _document.insertText(offs, str, style);
 227    }
 228    }
 229   
 230    /** Appends a string to this in the given named style, if the edit condition allows it.
 231    * @param str String to be inserted
 232    * @param style Name of the style to use. Must have been added using addStyle.
 233    * @throws EditDocumentException if the offset is illegal
 234    */
 235  127 public void append(String str, String style) throws EditDocumentException {
 236  127 /* */ assert Utilities.TEST_MODE || EventQueue.isDispatchThread();
 237  127 int offs = _document.getLength();
 238  127 _addToStyleLists(offs, str, style);
 239  127 _document.insertText(offs, str, style);
 240    }
 241   
 242    /** Inserts a string into the document at the given offset and style, regardless of the edit condition.
 243    * @param offs Offset into the document
 244    * @param str String to be inserted
 245    * @param style Name of the style to use. Must have been added using addStyle.
 246    * @throws EditDocumentException if the offset is illegal
 247    */
 248  328 public void forceInsertText(int offs, String str, String style) throws EditDocumentException {
 249  328 _addToStyleLists(offs, str, style);
 250    // System.err.println("Inserting text '" + str + "' at position " + offs);
 251  328 _document.forceInsertText(offs, str, style);
 252    }
 253   
 254    /** Adds style specifier to _stylelists. Only runs in event thread. */
 255  703 private void _addToStyleLists(int offs, String str, String style) {
 256  703 if (_document instanceof SwingDocument)
 257  703 ((SwingDocument)_document).addColoring(offs, offs + str.length(), style);
 258    }
 259   
 260    /** Removes a portion of the document, if the edit condition (including promptPos) allows it.
 261    * @param offs Offset to start deleting from
 262    * @param len Number of characters to remove
 263    * @throws EditDocumentException if the offset or length are illegal
 264    */
 265  51 public void removeText(int offs, int len) throws EditDocumentException {
 266  0 if (offs < _promptPos) _beep.run();
 267  51 else _document.removeText(offs, len);
 268    }
 269   
 270    /** Removes a portion of the document, regardless of the edit condition.
 271    * @param offs Offset to start deleting from
 272    * @param len Number of characters to remove
 273    * @throws EditDocumentException if the offset or length are illegal
 274    */
 275  7 public void forceRemoveText(int offs, int len) throws EditDocumentException {
 276  7 _document.forceRemoveText(offs, len);
 277    }
 278   
 279    /** Returns the length of the document. */
 280  327 public int getLength() { return _document.getLength(); }
 281   
 282    /** Returns a portion of the document.
 283    * @param offs First offset of the desired text
 284    * @param len Number of characters to return
 285    * @throws EditDocumentException if the offset or length are illegal
 286    */
 287  124 public String getDocText(int offs, int len) throws EditDocumentException {
 288  124 return _document.getDocText(offs, len);
 289    }
 290   
 291    /** Returns the entire text of the document. Identical to getText() in AbstractDocumentInterface.
 292    * @throws EditDocumentException if the offset or length are illegal
 293    */
 294  25 public String getText() { return _document.getDocText(0, getLength()); }
 295   
 296    /** Returns the string that the user has entered at the current prompt. May contain newline characters. */
 297  60 public String getCurrentInput() {
 298  60 try { return getDocText(_promptPos, _document.getLength() - _promptPos); }
 299  0 catch (EditDocumentException e) { throw new UnexpectedException(e); }
 300    }
 301   
 302    /** Clears the current input text. */
 303  13 public void clearCurrentInput() { _clearCurrentInputText(); }
 304   
 305    /** Removes the text from the current prompt to the end of the document. */
 306  15 protected void _clearCurrentInputText() {
 307  15 try {
 308    // Delete old value of current line
 309  15 removeText(_promptPos, _document.getLength() - _promptPos);
 310    }
 311  0 catch (EditDocumentException ble) { throw new UnexpectedException(ble); }
 312    }
 313   
 314    /* Returns the default style for a "console" document. */
 315  0 public String getDefaultStyle() { return ConsoleDocument.DEFAULT_STYLE; }
 316   
 317    /** Returns the Pageable object for printing.
 318    * @return A Pageable representing this document.
 319    */
 320  0 public Pageable getPageable() throws IllegalStateException { return _book; }
 321   
 322    /** This method tells the document to prepare all the DrJavaBook and PagePrinter objects. */
 323  0 public void preparePrintJob() {
 324  0 _book = new DrJavaBook(getDocText(0, getLength()), "Console", new PageFormat());
 325    }
 326   
 327    /** Prints the given document by bringing up a "Print" window. */
 328  0 public void print() throws PrinterException {
 329  0 preparePrintJob();
 330  0 PrinterJob printJob = PrinterJob.getPrinterJob();
 331  0 printJob.setPageable(_book);
 332  0 if (printJob.printDialog()) printJob.print();
 333  0 cleanUpPrintJob();
 334    }
 335   
 336    /** Clears the pageable object used to hold the print job. */
 337  0 public void cleanUpPrintJob() { _book = null; }
 338   
 339    /** Class ensuring that attempts to edit document lines above the prompt are rejected. */
 340    class ConsoleEditCondition extends DocumentEditCondition {
 341  377 public boolean canInsertText(int offs) { return canRemoveText(offs); }
 342   
 343  425 public boolean canRemoveText(int offs) {
 344  425 if (offs < _promptPos) {
 345  1 _beep.run();
 346  1 return false;
 347    }
 348  424 return true;
 349    }
 350    }
 351   
 352    /** Saves the contents of the document to a file.
 353    * @param selector File to save to
 354    */
 355  0 public void saveCopy(FileSaveSelector selector) throws IOException {
 356  0 assert EventQueue.isDispatchThread();
 357  0 try {
 358  0 final File file = selector.getFile().getCanonicalFile();
 359  0 if (! file.exists() || selector.verifyOverwrite(file)) { // confirm that existing file can be overwritten
 360  0 FileOps.saveFile(new FileOps.DefaultFileSaver(file) {
 361    /** Only runs in event thread so no read lock is necessary. */
 362  0 public void saveTo(OutputStream os) throws IOException {
 363  0 final String text = getDocText(0, getLength());
 364  0 OutputStreamWriter osw = new OutputStreamWriter(os);
 365  0 osw.write(text,0,text.length());
 366  0 osw.flush();
 367    }
 368    });
 369    }
 370    }
 371    catch (OperationCanceledException oce) {
 372    // Thrown by selector.getFile() if the user cancels.
 373    // We don't do anything if this happens.
 374  0 return;
 375    }
 376    }
 377    }