KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > eclipse > jface > text > AbstractLineTracker


1 /*******************************************************************************
2  * Copyright (c) 2000, 2006 IBM Corporation and others.
3  * All rights reserved. This program and the accompanying materials
4  * are made available under the terms of the Eclipse Public License v1.0
5  * which accompanies this distribution, and is available at
6  * http://www.eclipse.org/legal/epl-v10.html
7  *
8  * Contributors:
9  * IBM Corporation - initial API and implementation
10  *******************************************************************************/

11 package org.eclipse.jface.text;
12
13 import java.util.ArrayList JavaDoc;
14 import java.util.Iterator JavaDoc;
15 import java.util.List JavaDoc;
16
17 /**
18  * Abstract implementation of <code>ILineTracker</code>. It lets the definition of line
19  * delimiters to subclasses. Assuming that '\n' is the only line delimiter, this abstract
20  * implementation defines the following line scheme:
21  * <ul>
22  * <li> "" -> [0,0]
23  * <li> "a" -> [0,1]
24  * <li> "\n" -> [0,1], [1,0]
25  * <li> "a\n" -> [0,2], [2,0]
26  * <li> "a\nb" -> [0,2], [2,1]
27  * <li> "a\nbc\n" -> [0,2], [2,3], [5,0]
28  * </ul>
29  * <p>
30  * This class must be subclassed.
31  * </p>
32  */

