KickJava   Java API By Example, From Geeks To Geeks.

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


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
12 package org.eclipse.jface.text;
13
14
15 import java.util.ArrayList JavaDoc;
16 import java.util.Arrays JavaDoc;
17 import java.util.HashMap JavaDoc;
18 import java.util.Iterator JavaDoc;
19 import java.util.List JavaDoc;
20 import java.util.Map JavaDoc;
21 import java.util.regex.PatternSyntaxException JavaDoc;
22
23 import org.eclipse.core.runtime.Assert;
24 import org.eclipse.core.runtime.ListenerList;
25
26
27 /**
28  * Abstract default implementation of <code>IDocument</code> and its extension
29  * interfaces {@link org.eclipse.jface.text.IDocumentExtension},
30  * {@link org.eclipse.jface.text.IDocumentExtension2},
31  * {@link org.eclipse.jface.text.IDocumentExtension3},
32  * {@link org.eclipse.jface.text.IDocumentExtension4}, as well as
33  * {@link org.eclipse.jface.text.IRepairableDocument}.
34  * <p>
35  *
36  * An <code>AbstractDocument</code> supports the following implementation
37  * plug-ins:
38  * <ul>
39  * <li>a text store implementing {@link org.eclipse.jface.text.ITextStore} for
40  * storing and managing the document's content,</li>
41  * <li>a line tracker implementing {@link org.eclipse.jface.text.ILineTracker}
42  * to map character positions to line numbers and vice versa</li>
43  * </ul>
44  * The document can dynamically change the text store when switching between
45  * sequential rewrite mode and normal mode.
46  * <p>
47  *
48  * This class must be subclassed. Subclasses must configure which implementation
49  * plug-ins the document instance should use. Subclasses are not intended to
50  * overwrite existing methods.
51  *
52  * @see org.eclipse.jface.text.ITextStore
53  * @see org.eclipse.jface.text.ILineTracker
54  */

