]> gerrit.simantics Code Review - simantics/platform.git/blob - bundles/org.simantics.scl.ui/src/org/simantics/scl/ui/editor2/iterator/DocumentCharacterIterator.java
Fixed multiple issues causing dangling references to discarded queries
[simantics/platform.git] / bundles / org.simantics.scl.ui / src / org / simantics / scl / ui / editor2 / iterator / DocumentCharacterIterator.java
1 package org.simantics.scl.ui.editor2.iterator;
2
3 import java.text.CharacterIterator;
4
5 import org.eclipse.core.runtime.Assert;
6
7 import org.eclipse.jface.text.BadLocationException;
8 import org.eclipse.jface.text.IDocument;
9
10
11 /**
12  * An <code>IDocument</code> based implementation of
13  * <code>CharacterIterator</code> and <code>CharSequence</code>. Note that
14  * the supplied document is not copied; if the document is modified during the
15  * lifetime of a <code>DocumentCharacterIterator</code>, the methods
16  * returning document content may not always return the same values. Also, if
17  * accessing the document fails with a {@link BadLocationException}, any of
18  * <code>CharacterIterator</code> methods as well as <code>charAt</code>may
19  * return {@link CharacterIterator#DONE}.
20  *
21  * @since 3.0
22  */
23 public class DocumentCharacterIterator implements CharacterIterator, CharSequence {
24
25         private int fIndex= -1;
26         private final IDocument fDocument;
27         private final int fFirst;
28         private final int fLast;
29
30         private void invariant() {
31                 Assert.isTrue(fIndex >= fFirst);
32                 Assert.isTrue(fIndex <= fLast);
33         }
34
35         /**
36          * Creates an iterator for the entire document.
37          * 
38          * @param document the document backing this iterator
39          * @throws BadLocationException if the indices are out of bounds
40          */
41         public DocumentCharacterIterator(IDocument document) throws BadLocationException {
42                 this(document, 0);
43         }
44
45         /**
46          * Creates an iterator, starting at offset <code>first</code>.
47          * 
48          * @param document the document backing this iterator
49          * @param first the first character to consider
50          * @throws BadLocationException if the indices are out of bounds
51          */
52         public DocumentCharacterIterator(IDocument document, int first) throws BadLocationException {
53                 this(document, first, document.getLength());
54         }
55
56         /**
57          * Creates an iterator for the document contents from <code>first</code> (inclusive) to
58          * <code>last</code> (exclusive).
59          * 
60          * @param document the document backing this iterator
61          * @param first the first character to consider
62          * @param last the last character index to consider
63          * @throws BadLocationException if the indices are out of bounds
64          */
65         public DocumentCharacterIterator(IDocument document, int first, int last) throws BadLocationException {
66                 if (document == null)
67                         throw new NullPointerException();
68                 if (first < 0 || first > last)
69                         throw new BadLocationException();
70                 if (last > document.getLength()) {
71                         throw new BadLocationException();
72                 }
73                 fDocument= document;
74                 fFirst= first;
75                 fLast= last;
76                 fIndex= first;
77                 invariant();
78         }
79
80         /*
81          * @see java.text.CharacterIterator#first()
82          */
83         public char first() {
84                 return setIndex(getBeginIndex());
85         }
86
87         /*
88          * @see java.text.CharacterIterator#last()
89          */
90         public char last() {
91                 if (fFirst == fLast)
92                         return setIndex(getEndIndex());
93                 else
94                         return setIndex(getEndIndex() - 1);
95         }
96
97         /*
98          * @see java.text.CharacterIterator#current()
99          */
100         public char current() {
101                 if (fIndex >= fFirst && fIndex < fLast)
102                         try {
103                                 return fDocument.getChar(fIndex);
104                         } catch (BadLocationException e) {
105                                 // ignore
106                         }
107                 return DONE;
108         }
109
110         /*
111          * @see java.text.CharacterIterator#next()
112          */
113         public char next() {
114                 return setIndex(Math.min(fIndex + 1, getEndIndex()));
115         }
116
117         /*
118          * @see java.text.CharacterIterator#previous()
119          */
120         public char previous() {
121                 if (fIndex > getBeginIndex()) {
122                         return setIndex(fIndex - 1);
123                 } else {
124                         return DONE;
125                 }
126         }
127
128         /*
129          * @see java.text.CharacterIterator#setIndex(int)
130          */
131         public char setIndex(int position) {
132                 if (position >= getBeginIndex() && position <= getEndIndex())
133                         fIndex= position;
134                 else
135                         throw new IllegalArgumentException();
136
137                 invariant();
138                 return current();
139         }
140
141         /*
142          * @see java.text.CharacterIterator#getBeginIndex()
143          */
144         public int getBeginIndex() {
145                 return fFirst;
146         }
147
148         /*
149          * @see java.text.CharacterIterator#getEndIndex()
150          */
151         public int getEndIndex() {
152                 return fLast;
153         }
154
155         /*
156          * @see java.text.CharacterIterator#getIndex()
157          */
158         public int getIndex() {
159                 return fIndex;
160         }
161
162         /*
163          * @see java.text.CharacterIterator#clone()
164          */
165         @Override
166         public Object clone() {
167                 try {
168                         return super.clone();
169                 } catch (CloneNotSupportedException e) {
170                         throw new InternalError();
171                 }
172         }
173
174         /*
175          * @see java.lang.CharSequence#length()
176          */
177         public int length() {
178                 return getEndIndex() - getBeginIndex();
179         }
180
181         /**
182          * {@inheritDoc}
183          * <p>
184          * Note that, if the document is modified concurrently, this method may
185          * return {@link CharacterIterator#DONE} if a {@link BadLocationException}
186          * was thrown when accessing the backing document.
187          * </p>
188          *
189          * @param index {@inheritDoc}
190          * @return {@inheritDoc}
191          */
192         public char charAt(int index) {
193                 if (index >= 0 && index < length())
194                         try {
195                                 return fDocument.getChar(getBeginIndex() + index);
196                         } catch (BadLocationException e) {
197                                 // ignore and return DONE
198                                 return DONE;
199                         }
200                 else
201                         throw new IndexOutOfBoundsException();
202         }
203
204         /*
205          * @see java.lang.CharSequence#subSequence(int, int)
206          */
207         public CharSequence subSequence(int start, int end) {
208                 if (start < 0)
209                         throw new IndexOutOfBoundsException();
210                 if (end < start)
211                         throw new IndexOutOfBoundsException();
212                 if (end > length())
213                         throw new IndexOutOfBoundsException();
214                 try {
215                         return new DocumentCharacterIterator(fDocument, getBeginIndex() + start, getBeginIndex() + end);
216                 } catch (BadLocationException ex) {
217                         throw new IndexOutOfBoundsException();
218                 }
219         }
220 }