KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > eclipse > jface > text > rules > FastPartitioner


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.rules;
12
13
14 import java.util.ArrayList JavaDoc;
15 import java.util.List JavaDoc;
16
17 import org.eclipse.core.runtime.Assert;
18 import org.eclipse.core.runtime.Platform;
19
20 import org.eclipse.jface.text.BadLocationException;
21 import org.eclipse.jface.text.BadPositionCategoryException;
22 import org.eclipse.jface.text.DefaultPositionUpdater;
23 import org.eclipse.jface.text.DocumentEvent;
24 import org.eclipse.jface.text.DocumentRewriteSession;
25 import org.eclipse.jface.text.IDocument;
26 import org.eclipse.jface.text.IDocumentPartitioner;
27 import org.eclipse.jface.text.IDocumentPartitionerExtension;
28 import org.eclipse.jface.text.IDocumentPartitionerExtension2;
29 import org.eclipse.jface.text.IDocumentPartitionerExtension3;
30 import org.eclipse.jface.text.IRegion;
31 import org.eclipse.jface.text.ITypedRegion;
32 import org.eclipse.jface.text.Position;
33 import org.eclipse.jface.text.Region;
34 import org.eclipse.jface.text.TextUtilities;
35 import org.eclipse.jface.text.TypedPosition;
36 import org.eclipse.jface.text.TypedRegion;
37
38
39
40 /**
41  * A standard implementation of a document partitioner. It uses an
42  * {@link IPartitionTokenScanner} to scan the document and to determine the
43  * document's partitioning. The tokens returned by the scanner must return the
44  * partition type as their data. The partitioner remembers the document's
45  * partitions in the document itself rather than maintaining its own data
46  * structure.
47  * <p>
48  * To reduce array creations in {@link IDocument#getPositions(String)}, the
49  * positions get cached. The cache is cleared after updating the positions in
50  * {@link #documentChanged2(DocumentEvent)}. Subclasses need to call
51  * {@link #clearPositionCache()} after modifying the partitioner's positions.
52  * The cached positions may be accessed through {@link #getPositions()}.
53  * </p>
54  *
55  * @see IPartitionTokenScanner
56  * @since 3.1
57  */