33 public abstract class AbstractLineTracker implements ILineTracker, ILineTrackerExtension {
34
35     /**
36      * Tells whether this class is in debug mode.
37      *
38      * @since 3.1
39      */

40     private static final boolean DEBUG= false;
41
42     /**
43      * Combines the information of the occurrence of a line delimiter. <code>delimiterIndex</code>
44      * is the index where a line delimiter starts, whereas <code>delimiterLength</code>,
45      * indicates the length of the delimiter.
46      */

47     protected static class DelimiterInfo {
48         public int delimiterIndex;
49         public int delimiterLength;
50         public String JavaDoc delimiter;
51     }
52
53     /**
54      * Representation of replace and set requests.
55      *
56      * @since 3.1
57      */

58     protected static class Request {
59         public final int offset;
60         public final int length;
61         public final String JavaDoc text;
62
63         public Request(int offset, int length, String JavaDoc text) {
64             this.offset= offset;
65             this.length= length;
66             this.text= text;
67         }
68
69         public Request(String JavaDoc text) {
70             this.offset= -1;
71             this.length= -1;
72             this.text= text;
73         }
74
75         public boolean isReplaceRequest() {
76             return this.offset > -1 && this.length > -1;
77         }
78     }
79
80     /**
81      * The active rewrite session.
82      *
83      * @since 3.1
84      */

85     private DocumentRewriteSession fActiveRewriteSession;
86     /**
87      * The list of pending requests.
88      *
89      * @since 3.1
90      */

91     private List JavaDoc fPendingRequests;
92     /**
93      * The implementation that this tracker delegates to.
94      *
95      * @since 3.2
96      */

97     private ILineTracker fDelegate= new ListLineTracker() {
98         public String JavaDoc[] getLegalLineDelimiters() {
99             return AbstractLineTracker.this.getLegalLineDelimiters();
100         }
101
102         protected DelimiterInfo nextDelimiterInfo(String JavaDoc text, int offset) {
103             return AbstractLineTracker.this.nextDelimiterInfo(text, offset);
104         }
105     };
106     /**
107      * Whether the delegate needs conversion when the line structure is modified.
108      */

109     private boolean fNeedsConversion= true;
110
111     /**
112      * Creates a new line tracker.
113      */

114     protected AbstractLineTracker() {
115     }
116
117     /*
118      * @see org.eclipse.jface.text.ILineTracker#computeNumberOfLines(java.lang.String)
119      */

120     public int computeNumberOfLines(String JavaDoc text) {
121         return fDelegate.computeNumberOfLines(text);
122     }
123
124     /*
125      * @see org.eclipse.jface.text.ILineTracker#getLineDelimiter(int)
126      */

127     public String JavaDoc getLineDelimiter(int line) throws BadLocationException {
128         checkRewriteSession();
129         return fDelegate.getLineDelimiter(line);
130     }
131
132     /*
133      * @see org.eclipse.jface.text.ILineTracker#getLineInformation(int)
134      */

135     public IRegion getLineInformation(int line) throws BadLocationException {
136         checkRewriteSession();
137         return fDelegate.getLineInformation(line);
138     }
139
140     /*
141      * @see org.eclipse.jface.text.ILineTracker#getLineInformationOfOffset(int)
142      */

143     public IRegion getLineInformationOfOffset(int offset) throws BadLocationException {
144         checkRewriteSession();
145         return fDelegate.getLineInformationOfOffset(offset);
146     }
147
148     /*
149      * @see org.eclipse.jface.text.ILineTracker#getLineLength(int)
150      */

151     public int getLineLength(int line) throws BadLocationException {
152         checkRewriteSession();
153         return fDelegate.getLineLength(line);
154     }
155
156     /*
157      * @see org.eclipse.jface.text.ILineTracker#getLineNumberOfOffset(int)
158      */

159     public int getLineNumberOfOffset(int offset) throws BadLocationException {
160         checkRewriteSession();
161         return fDelegate.getLineNumberOfOffset(offset);
162     }
163
164     /*
165      * @see org.eclipse.jface.text.ILineTracker#getLineOffset(int)
166      */

167     public int getLineOffset(int line) throws BadLocationException {
168         checkRewriteSession();
169         return fDelegate.getLineOffset(line);
170     }
171
172     /*
173      * @see org.eclipse.jface.text.ILineTracker#getNumberOfLines()
174      */

175     public int getNumberOfLines() {
176         try {
177             checkRewriteSession();
178         } catch (BadLocationException x) {
179             // TODO there is currently no way to communicate that exception back to the document
180
}
181         return fDelegate.getNumberOfLines();
182     }
183
184     /*
185      * @see org.eclipse.jface.text.ILineTracker#getNumberOfLines(int, int)
186      */

187     public int getNumberOfLines(int offset, int length) throws BadLocationException {
188         checkRewriteSession();
189         return fDelegate.getNumberOfLines(offset, length);
190     }
191
192     /*
193      * @see org.eclipse.jface.text.ILineTracker#set(java.lang.String)
194      */

195     public void set(String JavaDoc text) {
196         if (hasActiveRewriteSession()) {
197             fPendingRequests.clear();
198             fPendingRequests.add(new Request(text));
199             return;
200         }
201
202         fDelegate.set(text);
203     }
204
205     /*
206      * @see org.eclipse.jface.text.ILineTracker#replace(int, int, java.lang.String)
207      */

208     public void replace(int offset, int length, String JavaDoc text) throws BadLocationException {
209         if (hasActiveRewriteSession()) {
210             fPendingRequests.add(new Request(offset, length, text));
211             return;
212         }
213
214         checkImplementation();
215
216         fDelegate.replace(offset, length, text);
217     }
218
219     /**
220      * Converts the implementation to be a {@link TreeLineTracker} if it isn't yet.
221      *
222      * @since 3.2
223      */

224     private void checkImplementation() {
225         if (fNeedsConversion) {
226             fNeedsConversion= false;
227             fDelegate= new TreeLineTracker((ListLineTracker) fDelegate) {
228                 protected DelimiterInfo nextDelimiterInfo(String JavaDoc text, int offset) {
229                     return AbstractLineTracker.this.nextDelimiterInfo(text, offset);
230                 }
231
232                 public String JavaDoc[] getLegalLineDelimiters() {
233                     return AbstractLineTracker.this.getLegalLineDelimiters();
234                 }
235             };
236         }
237     }
238
239     /**
240      * Returns the information about the first delimiter found in the given text starting at the
241      * given offset.
242      *
243      * @param text the text to be searched
244      * @param offset the offset in the given text
245      * @return the information of the first found delimiter or <code>null</code>
246      */

247     protected abstract DelimiterInfo nextDelimiterInfo(String JavaDoc text, int offset);
248
249     /*
250      * @see org.eclipse.jface.text.ILineTrackerExtension#startRewriteSession(org.eclipse.jface.text.DocumentRewriteSession)
251      * @since 3.1
252      */

253     public final void startRewriteSession(DocumentRewriteSession session) {
254         if (fActiveRewriteSession != null)
255             throw new IllegalStateException JavaDoc();
256         fActiveRewriteSession= session;
257         fPendingRequests= new ArrayList JavaDoc(20);
258     }
259
260     /*
261      * @see org.eclipse.jface.text.ILineTrackerExtension#stopRewriteSession(org.eclipse.jface.text.DocumentRewriteSession, java.lang.String)
262      * @since 3.1
263      */

264     public final void stopRewriteSession(DocumentRewriteSession session, String JavaDoc text) {
265         if (fActiveRewriteSession == session) {
266             fActiveRewriteSession= null;
267             fPendingRequests= null;
268             set(text);
269         }
270     }
271
272     /**
273      * Tells whether there's an active rewrite session.
274      *
275      * @return <code>true</code> if there is an active rewrite session, <code>false</code>
276      * otherwise
277      * @since 3.1
278      */

279     protected final boolean hasActiveRewriteSession() {
280         return fActiveRewriteSession != null;
281     }
282
283     /**
284      * Flushes the active rewrite session.
285      *
286      * @throws BadLocationException in case the recorded requests cannot be processed correctly
287      * @since 3.1
288      */

289     protected final void flushRewriteSession() throws BadLocationException {
290         if (DEBUG)
291             System.out.println("AbstractLineTracker: Flushing rewrite session: " + fActiveRewriteSession); //$NON-NLS-1$
292

293         Iterator JavaDoc e= fPendingRequests.iterator();
294
295         fPendingRequests= null;
296         fActiveRewriteSession= null;
297
298         while (e.hasNext()) {
299             Request request= (Request) e.next();
300             if (request.isReplaceRequest())
301                 replace(request.offset, request.length, request.text);
302             else
303                 set(request.text);
304         }
305     }
306
307     /**
308      * Checks the presence of a rewrite session and flushes it.
309      *
310      * @throws BadLocationException in case flushing does not succeed
311      * @since 3.1
312      */

313     protected final void checkRewriteSession() throws BadLocationException {
314         if (hasActiveRewriteSession())
315             flushRewriteSession();
316     }
317 }
318
Popular Tags