KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > edu > rice > cs > drjava > model > repl > History


1 /*BEGIN_COPYRIGHT_BLOCK
2  *
3  * This file is part of DrJava. Download the current version of this project from http://www.drjava.org/
4  * or http://sourceforge.net/projects/drjava/
5  *
6  * DrJava Open Source License
7  *
8  * Copyright (C) 2001-2005 JavaPLT group at Rice University (javaplt@rice.edu). All rights reserved.
9  *
10  * Developed by: Java Programming Languages Team, Rice University, http://www.cs.rice.edu/~javaplt/
11  *
12  * Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated
13  * documentation files (the "Software"), to deal with the Software without restriction, including without limitation
14  * the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and
15  * to permit persons to whom the Software is furnished to do so, subject to the following conditions:
16  *
17  * - Redistributions of source code must retain the above copyright notice, this list of conditions and the
18  * following disclaimers.
19  * - Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the
20  * following disclaimers in the documentation and/or other materials provided with the distribution.
21  * - Neither the names of DrJava, the JavaPLT, Rice University, nor the names of its contributors may be used to
22  * endorse or promote products derived from this Software without specific prior written permission.
23  * - Products derived from this software may not be called "DrJava" nor use the term "DrJava" as part of their
24  * names without prior written permission from the JavaPLT group. For permission, write to javaplt@rice.edu.
25  *
26  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO
27  * THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
28  * CONTRIBUTORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF
29  * CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
30  * WITH THE SOFTWARE.
31  *
32 END_COPYRIGHT_BLOCK*/

33
34 package edu.rice.cs.drjava.model.repl;
35
36 import java.util.Vector JavaDoc;
37 import java.util.HashMap JavaDoc;
38 import edu.rice.cs.util.FileOps;
39 import edu.rice.cs.drjava.config.*;
40 import edu.rice.cs.drjava.DrJava;
41 import edu.rice.cs.drjava.model.*;
42 import edu.rice.cs.util.OperationCanceledException;
43
44 import java.io.Serializable JavaDoc;
45 import java.io.IOException JavaDoc;
46 import java.io.File JavaDoc;
47 import java.io.OutputStreamWriter JavaDoc;
48 import java.io.OutputStream JavaDoc;
49 import java.io.BufferedWriter JavaDoc;
50
51 /** History class that records what has been typed in the interactions pane. This class is not thread safe;
52  * it is only accessed from InteractionsDocument which takes responsibility for synchronization.
53  * @version $Id: History.java 4029 2006-11-09 08:09:43Z rcartwright $
54  */

