KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > edu > rice > cs > drjava > model > definitions > reducedmodel > AbstractReducedModel


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-2006 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.definitions.reducedmodel;
35
36 /**
37  * A refactoring of the common code between ReducedModelComment and
38  * ReducedModelBrace. Both of the refactored classes extend this class.
39  * @version $Id: AbstractReducedModel.java 3903 2006-07-05 20:03:06Z rcartwright $
40  * @author JavaPLT
41  */

42 public abstract class AbstractReducedModel implements ReducedModelStates {
43     
44   /** The character that represents the cursor in toString(). @see #toString() */
45   public static final char PTR_CHAR = '#';
46   
47   /** The reduced model for a document is a list of ReducedTokens (braces and gaps).
48    * @see ModelList
49    */

50   TokenList _tokens;
51   
52   /** Keeps track of cursor position in document.
53    * @see ModelList.Iterator
54    */

55   TokenList.Iterator _cursor;
56   
57   /** Constructor. Creates a new reduced model with the cursor at the start of a blank "page." */
58   public AbstractReducedModel() {
59     _tokens = new TokenList();
60     _cursor = _tokens._getIterator();
61     // we should be pointing to the head of the list
62
_cursor.setBlockOffset(0);
63   }
64  
65   /** Get the offset into the current ReducedToken.
66    * @return the number of characters into the token where the cursor sits
67    */

68   int getBlockOffset() { return _cursor.getBlockOffset(); }
69   
70   /** Change the offset into the current ReducedToken.
71    * @param offset the number of characters into the token to set the cursor
72    */

73   void setBlockOffset(int offset) { _cursor.setBlockOffset(offset); }
74   
75   /** Package private absolute offset for tests. We don't keep track of absolute offset as it causes too much confusion
76    * and trouble.
77    */

78   int absOffset() {
79     int off = _cursor.getBlockOffset();
80     TokenList.Iterator it = _cursor._copy();
81     if (! it.atStart()) it.prev();
82     
83     while (! it.atStart()) {
84       off += it.current().getSize();
85       it.prev();
86     }
87     it.dispose();
88     return off;
89   }
90   
91   /** A toString() replacement for testing - easier to read. */
92   public String JavaDoc simpleString() {
93     final StringBuilder JavaDoc val = new StringBuilder JavaDoc();
94     ReducedToken tmp;
95     
96     TokenList.Iterator it = _tokens._getIterator();
97     it.next(); // since we start at the head, which has no current item
98

99     if (_cursor.atStart()) val.append(PTR_CHAR).append(_cursor.getBlockOffset());
100     
101     while (!it.atEnd()) {
102       tmp = it.current();
103       
104       if (!_cursor.atStart() && !_cursor.atEnd() && (tmp == _cursor.current())) {
105         val.append(PTR_CHAR).append(_cursor.getBlockOffset());
106       }
107       
108       val.append('|').append(tmp).append('|').append('\t');
109       it.next();
110     }
111     
112     if (_cursor.atEnd()) val.append(PTR_CHAR).append(_cursor.getBlockOffset());
113     
114     val.append("|end|");
115     it.dispose();
116     return val.toString();
117   }
118   
119   /** Inserts a character into the reduced model. A method to be implemented in each specific reduced
120    * sub-model. */

121   public abstract void insertChar(char ch);
122   
123   /**
124    * Inserts a block of text into the reduced model which has no
125    * special consideration in the reduced model.
126    * <OL>
127    * <li> atStart: if gap to right, augment first gap, else insert
128    * <li> atEnd: if gap to left, augment left gap, else insert
129    * <li> inside a gap: grow current gap, move offset by length
130    * <li> inside a multiple character brace:
131    * <ol>
132    * <li> break current brace
133    * <li> insert new gap
134    * </ol>
135    * <li> gap to left: grow that gap and set offset to zero
136    * <li> gap to right: this case handled by inside gap (offset invariant)
137    * <li> between two braces: insert new gap
138    * @param length the length of the inserted text
139    */

140   public void _insertGap( int length ) {
141     if (_cursor.atStart()) {
142       if (_gapToRight()) {
143         _cursor.next();
144         _augmentCurrentGap(length); //increases gap and moves offset
145
}
146       else _insertNewGap(length);//inserts gap and goes to next item
147
}
148     else if (_cursor.atEnd()) {
149       if (_gapToLeft()) {
150         _augmentGapToLeft(length);
151         //increases the gap to the left and
152
//cursor to next item in list leaving offset 0
153
}
154       else _insertNewGap(length); //inserts gap and moves to next item
155
}
156     // should we insert a Gap in between the characters of a multiple char brace
157
else if ((_cursor.getBlockOffset() > 0) && _cursor.current().isMultipleCharBrace())
158       insertGapBetweenMultiCharBrace(length);
159     // inserting inside a Gap
160
else if (_cursor.current().isGap()) {
161       _cursor.current().grow(length);
162       _cursor.setBlockOffset(_cursor.getBlockOffset() + length);
163     }
164     else if (!_cursor.atFirstItem() && _cursor.prevItem().isGap())
165       //already pointing to next item
166
_cursor.prevItem().grow(length);
167     else //between two braces
168
_insertNewGap(length); //inserts a gap and goes to the next item
169
return;
170   }
171
172   /**
173    * Inserts a gap between a multiple character brace.
174    * Because ReducedModelBrace does not keep track of multiple character
175    * braces, only (),{}, and [], it differed in its implementation of
176    * inserGap(int) from ReducedModelComment's. To pull out the otherwise
177    * identical code and place it here, we created this function to do
178    * something meaningful in ReducedModelComment and to throw an exception
179    * in ReducedModelBrace.
180    */

181   protected abstract void insertGapBetweenMultiCharBrace(int length);
182   
183   /**
184    * Make a copy of the token list's iterator.
185    * Be sure to dispose of the result of this method after you are
186    * finished with it, or there will be memory leaks as long as
187    * this ReducedModel is not garbage collected.
188    */

189   public TokenList.Iterator makeCopyCursor() {
190     return _cursor._copy();
191   }
192   
193   /**
194    * Wrapper for TokenList.Iterator.getStateAtCurrent that returns the current
195    * state for some iterator.
196    * Convenience method to return the current state in the cursor iterator.
197    */

198   protected ReducedModelState getStateAtCurrent() {
199     return _cursor.getStateAtCurrent();
200   }
201
202   /** Determines if there is a Gap immediately to the right of the cursor. */
203   protected boolean _gapToRight() {
204     // Before using, make sure not at last, or tail.
205
return (!_tokens.isEmpty() && !_cursor.atEnd() &&
206             !_cursor.atLastItem() && _cursor.nextItem().isGap());
207   }
208   
209   /** Determines if there is a gap immediately to the left of the cursor. */
210   protected boolean _gapToLeft() {
211     // Before using, make sure not at first or head.
212
return (!_tokens.isEmpty() && !_cursor.atStart() && !_cursor.atFirstItem() &&_cursor.prevItem().isGap());
213   }
214   
215   /** Assuming there is a gap to the left, this function increases the size of that gap.
216    * @param length the amount of increase
217    */

218   protected void _augmentGapToLeft(int length) { _cursor.prevItem().grow(length); }
219   
220   /** Assuming there is a gap to the right, this function increases the size of that gap.
221    * @param length the amount of increase
222    */

223   protected void _augmentCurrentGap(int length) {
224     _cursor.current().grow(length);
225     _cursor.setBlockOffset(length);
226   }
227   
228   /** Helper function for _insertGap. Performs the actual insert and marks the offset appropriately.
229    * @param length size of gap to insert
230    */

231   protected void _insertNewGap(int length) {
232     _cursor.insert(new Gap(length, getStateAtCurrent()));
233     _cursor.next();
234     _cursor.setBlockOffset(0);
235   }
236   
237   /** Returns the state at the relLocation, where relLocation is the location
238    * relative to the walker
239    * @param relLocation distance from walker to get state at.
240    */

241   protected abstract ReducedModelState moveWalkerGetState(int relLocation);
242   
243   /** Resets the walker to the current position in document. */
244   protected abstract void resetWalkerLocationToCursor();
245
246   /**
247    * Get the ReducedToken currently pointed at by the cursor.
248    * @return the current token
249    */

250   protected ReducedToken current() { return _cursor.current(); }
251   
252   /** Move to the token immediately right. This function forwards its responsibilities to the cursor.
253    * If the cursor is at the end, it will throw an exception.
254    */

255   protected void next() { _cursor.next(); }
256
257   /**
258    * Move to the token immediately left.
259    * This function forwards its responsibilities to the TokenList
260    * iterator. If the cursor is at the start, it will throw an
261    * exception.
262    */

263   protected void prev() {
264     _cursor.prev();
265   }
266
267 }
268
Popular Tags