55 public abstract class AbstractDocument implements IDocument, IDocumentExtension, IDocumentExtension2, IDocumentExtension3, IDocumentExtension4, IRepairableDocument {
56
57     /**
58      * Tells whether this class is in debug mode.
59      * @since 3.1
60      */

61     private static final boolean DEBUG= false;
62
63
64     /**
65      * Inner class to bundle a registered post notification replace operation together with its
66      * owner.
67      *
68      * @since 2.0
69      */

70     static private class RegisteredReplace {
71         /** The owner of this replace operation. */
72         IDocumentListener fOwner;
73         /** The replace operation */
74         IDocumentExtension.IReplace fReplace;
75
76         /**
77          * Creates a new bundle object.
78          * @param owner the document listener owning the replace operation
79          * @param replace the replace operation
80          */

81         RegisteredReplace(IDocumentListener owner, IDocumentExtension.IReplace replace) {
82             fOwner= owner;
83             fReplace= replace;
84         }
85     }
86
87
88     /** The document's text store */
89     private ITextStore fStore;
90     /** The document's line tracker */
91     private ILineTracker fTracker;
92     /** The registered document listeners */
93     private ListenerList fDocumentListeners;
94     /** The registered pre-notified document listeners */
95     private ListenerList fPrenotifiedDocumentListeners;
96     /** The registered document partitioning listeners */
97     private ListenerList fDocumentPartitioningListeners;
98     /** All positions managed by the document */
99     private Map JavaDoc fPositions;
100     /** All registered document position updaters */
101     private List JavaDoc fPositionUpdaters;
102     /**
103      * The list of post notification changes
104      * @since 2.0
105      */

106     private List JavaDoc fPostNotificationChanges;
107     /**
108      * The reentrance count for post notification changes.
109      * @since 2.0
110      */

111     private int fReentranceCount= 0;
112     /**
113      * Indicates whether post notification change processing has been stopped.
114      * @since 2.0
115      */

116     private int fStoppedCount= 0;
117     /**
118      * Indicates whether the registration of post notification changes should be ignored.
119      * @since 2.1
120      */

121     private boolean fAcceptPostNotificationReplaces= true;
122     /**
123      * Indicates whether the notification of listeners has been stopped.
124      * @since 2.1
125      */

126     private int fStoppedListenerNotification= 0;
127     /**
128      * The document event to be sent after listener notification has been resumed.
129      * @since 2.1
130      */

131     private DocumentEvent fDeferredDocumentEvent;
132     /**
133      * The registered document partitioners.
134      * @since 3.0
135      */

136     private Map JavaDoc fDocumentPartitioners;
137     /**
138      * The partitioning changed event.
139      * @since 3.0
140      */

141     private DocumentPartitioningChangedEvent fDocumentPartitioningChangedEvent;
142     /**
143      * The find/replace document adapter.
144      * @since 3.0
145      */

146     private FindReplaceDocumentAdapter fFindReplaceDocumentAdapter;
147     /**
148      * The active document rewrite session.
149      * @since 3.1
150      */

151     private DocumentRewriteSession fDocumentRewriteSession;
152     /**
153      * The registered document rewrite session listeners.
154      * @since 3.1
155      */

156     private List JavaDoc fDocumentRewriteSessionListeners;
157     /**
158      * The current modification stamp.
159      * @since 3.1
160      */

161     private long fModificationStamp= IDocumentExtension4.UNKNOWN_MODIFICATION_STAMP;
162     /**
163      * Keeps track of next modification stamp.
164      * @since 3.1.1
165      */

166     private long fNextModificationStamp= IDocumentExtension4.UNKNOWN_MODIFICATION_STAMP;
167     /**
168      * This document's default line delimiter.
169      * @since 3.1
170      */

171     private String JavaDoc fInitialLineDelimiter;
172
173
174     /**
175      * The default constructor does not perform any configuration
176      * but leaves it to the clients who must first initialize the
177      * implementation plug-ins and then call <code>completeInitialization</code>.
178      * Results in the construction of an empty document.
179      */

180     protected AbstractDocument() {
181         fModificationStamp= getNextModificationStamp();
182     }
183
184
185     /**
186      * Returns the document's text store. Assumes that the
187      * document has been initialized with a text store.
188      *
189      * @return the document's text store
190      */

191     protected ITextStore getStore() {
192         Assert.isNotNull(fStore);
193         return fStore;
194     }
195
196     /**
197      * Returns the document's line tracker. Assumes that the
198      * document has been initialized with a line tracker.
199      *
200      * @return the document's line tracker
201      */

202     protected ILineTracker getTracker() {
203         Assert.isNotNull(fTracker);
204         return fTracker;
205     }
206
207     /**
208      * Returns the document's document listeners.
209      *
210      * @return the document's document listeners
211      */

212     protected List JavaDoc getDocumentListeners() {
213         return Arrays.asList(fDocumentListeners.getListeners());
214     }
215
216     /**
217      * Returns the document's partitioning listeners.
218      *
219      * @return the document's partitioning listeners
220      */

221     protected List JavaDoc getDocumentPartitioningListeners() {
222         return Arrays.asList(fDocumentPartitioningListeners.getListeners());
223     }
224
225     /**
226      * Returns all positions managed by the document grouped by category.
227      *
228      * @return the document's positions
229      */

230     protected Map JavaDoc getDocumentManagedPositions() {
231         return fPositions;
232     }
233
234     /*
235      * @see org.eclipse.jface.text.IDocument#getDocumentPartitioner()
236      */

237     public IDocumentPartitioner getDocumentPartitioner() {
238         return getDocumentPartitioner(DEFAULT_PARTITIONING);
239     }
240
241
242
243     //--- implementation configuration interface ------------
244

245     /**
246      * Sets the document's text store.
247      * Must be called at the beginning of the constructor.
248      *
249      * @param store the document's text store
250      */

251     protected void setTextStore(ITextStore store) {
252         fStore= store;
253     }
254
255     /**
256      * Sets the document's line tracker.
257      * Must be called at the beginning of the constructor.
258      *
259      * @param tracker the document's line tracker
260      */

261     protected void setLineTracker(ILineTracker tracker) {
262         fTracker= tracker;
263     }
264
265     /*
266      * @see org.eclipse.jface.text.IDocument#setDocumentPartitioner(org.eclipse.jface.text.IDocumentPartitioner)
267      */

268     public void setDocumentPartitioner(IDocumentPartitioner partitioner) {
269         setDocumentPartitioner(DEFAULT_PARTITIONING, partitioner);
270     }
271
272     /**
273      * Initializes document listeners, positions, and position updaters.
274      * Must be called inside the constructor after the implementation plug-ins
275      * have been set.
276      */

277     protected void completeInitialization() {
278
279         fPositions= new HashMap JavaDoc();
280         fPositionUpdaters= new ArrayList JavaDoc();
281         fDocumentListeners= new ListenerList();
282         fPrenotifiedDocumentListeners= new ListenerList();
283         fDocumentPartitioningListeners= new ListenerList();
284         fDocumentRewriteSessionListeners= new ArrayList JavaDoc();
285
286         addPositionCategory(DEFAULT_CATEGORY);
287         addPositionUpdater(new DefaultPositionUpdater(DEFAULT_CATEGORY));
288     }
289
290
291     //-------------------------------------------------------
292

293     /*
294      * @see org.eclipse.jface.text.IDocument#addDocumentListener(org.eclipse.jface.text.IDocumentListener)
295      */

296     public void addDocumentListener(IDocumentListener listener) {
297         Assert.isNotNull(listener);
298         fDocumentListeners.add(listener);
299     }
300
301     /*
302      * @see org.eclipse.jface.text.IDocument#removeDocumentListener(org.eclipse.jface.text.IDocumentListener)
303      */

304     public void removeDocumentListener(IDocumentListener listener) {
305         Assert.isNotNull(listener);
306         fDocumentListeners.remove(listener);
307     }
308
309     /*
310      * @see org.eclipse.jface.text.IDocument#addPrenotifiedDocumentListener(org.eclipse.jface.text.IDocumentListener)
311      */

312     public void addPrenotifiedDocumentListener(IDocumentListener listener) {
313         Assert.isNotNull(listener);
314         fPrenotifiedDocumentListeners.add(listener);
315     }
316
317     /*
318      * @see org.eclipse.jface.text.IDocument#removePrenotifiedDocumentListener(org.eclipse.jface.text.IDocumentListener)
319      */

320     public void removePrenotifiedDocumentListener(IDocumentListener listener) {
321         Assert.isNotNull(listener);
322         fPrenotifiedDocumentListeners.remove(listener);
323     }
324
325     /*
326      * @see org.eclipse.jface.text.IDocument#addDocumentPartitioningListener(org.eclipse.jface.text.IDocumentPartitioningListener)
327      */

328     public void addDocumentPartitioningListener(IDocumentPartitioningListener listener) {
329         Assert.isNotNull(listener);
330         fDocumentPartitioningListeners.add(listener);
331     }
332
333     /*
334      * @see org.eclipse.jface.text.IDocument#removeDocumentPartitioningListener(org.eclipse.jface.text.IDocumentPartitioningListener)
335      */

336     public void removeDocumentPartitioningListener(IDocumentPartitioningListener listener) {
337         Assert.isNotNull(listener);
338         fDocumentPartitioningListeners.remove(listener);
339     }
340
341     /*
342      * @see org.eclipse.jface.text.IDocument#addPosition(java.lang.String, org.eclipse.jface.text.Position)
343      */

344     public void addPosition(String JavaDoc category, Position position) throws BadLocationException, BadPositionCategoryException {
345
346         if ((0 > position.offset) || (0 > position.length) || (position.offset + position.length > getLength()))
347             throw new BadLocationException();
348
349         if (category == null)
350             throw new BadPositionCategoryException();
351
352         List JavaDoc list= (List JavaDoc) fPositions.get(category);
353         if (list == null)
354             throw new BadPositionCategoryException();
355
356         list.add(computeIndexInPositionList(list, position.offset), position);
357     }
358
359     /*
360      * @see org.eclipse.jface.text.IDocument#addPosition(org.eclipse.jface.text.Position)
361      */

362     public void addPosition(Position position) throws BadLocationException {
363         try {
364             addPosition(DEFAULT_CATEGORY, position);
365         } catch (BadPositionCategoryException e) {
366         }
367     }
368
369     /*
370      * @see org.eclipse.jface.text.IDocument#addPositionCategory(java.lang.String)
371      */

372     public void addPositionCategory(String JavaDoc category) {
373
374         if (category == null)
375             return;
376
377         if (!containsPositionCategory(category))
378             fPositions.put(category, new ArrayList JavaDoc());
379     }
380
381     /*
382      * @see org.eclipse.jface.text.IDocument#addPositionUpdater(org.eclipse.jface.text.IPositionUpdater)
383      */

384     public void addPositionUpdater(IPositionUpdater updater) {
385         insertPositionUpdater(updater, fPositionUpdaters.size());
386     }
387
388     /*
389      * @see org.eclipse.jface.text.IDocument#containsPosition(java.lang.String, int, int)
390      */

391     public boolean containsPosition(String JavaDoc category, int offset, int length) {
392
393         if (category == null)
394             return false;
395
396         List JavaDoc list= (List JavaDoc) fPositions.get(category);
397         if (list == null)
398             return false;
399
400         int size= list.size();
401         if (size == 0)
402             return false;
403
404         int index= computeIndexInPositionList(list, offset);
405         if (index < size) {
406             Position p= (Position) list.get(index);
407             while (p != null && p.offset == offset) {
408                 if (p.length == length)
409                     return true;
410                 ++ index;
411                 p= (index < size) ? (Position) list.get(index) : null;
412             }
413         }
414
415         return false;
416     }
417
418     /*
419      * @see org.eclipse.jface.text.IDocument#containsPositionCategory(java.lang.String)
420      */

421     public boolean containsPositionCategory(String JavaDoc category) {
422         if (category != null)
423             return fPositions.containsKey(category);
424         return false;
425     }
426
427
428     /**
429      * Computes the index in the list of positions at which a position with the given
430      * offset would be inserted. The position is supposed to become the first in this list
431      * of all positions with the same offset.
432      *
433      * @param positions the list in which the index is computed
434      * @param offset the offset for which the index is computed
435      * @return the computed index
436      *
437      * @see IDocument#computeIndexInCategory(String, int)
438      */

439     protected int computeIndexInPositionList(List JavaDoc positions, int offset) {
440
441         if (positions.size() == 0)
442             return 0;
443
444         int left= 0;
445         int right= positions.size() -1;
446         int mid= 0;
447         Position p= null;
448
449         while (left < right) {
450
451             mid= (left + right) / 2;
452
453             p= (Position) positions.get(mid);
454             if (offset < p.getOffset()) {
455                 if (left == mid)
456                     right= left;
457                 else
458                     right= mid -1;
459             } else if (offset > p.getOffset()) {
460                 if (right == mid)
461                     left= right;
462                 else
463                     left= mid +1;
464             } else if (offset == p.getOffset()) {
465                 left= right= mid;
466             }
467
468         }
469
470         int pos= left;
471         p= (Position) positions.get(pos);
472         if (offset > p.getOffset()) {
473             // append to the end
474
pos++;
475         } else {
476             // entry will became the first of all entries with the same offset
477
do {
478                 --pos;
479                 if (pos < 0)
480                     break;
481                 p= (Position) positions.get(pos);
482             } while (offset == p.getOffset());
483             ++pos;
484         }
485
486         Assert.isTrue(0 <= pos && pos <= positions.size());
487
488         return pos;
489     }
490
491     /*
492      * @see org.eclipse.jface.text.IDocument#computeIndexInCategory(java.lang.String, int)
493      */

494     public int computeIndexInCategory(String JavaDoc category, int offset) throws BadLocationException, BadPositionCategoryException {
495
496         if (0 > offset || offset > getLength())
497             throw new BadLocationException();
498
499         List JavaDoc c= (List JavaDoc) fPositions.get(category);
500         if (c == null)
501             throw new BadPositionCategoryException();
502
503         return computeIndexInPositionList(c, offset);
504     }
505
506     /**
507      * Fires the document partitioning changed notification to all registered
508      * document partitioning listeners. Uses a robust iterator.
509      *
510      * @deprecated as of 2.0. Use <code>fireDocumentPartitioningChanged(IRegion)</code> instead.
511      */

512     protected void fireDocumentPartitioningChanged() {
513         if (fDocumentPartitioningListeners == null)
514             return;
515         
516         Object JavaDoc[] listeners= fDocumentPartitioningListeners.getListeners();
517         for (int i= 0; i < listeners.length; i++)
518             ((IDocumentPartitioningListener)listeners[i]).documentPartitioningChanged(this);
519     }
520
521     /**
522      * Fires the document partitioning changed notification to all registered
523      * document partitioning listeners. Uses a robust iterator.
524      *
525      * @param region the region in which partitioning has changed
526      *
527      * @see IDocumentPartitioningListenerExtension
528      * @since 2.0
529      * @deprecated as of 3.0. Use
530      * <code>fireDocumentPartitioningChanged(DocumentPartitioningChangedEvent)</code>
531      * instead.
532      */

533     protected void fireDocumentPartitioningChanged(IRegion region) {
534         if (fDocumentPartitioningListeners == null)
535             return;
536         
537         Object JavaDoc[] listeners= fDocumentPartitioningListeners.getListeners();
538         for (int i= 0; i < listeners.length; i++) {
539             IDocumentPartitioningListener l= (IDocumentPartitioningListener)listeners[i];
540             if (l instanceof IDocumentPartitioningListenerExtension)
541                 ((IDocumentPartitioningListenerExtension) l).documentPartitioningChanged(this, region);
542             else
543                 l.documentPartitioningChanged(this);
544         }
545     }
546
547     /**
548      * Fires the document partitioning changed notification to all registered
549      * document partitioning listeners. Uses a robust iterator.
550      *
551      * @param event the document partitioning changed event
552      *
553      * @see IDocumentPartitioningListenerExtension2
554      * @since 3.0
555      */

556     protected void fireDocumentPartitioningChanged(DocumentPartitioningChangedEvent event) {
557         if (fDocumentPartitioningListeners == null)
558             return;
559
560         Object JavaDoc[] listeners= fDocumentPartitioningListeners.getListeners();
561         for (int i= 0; i < listeners.length; i++) {
562             IDocumentPartitioningListener l= (IDocumentPartitioningListener)listeners[i];
563             if (l instanceof IDocumentPartitioningListenerExtension2) {
564                 IDocumentPartitioningListenerExtension2 extension2= (IDocumentPartitioningListenerExtension2) l;
565                 extension2.documentPartitioningChanged(event);
566             } else if (l instanceof IDocumentPartitioningListenerExtension) {
567                 IDocumentPartitioningListenerExtension extension= (IDocumentPartitioningListenerExtension) l;
568                 extension.documentPartitioningChanged(this, event.getCoverage());
569             } else {
570                 l.documentPartitioningChanged(this);
571             }
572         }
573     }
574
575     /**
576      * Fires the given document event to all registers document listeners informing them
577      * about the forthcoming document manipulation. Uses a robust iterator.
578      *
579      * @param event the event to be sent out
580      */

581     protected void fireDocumentAboutToBeChanged(DocumentEvent event) {
582
583         // IDocumentExtension
584
if (fReentranceCount == 0)
585             flushPostNotificationChanges();
586
587         if (fDocumentPartitioners != null) {
588             Iterator JavaDoc e= fDocumentPartitioners.values().iterator();
589             while (e.hasNext()) {
590                 IDocumentPartitioner p= (IDocumentPartitioner) e.next();
591                 if (p instanceof IDocumentPartitionerExtension3) {
592                     IDocumentPartitionerExtension3 extension= (IDocumentPartitionerExtension3) p;
593                     if (extension.getActiveRewriteSession() != null)
594                         continue;
595                 }
596                 p.documentAboutToBeChanged(event);
597             }
598         }
599
600         Object JavaDoc[] listeners= fPrenotifiedDocumentListeners.getListeners();
601         for (int i= 0; i < listeners.length; i++)
602             ((IDocumentListener)listeners[i]).documentAboutToBeChanged(event);
603         
604         listeners= fDocumentListeners.getListeners();
605         for (int i= 0; i < listeners.length; i++)
606             ((IDocumentListener)listeners[i]).documentAboutToBeChanged(event);
607     }
608
609
610     /**
611      * Updates document partitioning and document positions according to the
612      * specification given by the document event.
613      *
614      * @param event the document event describing the change to which structures must be adapted
615      */

616     protected void updateDocumentStructures(DocumentEvent event) {
617
618         if (fDocumentPartitioners != null) {
619             fDocumentPartitioningChangedEvent= new DocumentPartitioningChangedEvent(this);
620             Iterator JavaDoc e= fDocumentPartitioners.keySet().iterator();
621             while (e.hasNext()) {
622                 String JavaDoc partitioning= (String JavaDoc) e.next();
623                 IDocumentPartitioner partitioner= (IDocumentPartitioner) fDocumentPartitioners.get(partitioning);
624
625                 if (partitioner instanceof IDocumentPartitionerExtension3) {
626                     IDocumentPartitionerExtension3 extension= (IDocumentPartitionerExtension3) partitioner;
627                     if (extension.getActiveRewriteSession() != null)
628                         continue;
629                 }
630
631                 if (partitioner instanceof IDocumentPartitionerExtension) {
632                     IDocumentPartitionerExtension extension= (IDocumentPartitionerExtension) partitioner;
633                     IRegion r= extension.documentChanged2(event);
634                     if (r != null)
635                         fDocumentPartitioningChangedEvent.setPartitionChange(partitioning, r.getOffset(), r.getLength());
636                 } else {
637                     if (partitioner.documentChanged(event))
638                         fDocumentPartitioningChangedEvent.setPartitionChange(partitioning, 0, event.getDocument().getLength());
639                 }
640             }
641         }
642
643         if (fPositions.size() > 0)
644             updatePositions(event);
645     }
646
647     /**
648      * Notifies all listeners about the given document change. Uses a robust
649      * iterator.
650      * <p>
651      * Executes all registered post notification replace operation.
652      *
653      * @param event the event to be sent out.
654      */

655     protected void doFireDocumentChanged(DocumentEvent event) {
656         boolean changed= fDocumentPartitioningChangedEvent != null && !fDocumentPartitioningChangedEvent.isEmpty();
657         IRegion change= changed ? fDocumentPartitioningChangedEvent.getCoverage() : null;
658         doFireDocumentChanged(event, changed, change);
659     }
660
661     /**
662      * Notifies all listeners about the given document change.
663      * Uses a robust iterator. <p>
664      * Executes all registered post notification replace operation.
665      *
666      * @param event the event to be sent out
667      * @param firePartitionChange <code>true</code> if a partition change notification should be sent
668      * @param partitionChange the region whose partitioning changed
669      * @since 2.0
670      * @deprecated as of 3.0. Use <code>doFireDocumentChanged2(DocumentEvent)</code> instead; this method will be removed.
671      */

672     protected void doFireDocumentChanged(DocumentEvent event, boolean firePartitionChange, IRegion partitionChange) {
673         doFireDocumentChanged2(event);
674     }
675
676     /**
677      * Notifies all listeners about the given document change. Uses a robust
678      * iterator.
679      * <p>
680      * Executes all registered post notification replace operation.
681      * <p>
682      * This method will be renamed to <code>doFireDocumentChanged</code>.
683      *
684      * @param event the event to be sent out
685      * @since 3.0
686      */

687     protected void doFireDocumentChanged2(DocumentEvent event) {
688
689         DocumentPartitioningChangedEvent p= fDocumentPartitioningChangedEvent;
690         fDocumentPartitioningChangedEvent= null;
691         if (p != null && !p.isEmpty())
692             fireDocumentPartitioningChanged(p);
693
694         Object JavaDoc[] listeners= fPrenotifiedDocumentListeners.getListeners();
695         for (int i= 0; i < listeners.length; i++)
696             ((IDocumentListener)listeners[i]).documentChanged(event);
697
698         listeners= fDocumentListeners.getListeners();
699         for (int i= 0; i < listeners.length; i++)
700             ((IDocumentListener)listeners[i]).documentChanged(event);
701
702         // IDocumentExtension
703
++ fReentranceCount;
704         try {
705             if (fReentranceCount == 1)
706                 executePostNotificationChanges();
707         } finally {
708             -- fReentranceCount;
709         }
710     }
711
712     /**
713      * Updates the internal document structures and informs all document listeners
714      * if listener notification has been enabled. Otherwise it remembers the event
715      * to be sent to the listeners on resume.
716      *
717      * @param event the document event to be sent out
718      */

719     protected void fireDocumentChanged(DocumentEvent event) {
720         updateDocumentStructures(event);
721
722         if (fStoppedListenerNotification == 0)
723             doFireDocumentChanged(event);
724         else
725             fDeferredDocumentEvent= event;
726     }
727
728     /*
729      * @see org.eclipse.jface.text.IDocument#getChar(int)
730      */

731     public char getChar(int pos) throws BadLocationException {
732         if ((0 > pos) || (pos >= getLength()))
733             throw new BadLocationException();
734         return getStore().get(pos);
735     }
736
737     /*
738      * @see org.eclipse.jface.text.IDocument#getContentType(int)
739      */

740     public String JavaDoc getContentType(int offset) throws BadLocationException {
741         String JavaDoc contentType= null;
742         try {
743             contentType= getContentType(DEFAULT_PARTITIONING, offset, false);
744             Assert.isNotNull(contentType);
745         } catch (BadPartitioningException e) {
746             Assert.isTrue(false);
747         }
748         return contentType;
749     }
750
751     /*
752      * @see org.eclipse.jface.text.IDocument#getLegalContentTypes()
753      */

754     public String JavaDoc[] getLegalContentTypes() {
755         String JavaDoc[] contentTypes= null;
756         try {
757             contentTypes= getLegalContentTypes(DEFAULT_PARTITIONING);
758             Assert.isNotNull(contentTypes);
759         } catch (BadPartitioningException e) {
760             Assert.isTrue(false);
761         }
762         return contentTypes;
763     }
764
765     /*
766      * @see org.eclipse.jface.text.IDocument#getLength()
767      */

768     public int getLength() {
769         return getStore().getLength();
770     }
771
772     /*
773      * @see org.eclipse.jface.text.IDocument#getLineDelimiter(int)
774      */

775     public String JavaDoc getLineDelimiter(int line) throws BadLocationException {
776         return getTracker().getLineDelimiter(line);
777     }
778
779     /*
780      * @see org.eclipse.jface.text.IDocument#getLegalLineDelimiters()
781      */

782     public String JavaDoc[] getLegalLineDelimiters() {
783         return getTracker().getLegalLineDelimiters();
784     }
785     
786     /*
787      * @see org.eclipse.jface.text.IDocumentExtension4#getDefaultLineDelimiter()
788      * @since 3.1
789      */

790     public String JavaDoc getDefaultLineDelimiter() {
791         
792         String JavaDoc lineDelimiter= null;
793         
794         try {
795             lineDelimiter= getLineDelimiter(0);
796         } catch (BadLocationException x) {
797         }
798     
799         if (lineDelimiter != null)
800             return lineDelimiter;
801
802         if (fInitialLineDelimiter != null)
803             return fInitialLineDelimiter;
804
805         String JavaDoc sysLineDelimiter= System.getProperty("line.separator"); //$NON-NLS-1$
806
String JavaDoc[] delimiters= getLegalLineDelimiters();
807         Assert.isTrue(delimiters.length > 0);
808         for (int i= 0; i < delimiters.length; i++) {
809             if (delimiters[i].equals(sysLineDelimiter)) {
810                 lineDelimiter= sysLineDelimiter;
811                 break;
812             }
813         }
814         
815         if (lineDelimiter == null)
816             lineDelimiter= delimiters[0];
817     
818         return lineDelimiter;
819         
820     }
821     
822     /*
823      * @see org.eclipse.jface.text.IDocumentExtension4#setInitialLineDelimiter(java.lang.String)
824      * @since 3.1
825      */

826     public void setInitialLineDelimiter(String JavaDoc lineDelimiter) {
827         Assert.isNotNull(lineDelimiter);
828         fInitialLineDelimiter= lineDelimiter;
829     }
830
831     /*
832      * @see org.eclipse.jface.text.IDocument#getLineLength(int)
833      */

834     public int getLineLength(int line) throws BadLocationException {
835         return getTracker().getLineLength(line);
836     }
837
838     /*
839      * @see org.eclipse.jface.text.IDocument#getLineOfOffset(int)
840      */

841     public int getLineOfOffset(int pos) throws BadLocationException {
842         return getTracker().getLineNumberOfOffset(pos);
843     }
844
845     /*
846      * @see org.eclipse.jface.text.IDocument#getLineOffset(int)
847      */

848     public int getLineOffset(int line) throws BadLocationException {
849         return getTracker().getLineOffset(line);
850     }
851
852     /*
853      * @see org.eclipse.jface.text.IDocument#getLineInformation(int)
854      */

855     public IRegion getLineInformation(int line) throws BadLocationException {
856         return getTracker().getLineInformation(line);
857     }
858
859     /*
860      * @see org.eclipse.jface.text.IDocument#getLineInformationOfOffset(int)
861      */

862     public IRegion getLineInformationOfOffset(int offset) throws BadLocationException {
863         return getTracker().getLineInformationOfOffset(offset);
864     }
865
866     /*
867      * @see org.eclipse.jface.text.IDocument#getNumberOfLines()
868      */

869     public int getNumberOfLines() {
870         return getTracker().getNumberOfLines();
871     }
872
873     /*
874      * @see org.eclipse.jface.text.IDocument#getNumberOfLines(int, int)
875      */

876     public int getNumberOfLines(int offset, int length) throws BadLocationException {
877         return getTracker().getNumberOfLines(offset, length);
878     }
879
880     /*
881      * @see org.eclipse.jface.text.IDocument#computeNumberOfLines(java.lang.String)
882      */

883     public int computeNumberOfLines(String JavaDoc text) {
884         return getTracker().computeNumberOfLines(text);
885     }
886
887     /*
888      * @see org.eclipse.jface.text.IDocument#getPartition(int)
889      */

890     public ITypedRegion getPartition(int offset) throws BadLocationException {
891         ITypedRegion partition= null;
892         try {
893             partition= getPartition(DEFAULT_PARTITIONING, offset, false);
894             Assert.isNotNull(partition);
895         } catch (BadPartitioningException e) {
896             Assert.isTrue(false);
897         }
898         return partition;
899     }
900
901     /*
902      * @see org.eclipse.jface.text.IDocument#computePartitioning(int, int)
903      */

904     public ITypedRegion[] computePartitioning(int offset, int length) throws BadLocationException {
905         ITypedRegion[] partitioning= null;
906         try {
907             partitioning= computePartitioning(DEFAULT_PARTITIONING, offset, length, false);
908             Assert.isNotNull(partitioning);
909         } catch (BadPartitioningException e) {
910             Assert.isTrue(false);
911         }
912         return partitioning;
913     }
914
915     /*
916      * @see org.eclipse.jface.text.IDocument#getPositions(java.lang.String)
917      */

918     public Position[] getPositions(String JavaDoc category) throws BadPositionCategoryException {
919
920         if (category == null)
921             throw new BadPositionCategoryException();
922
923         List JavaDoc c= (List JavaDoc) fPositions.get(category);
924         if (c == null)
925             throw new BadPositionCategoryException();
926
927         Position[] positions= new Position[c.size()];
928         c.toArray(positions);
929         return positions;
930     }
931
932     /*
933      * @see org.eclipse.jface.text.IDocument#getPositionCategories()
934      */

935     public String JavaDoc[] getPositionCategories() {
936         String JavaDoc[] categories= new String JavaDoc[fPositions.size()];
937         Iterator JavaDoc keys= fPositions.keySet().iterator();
938         for (int i= 0; i < categories.length; i++)
939             categories[i]= (String JavaDoc) keys.next();
940         return categories;
941     }
942
943     /*
944      * @see org.eclipse.jface.text.IDocument#getPositionUpdaters()
945      */

946     public IPositionUpdater[] getPositionUpdaters() {
947         IPositionUpdater[] updaters= new IPositionUpdater[fPositionUpdaters.size()];
948         fPositionUpdaters.toArray(updaters);
949         return updaters;
950     }
951
952     /*
953      * @see org.eclipse.jface.text.IDocument#get()
954      */

955     public String JavaDoc get() {
956         return getStore().get(0, getLength());
957     }
958
959     /*
960      * @see org.eclipse.jface.text.IDocument#get(int, int)
961      */

962     public String JavaDoc get(int pos, int length) throws BadLocationException {
963         int myLength= getLength();
964         if ((0 > pos) || (0 > length) || (pos + length > myLength))
965             throw new BadLocationException();
966         return getStore().get(pos, length);
967     }
968
969     /*
970      * @see org.eclipse.jface.text.IDocument#insertPositionUpdater(org.eclipse.jface.text.IPositionUpdater, int)
971      */

972     public void insertPositionUpdater(IPositionUpdater updater, int index) {
973
974         for (int i= fPositionUpdaters.size() - 1; i >= 0; i--) {
975             if (fPositionUpdaters.get(i) == updater)
976                 return;
977         }
978
979         if (index == fPositionUpdaters.size())
980             fPositionUpdaters.add(updater);
981         else
982             fPositionUpdaters.add(index, updater);
983     }
984
985     /*
986      * @see org.eclipse.jface.text.IDocument#removePosition(java.lang.String, org.eclipse.jface.text.Position)
987      */

988     public void removePosition(String JavaDoc category, Position position) throws BadPositionCategoryException {
989
990         if (position == null)
991             return;
992
993         if (category == null)
994             throw new BadPositionCategoryException();
995
996         List JavaDoc c= (List JavaDoc) fPositions.get(category);
997         if (c == null)
998             throw new BadPositionCategoryException();
999
1000        // remove based on identity not equality
1001
int size= c.size();
1002        for (int i= 0; i < size; i++) {
1003            if (position == c.get(i)) {
1004                c.remove(i);
1005                return;
1006            }
1007        }
1008    }
1009
1010    /*
1011     * @see org.eclipse.jface.text.IDocument#removePosition(org.eclipse.jface.text.Position)
1012     */

1013    public void removePosition(Position position) {
1014        try {
1015            removePosition(DEFAULT_CATEGORY, position);
1016        } catch (BadPositionCategoryException e) {
1017        }
1018    }
1019
1020    /*
1021     * @see org.eclipse.jface.text.IDocument#removePositionCategory(java.lang.String)
1022     */

1023    public void removePositionCategory(String JavaDoc category) throws BadPositionCategoryException {
1024
1025        if (category == null)
1026            return;
1027
1028        if ( !containsPositionCategory(category))
1029            throw new BadPositionCategoryException();
1030
1031        fPositions.remove(category);
1032    }
1033
1034    /*
1035     * @see org.eclipse.jface.text.IDocument#removePositionUpdater(org.eclipse.jface.text.IPositionUpdater)
1036     */

1037    public void removePositionUpdater(IPositionUpdater updater) {
1038        for (int i= fPositionUpdaters.size() - 1; i >= 0; i--) {
1039            if (fPositionUpdaters.get(i) == updater) {
1040                fPositionUpdaters.remove(i);
1041                return;
1042            }
1043        }
1044    }
1045
1046    private long getNextModificationStamp() {
1047        if (fNextModificationStamp == Long.MAX_VALUE || fNextModificationStamp == IDocumentExtension4.UNKNOWN_MODIFICATION_STAMP)
1048            fNextModificationStamp= 0;
1049        else
1050            fNextModificationStamp= fNextModificationStamp + 1;
1051
1052        return fNextModificationStamp;
1053    }
1054
1055    /*
1056     * @see org.eclipse.jface.text.IDocumentExtension4#getModificationStamp()
1057     * @since 3.1
1058     */

1059    public long getModificationStamp() {
1060        return fModificationStamp;
1061    }
1062
1063    /*
1064     * @see org.eclipse.jface.text.IDocument#replace(int, int, java.lang.String)
1065     * @since 3.1
1066     */

1067    public void replace(int pos, int length, String JavaDoc text, long modificationStamp) throws BadLocationException {
1068        if ((0 > pos) || (0 > length) || (pos + length > getLength()))
1069            throw new BadLocationException();
1070
1071        DocumentEvent e= new DocumentEvent(this, pos, length, text);
1072        fireDocumentAboutToBeChanged(e);
1073
1074        getStore().replace(pos, length, text);
1075        getTracker().replace(pos, length, text);
1076
1077        fModificationStamp= modificationStamp;
1078        fNextModificationStamp= Math.max(fModificationStamp, fNextModificationStamp);
1079        e.fModificationStamp= fModificationStamp;
1080
1081        fireDocumentChanged(e);
1082    }
1083
1084    /*
1085     * @see org.eclipse.jface.text.IDocument#replace(int, int, java.lang.String)
1086     */

1087    public void replace(int pos, int length, String JavaDoc text) throws BadLocationException {
1088        if (length == 0 && (text == null || text.length() == 0))
1089            replace(pos, length, text, getModificationStamp());
1090        else
1091            replace(pos, length, text, getNextModificationStamp());
1092    }
1093
1094    /*
1095     * @see org.eclipse.jface.text.IDocument#set(java.lang.String)
1096     */

1097    public void set(String JavaDoc text) {
1098        set(text, getNextModificationStamp());
1099    }
1100    
1101    /*
1102     * @see org.eclipse.jface.text.IDocument#set(java.lang.String, long)
1103     */

1104    public void set(String JavaDoc text, long modificationStamp) {
1105        int length= getStore().getLength();
1106
1107        DocumentEvent e= new DocumentEvent(this, 0, length, text);
1108        fireDocumentAboutToBeChanged(e);
1109
1110        getStore().set(text);
1111        getTracker().set(text);
1112
1113        fModificationStamp= modificationStamp;
1114        fNextModificationStamp= Math.max(fModificationStamp, fNextModificationStamp);
1115        e.fModificationStamp= fModificationStamp;
1116
1117        fireDocumentChanged(e);
1118    }
1119
1120    /**
1121     * Updates all positions of all categories to the change described by the
1122     * document event. All registered document updaters are called in the
1123     * sequence they have been arranged. Uses a robust iterator.
1124     *
1125     * @param event the document event describing the change to which to adapt
1126     * the positions
1127     */

1128    protected void updatePositions(DocumentEvent event) {
1129        List JavaDoc list= new ArrayList JavaDoc(fPositionUpdaters);
1130        Iterator JavaDoc e= list.iterator();
1131        while (e.hasNext()) {
1132            IPositionUpdater u= (IPositionUpdater) e.next();
1133            u.update(event);
1134        }
1135    }
1136
1137    /*
1138     * @see org.eclipse.jface.text.IDocument#search(int, java.lang.String, boolean, boolean, boolean)
1139     */

1140    public int search(int startPosition, String JavaDoc findString, boolean forwardSearch, boolean caseSensitive, boolean wholeWord) throws BadLocationException {
1141        try {
1142            IRegion region= getFindReplaceDocumentAdapter().find(startPosition, findString, forwardSearch, caseSensitive, wholeWord, false);
1143            return region == null ? -1 : region.getOffset();
1144        } catch (IllegalStateException JavaDoc ex) {
1145            return -1;
1146        } catch (PatternSyntaxException JavaDoc ex) {
1147            return -1;
1148        }
1149    }
1150
1151    /**
1152     * Returns the find/replace adapter for this document.
1153     *
1154     * @return this document's find/replace document adapter
1155     * @since 3.0
1156     */

1157    private FindReplaceDocumentAdapter getFindReplaceDocumentAdapter() {
1158        if (fFindReplaceDocumentAdapter == null)
1159            fFindReplaceDocumentAdapter= new FindReplaceDocumentAdapter(this);
1160
1161        return fFindReplaceDocumentAdapter;
1162    }
1163
1164    /**
1165     * Flushes all registered post notification changes.
1166     *
1167     * @since 2.0
1168     */

1169    private void flushPostNotificationChanges() {
1170        if (fPostNotificationChanges != null)
1171            fPostNotificationChanges.clear();
1172    }
1173
1174    /**
1175     * Executes all registered post notification changes. The process is
1176     * repeated until no new post notification changes are added.
1177     *
1178     * @since 2.0
1179     */

1180    private void executePostNotificationChanges() {
1181
1182        if (fStoppedCount > 0)
1183            return;
1184
1185        while (fPostNotificationChanges != null) {
1186            List JavaDoc changes= fPostNotificationChanges;
1187            fPostNotificationChanges= null;
1188
1189            Iterator JavaDoc e= changes.iterator();
1190            while (e.hasNext()) {
1191                RegisteredReplace replace= (RegisteredReplace) e.next();
1192                replace.fReplace.perform(this, replace.fOwner);
1193            }
1194        }
1195    }
1196
1197    /*
1198     * @see org.eclipse.jface.text.IDocumentExtension2#acceptPostNotificationReplaces()
1199     * @since 2.1
1200     */

1201    public void acceptPostNotificationReplaces() {
1202        fAcceptPostNotificationReplaces= true;
1203    }
1204
1205    /*
1206     * @see org.eclipse.jface.text.IDocumentExtension2#ignorePostNotificationReplaces()
1207     * @since 2.1
1208     */

1209    public void ignorePostNotificationReplaces() {
1210        fAcceptPostNotificationReplaces= false;
1211    }
1212
1213    /*
1214     * @see org.eclipse.jface.text.IDocumentExtension#registerPostNotificationReplace(org.eclipse.jface.text.IDocumentListener, org.eclipse.jface.text.IDocumentExtension.IReplace)
1215     * @since 2.0
1216     */

1217    public void registerPostNotificationReplace(IDocumentListener owner, IDocumentExtension.IReplace replace) {
1218        if (fAcceptPostNotificationReplaces) {
1219            if (fPostNotificationChanges == null)
1220                fPostNotificationChanges= new ArrayList JavaDoc(1);
1221            fPostNotificationChanges.add(new RegisteredReplace(owner, replace));
1222        }
1223    }
1224
1225    /*
1226     * @see org.eclipse.jface.text.IDocumentExtension#stopPostNotificationProcessing()
1227     * @since 2.0
1228     */

1229    public void stopPostNotificationProcessing() {
1230        ++ fStoppedCount;
1231    }
1232
1233    /*
1234     * @see org.eclipse.jface.text.IDocumentExtension#resumePostNotificationProcessing()
1235     * @since 2.0
1236     */

1237    public void resumePostNotificationProcessing() {
1238        -- fStoppedCount;
1239        if (fStoppedCount == 0 && fReentranceCount == 0)
1240            executePostNotificationChanges();
1241    }
1242
1243    /*
1244     * @see org.eclipse.jface.text.IDocumentExtension#startSequentialRewrite(boolean)
1245     * @since 2.0
1246     */

1247    public void startSequentialRewrite(boolean normalized) {
1248    }
1249
1250    /*
1251     * @see org.eclipse.jface.text.IDocumentExtension#stopSequentialRewrite()
1252     * @since 2.0
1253     */

1254    public void stopSequentialRewrite() {
1255    }
1256
1257    /*
1258     * @see org.eclipse.jface.text.IDocumentExtension2#resumeListenerNotification()
1259     * @since 2.1
1260     */

1261    public void resumeListenerNotification() {
1262        -- fStoppedListenerNotification;
1263        if (fStoppedListenerNotification == 0) {
1264            resumeDocumentListenerNotification();
1265        }
1266    }
1267
1268    /*
1269     * @see org.eclipse.jface.text.IDocumentExtension2#stopListenerNotification()
1270     * @since 2.1
1271     */

1272    public void stopListenerNotification() {
1273        ++ fStoppedListenerNotification;
1274    }
1275
1276    /**
1277     * Resumes the document listener notification by sending out the remembered
1278     * partition changed and document event.
1279     *
1280     * @since 2.1
1281     */

1282    private void resumeDocumentListenerNotification() {
1283        if (fDeferredDocumentEvent != null) {
1284            DocumentEvent event= fDeferredDocumentEvent;
1285            fDeferredDocumentEvent= null;
1286            doFireDocumentChanged(event);
1287        }
1288    }
1289
1290    /*
1291     * @see org.eclipse.jface.text.IDocumentExtension3#computeZeroLengthPartitioning(java.lang.String, int, int)
1292     * @since 3.0
1293     */

1294    public ITypedRegion[] computePartitioning(String JavaDoc partitioning, int offset, int length, boolean includeZeroLengthPartitions) throws BadLocationException, BadPartitioningException {
1295        if ((0 > offset) || (0 > length) || (offset + length > getLength()))
1296            throw new BadLocationException();
1297
1298        IDocumentPartitioner partitioner= getDocumentPartitioner(partitioning);
1299
1300        if (partitioner instanceof IDocumentPartitionerExtension2) {
1301            checkStateOfPartitioner(partitioner, partitioning);
1302            return ((IDocumentPartitionerExtension2) partitioner).computePartitioning(offset, length, includeZeroLengthPartitions);
1303        } else if (partitioner != null) {
1304            checkStateOfPartitioner(partitioner, partitioning);
1305            return partitioner.computePartitioning(offset, length);
1306        } else if (DEFAULT_PARTITIONING.equals(partitioning))
1307            return new TypedRegion[] { new TypedRegion(offset, length, DEFAULT_CONTENT_TYPE) };
1308        else
1309            throw new BadPartitioningException();
1310    }
1311
1312    /*
1313     * @see org.eclipse.jface.text.IDocumentExtension3#getZeroLengthContentType(java.lang.String, int)
1314     * @since 3.0
1315     */

1316    public String JavaDoc getContentType(String JavaDoc partitioning, int offset, boolean preferOpenPartitions) throws BadLocationException, BadPartitioningException {
1317        if ((0 > offset) || (offset > getLength()))
1318            throw new BadLocationException();
1319
1320        IDocumentPartitioner partitioner= getDocumentPartitioner(partitioning);
1321
1322        if (partitioner instanceof IDocumentPartitionerExtension2) {
1323            checkStateOfPartitioner(partitioner, partitioning);
1324            return ((IDocumentPartitionerExtension2) partitioner).getContentType(offset, preferOpenPartitions);
1325        } else if (partitioner != null) {
1326            checkStateOfPartitioner(partitioner, partitioning);
1327            return partitioner.getContentType(offset);
1328        } else if (DEFAULT_PARTITIONING.equals(partitioning))
1329            return DEFAULT_CONTENT_TYPE;
1330        else
1331            throw new BadPartitioningException();
1332    }
1333
1334    /*
1335     * @see org.eclipse.jface.text.IDocumentExtension3#getDocumentPartitioner(java.lang.String)
1336     * @since 3.0
1337     */

1338    public IDocumentPartitioner getDocumentPartitioner(String JavaDoc partitioning) {
1339        return fDocumentPartitioners != null ? (IDocumentPartitioner) fDocumentPartitioners.get(partitioning) : null;
1340    }
1341
1342    /*
1343     * @see org.eclipse.jface.text.IDocumentExtension3#getLegalContentTypes(java.lang.String)
1344     * @since 3.0
1345     */

1346    public String JavaDoc[] getLegalContentTypes(String JavaDoc partitioning) throws BadPartitioningException {
1347        IDocumentPartitioner partitioner= getDocumentPartitioner(partitioning);
1348        if (partitioner != null)
1349            return partitioner.getLegalContentTypes();
1350        if (DEFAULT_PARTITIONING.equals(partitioning))
1351            return new String JavaDoc[] { DEFAULT_CONTENT_TYPE };
1352        throw new BadPartitioningException();
1353    }
1354
1355    /*
1356     * @see org.eclipse.jface.text.IDocumentExtension3#getZeroLengthPartition(java.lang.String, int)
1357     * @since 3.0
1358     */

1359    public ITypedRegion getPartition(String JavaDoc partitioning, int offset, boolean preferOpenPartitions) throws BadLocationException, BadPartitioningException {
1360        if ((0 > offset) || (offset > getLength()))
1361            throw new BadLocationException();
1362
1363        IDocumentPartitioner partitioner= getDocumentPartitioner(partitioning);
1364
1365        if (partitioner instanceof IDocumentPartitionerExtension2) {
1366            checkStateOfPartitioner(partitioner, partitioning);
1367            return ((IDocumentPartitionerExtension2) partitioner).getPartition(offset, preferOpenPartitions);
1368        } else if (partitioner != null) {
1369            checkStateOfPartitioner(partitioner, partitioning);
1370            return partitioner.getPartition(offset);
1371        } else if (DEFAULT_PARTITIONING.equals(partitioning))
1372            return new TypedRegion(0, getLength(), DEFAULT_CONTENT_TYPE);
1373        else
1374            throw new BadPartitioningException();
1375    }
1376
1377    /*
1378     * @see org.eclipse.jface.text.IDocumentExtension3#getPartitionings()
1379     * @since 3.0
1380     */

1381    public String JavaDoc[] getPartitionings() {
1382        if (fDocumentPartitioners == null)
1383            return new String JavaDoc[0];
1384        String JavaDoc[] partitionings= new String JavaDoc[fDocumentPartitioners.size()];
1385        fDocumentPartitioners.keySet().toArray(partitionings);
1386        return partitionings;
1387    }
1388
1389    /*
1390     * @see org.eclipse.jface.text.IDocumentExtension3#setDocumentPartitioner(java.lang.String, org.eclipse.jface.text.IDocumentPartitioner)
1391     * @since 3.0
1392     */

1393    public void setDocumentPartitioner(String JavaDoc partitioning, IDocumentPartitioner partitioner) {
1394        if (partitioner == null) {
1395            if (fDocumentPartitioners != null) {
1396                fDocumentPartitioners.remove(partitioning);
1397                if (fDocumentPartitioners.size() == 0)
1398                    fDocumentPartitioners= null;
1399            }
1400        } else {
1401            if (fDocumentPartitioners == null)
1402                fDocumentPartitioners= new HashMap JavaDoc();
1403            fDocumentPartitioners.put(partitioning, partitioner);
1404        }
1405        DocumentPartitioningChangedEvent event= new DocumentPartitioningChangedEvent(this);
1406        event.setPartitionChange(partitioning, 0, getLength());
1407        fireDocumentPartitioningChanged(event);
1408    }
1409
1410    /*
1411     * @see org.eclipse.jface.text.IRepairableDocument#repairLineInformation()
1412     * @since 3.0
1413     */

1414    public void repairLineInformation() {
1415        getTracker().set(get());
1416    }
1417
1418    /**
1419     * Fires the given event to all registered rewrite session listeners. Uses robust iterators.
1420     *
1421     * @param event the event to be fired
1422     * @since 3.1
1423     */

1424    protected void fireRewriteSessionChanged(DocumentRewriteSessionEvent event) {
1425        if (fDocumentRewriteSessionListeners.size() > 0) {
1426            List JavaDoc list= new ArrayList JavaDoc(fDocumentRewriteSessionListeners);
1427            Iterator JavaDoc e= list.iterator();
1428            while (e.hasNext()) {
1429                IDocumentRewriteSessionListener l= (IDocumentRewriteSessionListener) e.next();
1430                l.documentRewriteSessionChanged(event);
1431            }
1432        }
1433    }
1434
1435    /*
1436     * @see org.eclipse.jface.text.IDocumentExtension4#getActiveRewriteSession()
1437     */

1438    public final DocumentRewriteSession getActiveRewriteSession() {
1439        return fDocumentRewriteSession;
1440    }
1441
1442    /*
1443     * @see org.eclipse.jface.text.IDocumentExtension4#startRewriteSession(org.eclipse.jface.text.DocumentRewriteSessionType)
1444     * @since 3.1
1445     */

1446    public DocumentRewriteSession startRewriteSession(DocumentRewriteSessionType sessionType) {
1447
1448        if (getActiveRewriteSession() != null)
1449            throw new IllegalStateException JavaDoc();
1450
1451
1452        fDocumentRewriteSession= new DocumentRewriteSession(sessionType);
1453        if (DEBUG)
1454            System.out.println("AbstractDocument: Starting rewrite session: " + fDocumentRewriteSession); //$NON-NLS-1$
1455

1456        fireRewriteSessionChanged(new DocumentRewriteSessionEvent(this, fDocumentRewriteSession, DocumentRewriteSessionEvent.SESSION_START));
1457
1458        startRewriteSessionOnPartitioners(fDocumentRewriteSession);
1459
1460        ILineTracker tracker= getTracker();
1461        if (tracker instanceof ILineTrackerExtension) {
1462            ILineTrackerExtension extension= (ILineTrackerExtension) tracker;
1463            extension.startRewriteSession(fDocumentRewriteSession);
1464        }
1465
1466        if (DocumentRewriteSessionType.SEQUENTIAL == sessionType)
1467            startSequentialRewrite(false);
1468        else if (DocumentRewriteSessionType.STRICTLY_SEQUENTIAL == sessionType)
1469            startSequentialRewrite(true);
1470
1471        return fDocumentRewriteSession;
1472    }
1473
1474    /**
1475     * Starts the given rewrite session.
1476     *
1477     * @param session the rewrite session
1478     * @since 3.1
1479     */

1480    protected final void startRewriteSessionOnPartitioners(DocumentRewriteSession session) {
1481        if (fDocumentPartitioners != null) {
1482            Iterator JavaDoc e= fDocumentPartitioners.values().iterator();
1483            while (e.hasNext()) {
1484                Object JavaDoc partitioner= e.next();
1485                if (partitioner instanceof IDocumentPartitionerExtension3) {
1486                    IDocumentPartitionerExtension3 extension= (IDocumentPartitionerExtension3) partitioner;
1487                    extension.startRewriteSession(session);
1488                }
1489            }
1490        }
1491    }
1492
1493    /*
1494     * @see org.eclipse.jface.text.IDocumentExtension4#stopRewriteSession(org.eclipse.jface.text.DocumentRewriteSession)
1495     * @since 3.1
1496     */

1497    public void stopRewriteSession(DocumentRewriteSession session) {
1498        if (fDocumentRewriteSession == session) {
1499
1500            if (DEBUG)
1501                System.out.println("AbstractDocument: Stopping rewrite session: " + session); //$NON-NLS-1$
1502

1503            DocumentRewriteSessionType sessionType= session.getSessionType();
1504            if (DocumentRewriteSessionType.SEQUENTIAL == sessionType || DocumentRewriteSessionType.STRICTLY_SEQUENTIAL == sessionType)
1505                stopSequentialRewrite();
1506
1507            ILineTracker tracker= getTracker();
1508            if (tracker instanceof ILineTrackerExtension) {
1509                ILineTrackerExtension extension= (ILineTrackerExtension) tracker;
1510                extension.stopRewriteSession(session, get());
1511            }
1512
1513            stopRewriteSessionOnPartitioners(fDocumentRewriteSession);
1514
1515            fDocumentRewriteSession= null;
1516            fireRewriteSessionChanged(new DocumentRewriteSessionEvent(this, session, DocumentRewriteSessionEvent.SESSION_STOP));
1517        }
1518    }
1519
1520    /**
1521     * Stops the given rewrite session.
1522     *
1523     * @param session the rewrite session
1524     * @since 3.1
1525     */

1526    protected final void stopRewriteSessionOnPartitioners(DocumentRewriteSession session) {
1527        if (fDocumentPartitioners != null) {
1528            DocumentPartitioningChangedEvent event= new DocumentPartitioningChangedEvent(this);
1529            Iterator JavaDoc e= fDocumentPartitioners.keySet().iterator();
1530            while (e.hasNext()) {
1531                String JavaDoc partitioning= (String JavaDoc) e.next();
1532                IDocumentPartitioner partitioner= (IDocumentPartitioner) fDocumentPartitioners.get(partitioning);
1533                if (partitioner instanceof IDocumentPartitionerExtension3) {
1534                    IDocumentPartitionerExtension3 extension= (IDocumentPartitionerExtension3) partitioner;
1535                    extension.stopRewriteSession(session);
1536                    event.setPartitionChange(partitioning, 0, getLength());
1537                }
1538            }
1539            if (!event.isEmpty())
1540                fireDocumentPartitioningChanged(event);
1541        }
1542    }
1543
1544    /*
1545     * @see org.eclipse.jface.text.IDocumentExtension4#addDocumentRewriteSessionListener(org.eclipse.jface.text.IDocumentRewriteSessionListener)
1546     * @since 3.1
1547     */

1548    public void addDocumentRewriteSessionListener(IDocumentRewriteSessionListener listener) {
1549        Assert.isNotNull(listener);
1550        if (! fDocumentRewriteSessionListeners.contains(listener))
1551            fDocumentRewriteSessionListeners.add(listener);
1552    }
1553
1554    /*
1555     * @see org.eclipse.jface.text.IDocumentExtension4#removeDocumentRewriteSessionListener(org.eclipse.jface.text.IDocumentRewriteSessionListener)
1556     * @since 3.1
1557     */

1558    public void removeDocumentRewriteSessionListener(IDocumentRewriteSessionListener listener) {
1559        Assert.isNotNull(listener);
1560        fDocumentRewriteSessionListeners.remove(listener);
1561    }
1562
1563    /**
1564     * Checks the state for the given partitioner and stops the
1565     * active rewrite session.
1566     *
1567     * @param partitioner the document partitioner to be checked
1568     * @param partitioning the document partitioning the partitioner is registered for
1569     * @since 3.1
1570     */

1571    protected final void checkStateOfPartitioner(IDocumentPartitioner partitioner, String JavaDoc partitioning) {
1572        if (!(partitioner instanceof IDocumentPartitionerExtension3))
1573            return;
1574
1575        IDocumentPartitionerExtension3 extension= (IDocumentPartitionerExtension3) partitioner;
1576        DocumentRewriteSession session= extension.getActiveRewriteSession();
1577        if (session != null) {
1578            extension.stopRewriteSession(session);
1579
1580            if (DEBUG)
1581                System.out.println("AbstractDocument: Flushing rewrite session for partition type: " + partitioning); //$NON-NLS-1$
1582

1583            DocumentPartitioningChangedEvent event= new DocumentPartitioningChangedEvent(this);
1584            event.setPartitionChange(partitioning, 0, getLength());
1585            fireDocumentPartitioningChanged(event);
1586        }
1587    }
1588}
1589
Popular Tags