55 public class History implements OptionConstants, Serializable JavaDoc {
56
57   public static final String JavaDoc INTERACTION_SEPARATOR = "//End of Interaction//";
58
59   // Not final because it may be updated by config
60
private int _maxSize;
61
62   /** Version flag at the beginning of saved history file format
63    * If this is not present in a saved history, it is assumed to be the original format.
64    */

65   public static final String JavaDoc HISTORY_FORMAT_VERSION_2 =
66     "// DrJava saved history v2" + System.getProperty("line.separator");
67
68   private Vector JavaDoc<String JavaDoc> _vector = new Vector JavaDoc<String JavaDoc>();
69   private int _cursor = -1;
70
71   /** A hashmap for edited entries in the history. */
72   private HashMap JavaDoc<Integer JavaDoc, String JavaDoc> _editedEntries = new HashMap JavaDoc<Integer JavaDoc, String JavaDoc>();
73
74   /** A placeholder for the current search string. */
75   private String JavaDoc _currentSearchString = "";
76
77   /** Constructor, so we can add a listener to the Config item being used. */
78   public History() {
79     this(DrJava.getConfig().getSetting(HISTORY_MAX_SIZE).intValue());
80     DrJava.getConfig().addOptionListener(HISTORY_MAX_SIZE, historyOptionListener);
81   }
82
83   /** Creates a new History with the given size. An option listener is not added for the config framework.
84    * @param maxSize Number of lines to remember in the history.
85    */

86   public History(int maxSize) {
87     _maxSize = maxSize;
88     // Sanity check on _maxSize
89
if (_maxSize < 0) _maxSize = 0;
90   }
91
92   /** Adds an item to the history and moves the cursor to point to the place after it.
93    * Note: Items are not inserted if they are empty. (This is in accordance with
94    * bug #522123, but in divergence from feature #522213 which originally excluded
95    * sequential duplicate entries from ever being stored.)
96    *
97    * Thus, to access the newly inserted item, you must movePrevious first.
98    */

99   public void add(String JavaDoc item) {
100     // for consistency in saved History files, WILL save sequential duplicate entries
101
if (item.trim().length() > 0) {
102       _vector.add(item);
103       // If adding the new element has filled _vector to beyond max
104
// capacity, spill the oldest element out of the History.
105
if (_vector.size() > _maxSize) {
106         _vector.remove(0);
107       }
108       moveEnd();
109       _editedEntries.clear();
110     }
111   }
112
113   /** Move the cursor to just past the end. Thus, to access the last element, you must movePrevious. */
114   public void moveEnd() { _cursor = _vector.size(); }
115
116   /** Moves cursor back 1, or throws exception if there is none.
117    * @param entry the current entry (perhaps edited from what is in history)
118    */

119   public void movePrevious(String JavaDoc entry) {
120     if (! hasPrevious()) throw new ArrayIndexOutOfBoundsException JavaDoc();
121     setEditedEntry(entry);
122     _cursor--;
123   }
124   
125   /** Returns the last entry from the history. Throw array indexing exception if no such entry. */
126   public String JavaDoc lastEntry() { return _vector.get(_cursor - 1); }
127
128   /** Moves cursor forward 1, or throws exception if there is none.
129    * @param entry the current entry (perhaps edited from what is in history)
130    */

131   public void moveNext(String JavaDoc entry) {
132     if (! hasNext()) throw new ArrayIndexOutOfBoundsException JavaDoc();
133     setEditedEntry(entry);
134     _cursor++;
135   }
136
137   /** Returns whether moveNext() would succeed right now. */
138   public boolean hasNext() { return _cursor < (_vector.size()); }
139
140   /** Returns whether movePrevious() would succeed right now. */
141   public boolean hasPrevious() { return _cursor > 0; }
142
143   /** Returns item in history at current position; returns "" if no current item exists. */
144   public String JavaDoc getCurrent() {
145     Integer JavaDoc cursor = new Integer JavaDoc(_cursor);
146     if (_editedEntries.containsKey(cursor)) return _editedEntries.get(cursor);
147
148     if (hasNext()) return _vector.get(_cursor);
149     return "";
150   }
151
152   /** Returns the number of items in this History. */
153   public int size() { return _vector.size(); }
154
155   /** Clears the vector */
156   public void clear() { _vector.clear(); }
157
158   /** Returns the history as a string by concatenating each string in the vector separated by the delimiting
159    * character. A semicolon is added to the end of every statement that didn't already end with one.
160    */

161   public String JavaDoc getHistoryAsStringWithSemicolons() {
162     final StringBuilder JavaDoc s = new StringBuilder JavaDoc();
163     final String JavaDoc delimiter = INTERACTION_SEPARATOR + System.getProperty("line.separator");
164     for (int i = 0; i < _vector.size(); i++) {
165       String JavaDoc nextLine = _vector.get(i);
166 // int nextLength = nextLine.length();
167
// if ((nextLength > 0) && (nextLine.charAt(nextLength-1) != ';')) {
168
// nextLine += ";";
169
// }
170
// s += nextLine + delimiter;
171
s.append(nextLine);
172       s.append(delimiter);
173     }
174     return s.toString();
175   }
176
177   /** Returns the history as a string by concatenating each string in the vector separated by the delimiting
178    * character.
179    */

180   public String JavaDoc getHistoryAsString() {
181     final StringBuilder JavaDoc sb = new StringBuilder JavaDoc();
182     final String JavaDoc delimiter = System.getProperty("line.separator");
183     for (String JavaDoc s: _vector) sb.append(s).append(delimiter);
184     return sb.toString();
185   }
186
187   /** Writes this (unedited) History to the file selected in the FileSaveSelector.
188    * @param selector File to save to
189    */

190   public void writeToFile(FileSaveSelector selector) throws IOException JavaDoc {
191     writeToFile(selector, getHistoryAsStringWithSemicolons());
192   }
193
194   /** Writes this History to the file selected in the FileSaveSelector. The saved file will still include
195    * any tags or extensions needed to recognize it as a saved interactions file.
196    * @param selector File to save to
197    * @param editedVersion The edited version of the text to be saved.
198    */

199   public static void writeToFile(FileSaveSelector selector, final String JavaDoc editedVersion) throws IOException JavaDoc {
200     File JavaDoc c;
201     
202     try { c = selector.getFile(); }
203     catch (OperationCanceledException oce) { return; }
204     
205     // Make sure we ask before overwriting
206
if (c != null) {
207       if (! c.exists() || selector.verifyOverwrite()) {
208         FileOps.DefaultFileSaver saver = new FileOps.DefaultFileSaver(c) {
209           public void saveTo(OutputStream JavaDoc os) throws IOException JavaDoc {
210
211             OutputStreamWriter JavaDoc osw = new OutputStreamWriter JavaDoc(os);
212             BufferedWriter JavaDoc bw = new BufferedWriter JavaDoc(osw);
213             String JavaDoc file = HISTORY_FORMAT_VERSION_2 + editedVersion;
214 // if (PlatformFactory.ONLY.isWindowsPlatform()) {
215
// StringBuffer buf = new StringBuffer();
216
// String lineSep = System.getProperty("line.separator");
217
// int last = 0;
218
// for (int i = file.indexOf('\n'); i != -1; i = file.indexOf('\n', last)) {
219
// buf.append(file.substring(last, i));
220
// buf.append(lineSep);
221
// last = i+1;
222
// }
223
// file = buf.toString();
224
// }
225
bw.write(file, 0, file.length());
226             bw.close();
227           }
228         };
229         FileOps.saveFile(saver);
230       }
231     }
232   }
233
234   /** Changes the maximum number of interactions remembered by this History.
235    * @param newSize New number of interactions to remember.
236    */

237   public void setMaxSize(int newSize) {
238     // Sanity check
239
if (newSize < 0) newSize = 0;
240
241     // Remove old elements if the new size is less than current size
242
if (size() > newSize) {
243
244       int numToDelete = size() - newSize;
245
246       for (int i = 0; i< numToDelete; i++) { _vector.remove(0); }
247
248       moveEnd();
249     }
250     _maxSize = newSize;
251   }
252   
253   /** The OptionListener for HISTORY_MAX_SIZE */
254   public final OptionListener<Integer JavaDoc> historyOptionListener = new OptionListener<Integer JavaDoc>() {
255     public void optionChanged (OptionEvent<Integer JavaDoc> oce) {
256       int newSize = oce.value.intValue();
257       setMaxSize(newSize);
258     }
259   };
260
261   /* Getter for historyOptionListener. */
262   public OptionListener<Integer JavaDoc> getHistoryOptionListener() { return historyOptionListener; }
263
264   /** Sets the edited entry to the given value.
265    * @param entry the string to set
266    */

267   public void setEditedEntry(String JavaDoc entry) {
268     if (!entry.equals(getCurrent())) _editedEntries.put(new Integer JavaDoc(_cursor), entry);
269   }
270
271   /** Reverse-searches the history for the previous matching string.
272    * @param currentInteraction the current interaction
273    */

274   public void reverseSearch(String JavaDoc currentInteraction) {
275     if (_currentSearchString.equals("") || ! currentInteraction.startsWith(_currentSearchString))
276       _currentSearchString = currentInteraction;
277
278     setEditedEntry(currentInteraction);
279     while (hasPrevious()) {
280       movePrevious(getCurrent());
281       if (getCurrent().startsWith(_currentSearchString, 0)) break;
282     }
283     
284     if (! getCurrent().startsWith(_currentSearchString, 0)) moveEnd();
285   }
286
287   /** Forward-searches the history for the next matching string.
288    * @param currentInteraction the current interaction
289    */

290   public void forwardSearch(String JavaDoc currentInteraction) {
291     if (_currentSearchString.equals("") || ! currentInteraction.startsWith(_currentSearchString))
292       _currentSearchString = currentInteraction;
293
294     setEditedEntry(currentInteraction);
295     while (hasNext()) {
296       moveNext(getCurrent());
297       if (getCurrent().startsWith(_currentSearchString, 0)) break;
298     }
299     
300     if (! getCurrent().startsWith(_currentSearchString, 0)) moveEnd();
301   }
302 }
303
Popular Tags