58 public class FastPartitioner implements IDocumentPartitioner, IDocumentPartitionerExtension, IDocumentPartitionerExtension2, IDocumentPartitionerExtension3 {
59
60     /**
61      * The position category this partitioner uses to store the document's partitioning information.
62      */

63     private static final String JavaDoc CONTENT_TYPES_CATEGORY= "__content_types_category"; //$NON-NLS-1$
64
/** The partitioner's scanner */
65     protected final IPartitionTokenScanner fScanner;
66     /** The legal content types of this partitioner */
67     protected final String JavaDoc[] fLegalContentTypes;
68     /** The partitioner's document */
69     protected IDocument fDocument;
70     /** The document length before a document change occurred */
71     protected int fPreviousDocumentLength;
72     /** The position updater used to for the default updating of partitions */
73     protected final DefaultPositionUpdater fPositionUpdater;
74     /** The offset at which the first changed partition starts */
75     protected int fStartOffset;
76     /** The offset at which the last changed partition ends */
77     protected int fEndOffset;
78     /**The offset at which a partition has been deleted */
79     protected int fDeleteOffset;
80     /**
81      * The position category this partitioner uses to store the document's partitioning information.
82      */

83     private final String JavaDoc fPositionCategory;
84     /**
85      * The active document rewrite session.
86      */

87     private DocumentRewriteSession fActiveRewriteSession;
88     /**
89      * Flag indicating whether this partitioner has been initialized.
90      */

91     private boolean fIsInitialized= false;
92     /**
93      * The cached positions from our document, so we don't create a new array every time
94      * someone requests partition information.
95      */

96     private Position[] fCachedPositions= null;
97     /** Debug option for cache consistency checking. */
98     private static final boolean CHECK_CACHE_CONSISTENCY= "true".equalsIgnoreCase(Platform.getDebugOption("org.eclipse.jface.text/debug/FastPartitioner/PositionCache")); //$NON-NLS-1$//$NON-NLS-2$;
99

100     /**
101      * Creates a new partitioner that uses the given scanner and may return
102      * partitions of the given legal content types.
103      *
104      * @param scanner the scanner this partitioner is supposed to use
105      * @param legalContentTypes the legal content types of this partitioner
106      */

107     public FastPartitioner(IPartitionTokenScanner scanner, String JavaDoc[] legalContentTypes) {
108         fScanner= scanner;
109         fLegalContentTypes= TextUtilities.copy(legalContentTypes);
110         fPositionCategory= CONTENT_TYPES_CATEGORY + hashCode();
111         fPositionUpdater= new DefaultPositionUpdater(fPositionCategory);
112     }
113
114     /*
115      * @see org.eclipse.jface.text.IDocumentPartitionerExtension2#getManagingPositionCategories()
116      */

117     public String JavaDoc[] getManagingPositionCategories() {
118         return new String JavaDoc[] { fPositionCategory };
119     }
120
121     /*
122      * @see org.eclipse.jface.text.IDocumentPartitioner#connect(org.eclipse.jface.text.IDocument)
123      */

124     public final void connect(IDocument document) {
125         connect(document, false);
126     }
127
128     /**
129      * {@inheritDoc}
130      * <p>
131      * May be extended by subclasses.
132      * </p>
133      */

134     public void connect(IDocument document, boolean delayInitialization) {
135         Assert.isNotNull(document);
136         Assert.isTrue(!document.containsPositionCategory(fPositionCategory));
137
138         fDocument= document;
139         fDocument.addPositionCategory(fPositionCategory);
140
141         fIsInitialized= false;
142         if (!delayInitialization)
143             checkInitialization();
144     }
145
146     /**
147      * Calls {@link #initialize()} if the receiver is not yet initialized.
148      */

149     protected final void checkInitialization() {
150         if (!fIsInitialized)
151             initialize();
152     }
153
154     /**
155      * Performs the initial partitioning of the partitioner's document.
156      * <p>
157      * May be extended by subclasses.
158      * </p>
159      */

160     protected void initialize() {
161         fIsInitialized= true;
162         clearPositionCache();
163         fScanner.setRange(fDocument, 0, fDocument.getLength());
164
165         try {
166             IToken token= fScanner.nextToken();
167             while (!token.isEOF()) {
168
169                 String JavaDoc contentType= getTokenContentType(token);
170
171                 if (isSupportedContentType(contentType)) {
172                     TypedPosition p= new TypedPosition(fScanner.getTokenOffset(), fScanner.getTokenLength(), contentType);
173                     fDocument.addPosition(fPositionCategory, p);
174                 }
175
176                 token= fScanner.nextToken();
177             }
178         } catch (BadLocationException x) {
179             // cannot happen as offsets come from scanner
180
} catch (BadPositionCategoryException x) {
181             // cannot happen if document has been connected before
182
}
183     }
184
185     /**
186      * {@inheritDoc}
187      * <p>
188      * May be extended by subclasses.
189      * </p>
190      */

191     public void disconnect() {
192
193         Assert.isTrue(fDocument.containsPositionCategory(fPositionCategory));
194
195         try {
196             fDocument.removePositionCategory(fPositionCategory);
197         } catch (BadPositionCategoryException x) {
198             // can not happen because of Assert
199
}
200     }
201
202     /**
203      * {@inheritDoc}
204      * <p>
205      * May be extended by subclasses.
206      * </p>
207      */

208     public void documentAboutToBeChanged(DocumentEvent e) {
209         if (fIsInitialized) {
210
211             Assert.isTrue(e.getDocument() == fDocument);
212
213             fPreviousDocumentLength= e.getDocument().getLength();
214             fStartOffset= -1;
215             fEndOffset= -1;
216             fDeleteOffset= -1;
217         }
218     }
219
220     /*
221      * @see IDocumentPartitioner#documentChanged(DocumentEvent)
222      */

223     public final boolean documentChanged(DocumentEvent e) {
224         if (fIsInitialized) {
225             IRegion region= documentChanged2(e);
226             return (region != null);
227         }
228         return false;
229     }
230
231     /**
232      * Helper method for tracking the minimal region containing all partition changes.
233      * If <code>offset</code> is smaller than the remembered offset, <code>offset</code>
234      * will from now on be remembered. If <code>offset + length</code> is greater than
235      * the remembered end offset, it will be remembered from now on.
236      *
237      * @param offset the offset
238      * @param length the length
239      */

240     private void rememberRegion(int offset, int length) {
241         // remember start offset
242
if (fStartOffset == -1)
243             fStartOffset= offset;
244         else if (offset < fStartOffset)
245             fStartOffset= offset;
246
247         // remember end offset
248
int endOffset= offset + length;
249         if (fEndOffset == -1)
250             fEndOffset= endOffset;
251         else if (endOffset > fEndOffset)
252             fEndOffset= endOffset;
253     }
254
255     /**
256      * Remembers the given offset as the deletion offset.
257      *
258      * @param offset the offset
259      */

260     private void rememberDeletedOffset(int offset) {
261         fDeleteOffset= offset;
262     }
263
264     /**
265      * Creates the minimal region containing all partition changes using the
266      * remembered offset, end offset, and deletion offset.
267      *
268      * @return the minimal region containing all the partition changes
269      */

270     private IRegion createRegion() {
271         if (fDeleteOffset == -1) {
272             if (fStartOffset == -1 || fEndOffset == -1)
273                 return null;
274             return new Region(fStartOffset, fEndOffset - fStartOffset);
275         } else if (fStartOffset == -1 || fEndOffset == -1) {
276             return new Region(fDeleteOffset, 0);
277         } else {
278             int offset= Math.min(fDeleteOffset, fStartOffset);
279             int endOffset= Math.max(fDeleteOffset, fEndOffset);
280             return new Region(offset, endOffset - offset);
281         }
282     }
283
284     /**
285      * {@inheritDoc}
286      * <p>
287      * May be extended by subclasses.
288      * </p>
289      */

290     public IRegion documentChanged2(DocumentEvent e) {
291
292         if (!fIsInitialized)
293             return null;
294
295         try {
296             Assert.isTrue(e.getDocument() == fDocument);
297
298             Position[] category= getPositions();
299             IRegion line= fDocument.getLineInformationOfOffset(e.getOffset());
300             int reparseStart= line.getOffset();
301             int partitionStart= -1;
302             String JavaDoc contentType= null;
303             int newLength= e.getText() == null ? 0 : e.getText().length();
304
305             int first= fDocument.computeIndexInCategory(fPositionCategory, reparseStart);
306             if (first > 0) {
307                 TypedPosition partition= (TypedPosition) category[first - 1];
308                 if (partition.includes(reparseStart)) {
309                     partitionStart= partition.getOffset();
310                     contentType= partition.getType();
311                     if (e.getOffset() == partition.getOffset() + partition.getLength())
312                         reparseStart= partitionStart;
313                     -- first;
314                 } else if (reparseStart == e.getOffset() && reparseStart == partition.getOffset() + partition.getLength()) {
315                     partitionStart= partition.getOffset();
316                     contentType= partition.getType();
317                     reparseStart= partitionStart;
318                     -- first;
319                 } else {
320                     partitionStart= partition.getOffset() + partition.getLength();
321                     contentType= IDocument.DEFAULT_CONTENT_TYPE;
322                 }
323             }
324
325             fPositionUpdater.update(e);
326             for (int i= first; i < category.length; i++) {
327                 Position p= category[i];
328                 if (p.isDeleted) {
329                     rememberDeletedOffset(e.getOffset());
330                     break;
331                 }
332             }
333             clearPositionCache();
334             category= getPositions();
335
336             fScanner.setPartialRange(fDocument, reparseStart, fDocument.getLength() - reparseStart, contentType, partitionStart);
337
338             int behindLastScannedPosition= reparseStart;
339             IToken token= fScanner.nextToken();
340
341             while (!token.isEOF()) {
342
343                 contentType= getTokenContentType(token);
344
345                 if (!isSupportedContentType(contentType)) {
346                     token= fScanner.nextToken();
347                     continue;
348                 }
349
350                 int start= fScanner.getTokenOffset();
351                 int length= fScanner.getTokenLength();
352
353                 behindLastScannedPosition= start + length;
354                 int lastScannedPosition= behindLastScannedPosition - 1;
355
356                 // remove all affected positions
357
while (first < category.length) {
358                     TypedPosition p= (TypedPosition) category[first];
359                     if (lastScannedPosition >= p.offset + p.length ||
360                             (p.overlapsWith(start, length) &&
361                                 (!fDocument.containsPosition(fPositionCategory, start, length) ||
362                                  !contentType.equals(p.getType())))) {
363
364                         rememberRegion(p.offset, p.length);
365                         fDocument.removePosition(fPositionCategory, p);
366                         ++ first;
367
368                     } else
369                         break;
370                 }
371
372                 // if position already exists and we have scanned at least the
373
// area covered by the event, we are done
374
if (fDocument.containsPosition(fPositionCategory, start, length)) {
375                     if (lastScannedPosition >= e.getOffset() + newLength)
376                         return createRegion();
377                     ++ first;
378                 } else {
379                     // insert the new type position
380
try {
381                         fDocument.addPosition(fPositionCategory, new TypedPosition(start, length, contentType));
382                         rememberRegion(start, length);
383                     } catch (BadPositionCategoryException x) {
384                     } catch (BadLocationException x) {
385                     }
386                 }
387
388                 token= fScanner.nextToken();
389             }
390
391             first= fDocument.computeIndexInCategory(fPositionCategory, behindLastScannedPosition);
392
393             clearPositionCache();
394             category= getPositions();
395             TypedPosition p;
396             while (first < category.length) {
397                 p= (TypedPosition) category[first++];
398                 fDocument.removePosition(fPositionCategory, p);
399                 rememberRegion(p.offset, p.length);
400             }
401
402         } catch (BadPositionCategoryException x) {
403             // should never happen on connected documents
404
} catch (BadLocationException x) {
405         } finally {
406             clearPositionCache();
407         }
408
409         return createRegion();
410     }
411
412     /**
413      * Returns the position in the partitoner's position category which is
414      * close to the given offset. This is, the position has either an offset which
415      * is the same as the given offset or an offset which is smaller than the given
416      * offset. This method profits from the knowledge that a partitioning is
417      * a ordered set of disjoint position.
418      * <p>
419      * May be extended or replaced by subclasses.
420      * </p>
421      * @param offset the offset for which to search the closest position
422      * @return the closest position in the partitioner's category
423      */

424     protected TypedPosition findClosestPosition(int offset) {
425
426         try {
427
428             int index= fDocument.computeIndexInCategory(fPositionCategory, offset);
429             Position[] category= getPositions();
430
431             if (category.length == 0)
432                 return null;
433
434             if (index < category.length) {
435                 if (offset == category[index].offset)
436                     return (TypedPosition) category[index];
437             }
438
439             if (index > 0)
440                 index--;
441
442             return (TypedPosition) category[index];
443
444         } catch (BadPositionCategoryException x) {
445         } catch (BadLocationException x) {
446         }
447
448         return null;
449     }
450
451
452     /**
453      * {@inheritDoc}
454      * <p>
455      * May be replaced or extended by subclasses.
456      * </p>
457      */

458     public String JavaDoc getContentType(int offset) {
459         checkInitialization();
460
461         TypedPosition p= findClosestPosition(offset);
462         if (p != null && p.includes(offset))
463             return p.getType();
464
465         return IDocument.DEFAULT_CONTENT_TYPE;
466     }
467
468     /**
469      * {@inheritDoc}
470      * <p>
471      * May be replaced or extended by subclasses.
472      * </p>
473      */

474     public ITypedRegion getPartition(int offset) {
475         checkInitialization();
476
477         try {
478
479             Position[] category = getPositions();
480
481             if (category == null || category.length == 0)
482                 return new TypedRegion(0, fDocument.getLength(), IDocument.DEFAULT_CONTENT_TYPE);
483
484             int index= fDocument.computeIndexInCategory(fPositionCategory, offset);
485
486             if (index < category.length) {
487
488                 TypedPosition next= (TypedPosition) category[index];
489
490                 if (offset == next.offset)
491                     return new TypedRegion(next.getOffset(), next.getLength(), next.getType());
492
493                 if (index == 0)
494                     return new TypedRegion(0, next.offset, IDocument.DEFAULT_CONTENT_TYPE);
495
496                 TypedPosition previous= (TypedPosition) category[index - 1];
497                 if (previous.includes(offset))
498                     return new TypedRegion(previous.getOffset(), previous.getLength(), previous.getType());
499
500                 int endOffset= previous.getOffset() + previous.getLength();
501                 return new TypedRegion(endOffset, next.getOffset() - endOffset, IDocument.DEFAULT_CONTENT_TYPE);
502             }
503
504             TypedPosition previous= (TypedPosition) category[category.length - 1];
505             if (previous.includes(offset))
506                 return new TypedRegion(previous.getOffset(), previous.getLength(), previous.getType());
507
508             int endOffset= previous.getOffset() + previous.getLength();
509             return new TypedRegion(endOffset, fDocument.getLength() - endOffset, IDocument.DEFAULT_CONTENT_TYPE);
510
511         } catch (BadPositionCategoryException x) {
512         } catch (BadLocationException x) {
513         }
514
515         return new TypedRegion(0, fDocument.getLength(), IDocument.DEFAULT_CONTENT_TYPE);
516     }
517
518     /*
519      * @see IDocumentPartitioner#computePartitioning(int, int)
520      */

521     public final ITypedRegion[] computePartitioning(int offset, int length) {
522         return computePartitioning(offset, length, false);
523     }
524
525     /**
526      * {@inheritDoc}
527      * <p>
528      * May be replaced or extended by subclasses.
529      * </p>
530      */

531     public String JavaDoc[] getLegalContentTypes() {
532         return TextUtilities.copy(fLegalContentTypes);
533     }
534
535     /**
536      * Returns whether the given type is one of the legal content types.
537      * <p>
538      * May be extended by subclasses.
539      * </p>
540      *
541      * @param contentType the content type to check
542      * @return <code>true</code> if the content type is a legal content type
543      */

544     protected boolean isSupportedContentType(String JavaDoc contentType) {
545         if (contentType != null) {
546             for (int i= 0; i < fLegalContentTypes.length; i++) {
547                 if (fLegalContentTypes[i].equals(contentType))
548                     return true;
549             }
550         }
551
552         return false;
553     }
554
555     /**
556      * Returns a content type encoded in the given token. If the token's
557      * data is not <code>null</code> and a string it is assumed that
558      * it is the encoded content type.
559      * <p>
560      * May be replaced or extended by subclasses.
561      * </p>
562      *
563      * @param token the token whose content type is to be determined
564      * @return the token's content type
565      */

566     protected String JavaDoc getTokenContentType(IToken token) {
567         Object JavaDoc data= token.getData();
568         if (data instanceof String JavaDoc)
569             return (String JavaDoc) data;
570         return null;
571     }
572
573     /* zero-length partition support */
574
575     /**
576      * {@inheritDoc}
577      * <p>
578      * May be replaced or extended by subclasses.
579      * </p>
580      */

581     public String JavaDoc getContentType(int offset, boolean preferOpenPartitions) {
582         return getPartition(offset, preferOpenPartitions).getType();
583     }
584
585     /**
586      * {@inheritDoc}
587      * <p>
588      * May be replaced or extended by subclasses.
589      * </p>
590      */

591     public ITypedRegion getPartition(int offset, boolean preferOpenPartitions) {
592         ITypedRegion region= getPartition(offset);
593         if (preferOpenPartitions) {
594             if (region.getOffset() == offset && !region.getType().equals(IDocument.DEFAULT_CONTENT_TYPE)) {
595                 if (offset > 0) {
596                     region= getPartition(offset - 1);
597                     if (region.getType().equals(IDocument.DEFAULT_CONTENT_TYPE))
598                         return region;
599                 }
600                 return new TypedRegion(offset, 0, IDocument.DEFAULT_CONTENT_TYPE);
601             }
602         }
603         return region;
604     }
605
606     /**
607      * {@inheritDoc}
608      * <p>
609      * May be replaced or extended by subclasses.
610      * </p>
611      */

612     public ITypedRegion[] computePartitioning(int offset, int length, boolean includeZeroLengthPartitions) {
613         checkInitialization();
614         List JavaDoc list= new ArrayList JavaDoc();
615
616         try {
617
618             int endOffset= offset + length;
619
620             Position[] category= getPositions();
621
622             TypedPosition previous= null, current= null;
623             int start, end, gapOffset;
624             Position gap= new Position(0);
625
626             int startIndex= getFirstIndexEndingAfterOffset(category, offset);
627             int endIndex= getFirstIndexStartingAfterOffset(category, endOffset);
628             for (int i= startIndex; i < endIndex; i++) {
629
630                 current= (TypedPosition) category[i];
631
632                 gapOffset= (previous != null) ? previous.getOffset() + previous.getLength() : 0;
633                 gap.setOffset(gapOffset);
634                 gap.setLength(current.getOffset() - gapOffset);
635                 if ((includeZeroLengthPartitions && overlapsOrTouches(gap, offset, length)) ||
636                         (gap.getLength() > 0 && gap.overlapsWith(offset, length))) {
637                     start= Math.max(offset, gapOffset);
638                     end= Math.min(endOffset, gap.getOffset() + gap.getLength());
639                     list.add(new TypedRegion(start, end - start, IDocument.DEFAULT_CONTENT_TYPE));
640                 }
641
642                 if (current.overlapsWith(offset, length)) {
643                     start= Math.max(offset, current.getOffset());
644                     end= Math.min(endOffset, current.getOffset() + current.getLength());
645                     list.add(new TypedRegion(start, end - start, current.getType()));
646                 }
647
648                 previous= current;
649             }
650
651             if (previous != null) {
652                 gapOffset= previous.getOffset() + previous.getLength();
653                 gap.setOffset(gapOffset);
654                 gap.setLength(fDocument.getLength() - gapOffset);
655                 if ((includeZeroLengthPartitions && overlapsOrTouches(gap, offset, length)) ||
656                         (gap.getLength() > 0 && gap.overlapsWith(offset, length))) {
657                     start= Math.max(offset, gapOffset);
658                     end= Math.min(endOffset, fDocument.getLength());
659                     list.add(new TypedRegion(start, end - start, IDocument.DEFAULT_CONTENT_TYPE));
660                 }
661             }
662
663             if (list.isEmpty())
664                 list.add(new TypedRegion(offset, length, IDocument.DEFAULT_CONTENT_TYPE));
665
666         } catch (BadPositionCategoryException ex) {
667             // Make sure we clear the cache
668
clearPositionCache();
669         } catch (RuntimeException JavaDoc ex) {
670             // Make sure we clear the cache
671
clearPositionCache();
672             throw ex;
673         }
674
675         TypedRegion[] result= new TypedRegion[list.size()];
676         list.toArray(result);
677         return result;
678     }
679
680     /**
681      * Returns <code>true</code> if the given ranges overlap with or touch each other.
682      *
683      * @param gap the first range
684      * @param offset the offset of the second range
685      * @param length the length of the second range
686      * @return <code>true</code> if the given ranges overlap with or touch each other
687      */

688     private boolean overlapsOrTouches(Position gap, int offset, int length) {
689         return gap.getOffset() <= offset + length && offset <= gap.getOffset() + gap.getLength();
690     }
691
692     /**
693      * Returns the index of the first position which ends after the given offset.
694      *
695      * @param positions the positions in linear order
696      * @param offset the offset
697      * @return the index of the first position which ends after the offset
698      */

699     private int getFirstIndexEndingAfterOffset(Position[] positions, int offset) {
700         int i= -1, j= positions.length;
701         while (j - i > 1) {
702             int k= (i + j) >> 1;
703             Position p= positions[k];
704             if (p.getOffset() + p.getLength() > offset)
705                 j= k;
706             else
707                 i= k;
708         }
709         return j;
710     }
711
712     /**
713      * Returns the index of the first position which starts at or after the given offset.
714      *
715      * @param positions the positions in linear order
716      * @param offset the offset
717      * @return the index of the first position which starts after the offset
718      */

719     private int getFirstIndexStartingAfterOffset(Position[] positions, int offset) {
720         int i= -1, j= positions.length;
721         while (j - i > 1) {
722             int k= (i + j) >> 1;
723             Position p= positions[k];
724             if (p.getOffset() >= offset)
725                 j= k;
726             else
727                 i= k;
728         }
729         return j;
730     }
731
732     /*
733      * @see org.eclipse.jface.text.IDocumentPartitionerExtension3#startRewriteSession(org.eclipse.jface.text.DocumentRewriteSession)
734      */

735     public void startRewriteSession(DocumentRewriteSession session) throws IllegalStateException JavaDoc {
736         if (fActiveRewriteSession != null)
737             throw new IllegalStateException JavaDoc();
738         fActiveRewriteSession= session;
739     }
740
741     /**
742      * {@inheritDoc}
743      * <p>
744      * May be extended by subclasses.
745      * </p>
746      */

747     public void stopRewriteSession(DocumentRewriteSession session) {
748         if (fActiveRewriteSession == session)
749             flushRewriteSession();
750     }
751
752     /**
753      * {@inheritDoc}
754      * <p>
755      * May be extended by subclasses.
756      * </p>
757      */

758     public DocumentRewriteSession getActiveRewriteSession() {
759         return fActiveRewriteSession;
760     }
761
762     /**
763      * Flushes the active rewrite session.
764      */

765     protected final void flushRewriteSession() {
766         fActiveRewriteSession= null;
767
768         // remove all position belonging to the partitioner position category
769
try {
770             fDocument.removePositionCategory(fPositionCategory);
771         } catch (BadPositionCategoryException x) {
772         }
773         fDocument.addPositionCategory(fPositionCategory);
774
775         fIsInitialized= false;
776     }
777
778     /**
779      * Clears the position cache. Needs to be called whenever the positions have
780      * been updated.
781      */

782     protected final void clearPositionCache() {
783         if (fCachedPositions != null) {
784             fCachedPositions= null;
785         }
786     }
787
788     /**
789      * Returns the partitioners positions.
790      *
791      * @return the partitioners positions
792      * @throws BadPositionCategoryException if getting the positions from the
793      * document fails
794      */

795     protected final Position[] getPositions() throws BadPositionCategoryException {
796         if (fCachedPositions == null) {
797             fCachedPositions= fDocument.getPositions(fPositionCategory);
798         } else if (CHECK_CACHE_CONSISTENCY) {
799             Position[] positions= fDocument.getPositions(fPositionCategory);
800             int len= Math.min(positions.length, fCachedPositions.length);
801             for (int i= 0; i < len; i++) {
802                 if (!positions[i].equals(fCachedPositions[i]))
803                     System.err.println("FastPartitioner.getPositions(): cached position is not up to date: from document: " + toString(positions[i]) + " in cache: " + toString(fCachedPositions[i])); //$NON-NLS-1$ //$NON-NLS-2$
804
}
805             for (int i= len; i < positions.length; i++)
806                 System.err.println("FastPartitioner.getPositions(): new position in document: " + toString(positions[i])); //$NON-NLS-1$
807
for (int i= len; i < fCachedPositions.length; i++)
808                 System.err.println("FastPartitioner.getPositions(): stale position in cache: " + toString(fCachedPositions[i])); //$NON-NLS-1$
809
}
810         return fCachedPositions;
811     }
812
813     /**
814      * Pretty print a <code>Position</code>.
815      *
816      * @param position the position to format
817      * @return a formatted string
818      */

819     private String JavaDoc toString(Position position) {
820         return "P[" + position.getOffset() + "+" + position.getLength() + "]"; //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$
821
}
822 }
823
Popular Tags