Source code: org/eclipse/jface/text/IDocument.java
1 /*******************************************************************************
2 * Copyright (c) 2000, 2004 IBM Corporation and others.
3 * All rights reserved. This program and the accompanying materials
4 * are made available under the terms of the Common Public License v1.0
5 * which accompanies this distribution, and is available at
6 * http://www.eclipse.org/legal/cpl-v10.html
7 *
8 * Contributors:
9 * IBM Corporation - initial API and implementation
10 *******************************************************************************/
11
12 package org.eclipse.jface.text;
13
14
15 /**
16 * An <code>IDocument</code> represents text providing support for
17 * <ul>
18 * <li> text manipulation
19 * <li> positions
20 * <li> partitions
21 * <li> line information
22 * <li> document change listeners
23 * <li> document partition change listeners
24 * </ul>
25 *
26 * A document allows to set its content and to manipulate it. For manipulation
27 * a document provides the <code>replace</code> method which substitutes a given
28 * string for a specified text range in the document. On each document change, all
29 * registered document listeners are informed exactly once.
30 *
31 * Positions are stickers to the document's text that are updated when the
32 * document is changed. Positions are updated by {@link org.eclipse.jface.text.IPositionUpdater}s. Position
33 * updaters are managed as a list. The list defines the sequence in which position
34 * updaters are invoked. This way, position updaters may rely on each other.
35 * Positions are grouped into categories. A category is a ordered list of positions.
36 * the document defines the order of position in a category based on the position's offset
37 * based on the implementation of the method <code>computeIndexInCategory</code>.
38 * Each document must support a default position category whose name is specified by this
39 * interface.<p>
40 *
41 * A document can be considered consisting of a sequence of not overlapping partitions.
42 * A partition is defined by its offset, its length, and its type. Partitions are
43 * updated on every document manipulation and ensured to be up-to-date when the document
44 * listeners are informed. A document uses an <code>IDocumentPartitioner</code> to
45 * manage its partitions. A document may be unpartitioned which happens when there is no
46 * partitioner. In this case, the document is considered as one single partition of a
47 * default type. The default type is specified by this interface. If a document change
48 * changes the document's partitioning all registered partitioning listeners are
49 * informed exactly once. The extension interface {@link org.eclipse.jface.text.IDocumentExtension3}
50 * introduced in version 3.0 extends the concept of partitions and allows a document to
51 * not only manage one but multiple partitioning. Each partitioning has an id which must
52 * be used to refer to a particular partitioning.<p>
53 *
54 * An <code>IDocument</code> provides methods to map line numbers and character
55 * positions onto each other based on the document's line delimiters. When moving text
56 * between documents using different line delimiters, the text must be converted to
57 * use the target document's line delimiters.<p>
58 *
59 * <code>IDocument</code> throws <code>BadLocationException</code> if the parameters of
60 * queries or manipulation requests are not inside the bounds of the document. The purpose
61 * of this style of exception handling is
62 * <ul>
63 * <li> prepare document for multi-thread access
64 * <li> allow clients to implement backtracking recovery methods
65 * <li> prevent clients from up-front contract checking when dealing with documents.
66 * </ul>
67 *
68 * A document support for searching has deprecated since version 3.0. The recommended way
69 * for searching is to use a {@link org.eclipse.jface.text.FindReplaceDocumentAdapter}.<p>
70 *
71 * In order to provide backward compatibility for clients of <code>IDocument</code>, extension
72 * interfaces are used to provide a means of evolution. The following extension interfaces
73 * exist:
74 * <ul>
75 * <li> {@link org.eclipse.jface.text.IDocumentExtension} since version 2.0 introducing the concept
76 * of post notification replaces in order to allow document listeners to manipulate the document
77 * while receiving a document change notification </li>
78 * <li> {@link org.eclipse.jface.text.IDocumentExtension2} since version 2.1 introducing configuration
79 * methods for post notification replaces and document change notification. </li>
80 * <li> {@link org.eclipse.jface.text.IDocumentExtension3} since version 3.0 replacing the original
81 * partitioning concept by allowing multiple partitionings at the same time and introducing zero-
82 * length partitions in conjunction with the distinction between open and closed partitions. </li>
83 * </ul>
84 *
85 * Clients may implement this interface and its extension interfaces or use the default
86 * implementation provided by <code>AbstractDocument</code> and <code>Document</code>.
87 *
88 * @see org.eclipse.jface.text.IDocumentExtension
89 * @see org.eclipse.jface.text.IDocumentExtension2
90 * @see org.eclipse.jface.text.IDocumentExtension3
91 * @see org.eclipse.jface.text.Position
92 * @see org.eclipse.jface.text.IPositionUpdater
93 * @see org.eclipse.jface.text.IDocumentPartitioner
94 * @see org.eclipse.jface.text.ILineTracker
95 * @see org.eclipse.jface.text.IDocumentListener
96 * @see org.eclipse.jface.text.IDocumentPartitioningListener
97 */
98 public interface IDocument {
99
100
101 /**
102 * The identifier of the default position category.
103 */
104 final static String DEFAULT_CATEGORY= "__dflt_position_category"; //$NON-NLS-1$
105
106 /**
107 * The identifier of the default partition content type.
108 */
109 final static String DEFAULT_CONTENT_TYPE= "__dftl_partition_content_type"; //$NON-NLS-1$
110
111
112
113
114 /* --------------- text access and manipulation --------------------------- */
115
116 /**
117 * Returns the character at the given document offset in this document.
118 *
119 * @param offset a document offset
120 * @return the character at the offset
121 * @exception BadLocationException if the offset is invalid in this document
122 */
123 char getChar(int offset) throws BadLocationException;
124
125 /**
126 * Returns the number of characters in this document.
127 *
128 * @return the number of characters in this document
129 */
130 int getLength();
131
132 /**
133 * Returns this document's complete text.
134 *
135 * @return the document's complete text
136 */
137 String get();
138
139 /**
140 * Returns this document's text for the specified range.
141 *
142 * @param offset the document offset
143 * @param length the length of the specified range
144 * @return the document's text for the specified range
145 * @exception BadLocationException if the range is invalid in this document
146 */
147 String get(int offset, int length) throws BadLocationException;
148
149 /**
150 * Replaces the content of the document with the given text.
151 * Sends a <code>DocumentEvent</code> to all registered <code>IDocumentListener</code>.
152 * This method is a convenience method for <code>replace(0, getLength(), text)</code>.
153 *
154 * @param text the new content of the document
155 *
156 * @see DocumentEvent
157 * @see IDocumentListener
158 */
159 void set(String text);
160
161 /**
162 * Substitutes the given text for the specified document range.
163 * Sends a <code>DocumentEvent</code> to all registered <code>IDocumentListener</code>.
164 *
165 * @param offset the document offset
166 * @param length the length of the specified range
167 * @param text the substitution text
168 * @exception BadLocationException if the offset is invalid in this document
169 *
170 * @see DocumentEvent
171 * @see IDocumentListener
172 */
173 void replace(int offset, int length, String text) throws BadLocationException;
174
175 /**
176 * Registers the document listener with the document. After registration
177 * the IDocumentListener is informed about each change of this document.
178 * If the listener is already registered nothing happens.<p>
179 * An <code>IDocumentListener</code> may call back to this method
180 * when being inside a document notification.
181 *
182 * @param listener the listener to be registered
183 */
184 void addDocumentListener(IDocumentListener listener);
185
186 /**
187 * Removes the listener from the document's list of document listeners.
188 * If the listener is not registered with the document nothing happens.<p>
189 * An <code>IDocumentListener</code> may call back to this method
190 * when being inside a document notification.
191 *
192 * @param listener the listener to be removed
193 */
194 void removeDocumentListener(IDocumentListener listener);
195
196 /**
197 * Adds the given document listener as one which is notified before
198 * those document listeners added with <code>addDocumentListener</code>
199 * are notified. If the given listener is also registered using
200 * <code>addDocumentListener</code> it will be notified twice.
201 * If the listener is already registered nothing happens.<p>
202 *
203 * This method is not for public use.
204 *
205 * @param documentAdapter the listener to be added as pre-notified document listener
206 *
207 * @see #removePrenotifiedDocumentListener(IDocumentListener)
208 */
209 void addPrenotifiedDocumentListener(IDocumentListener documentAdapter);
210
211 /**
212 * Removes the given document listener from the document's list of
213 * pre-notified document listeners. If the listener is not registered
214 * with the document nothing happens. <p>
215 *
216 * This method is not for public use.
217 *
218 * @param documentAdapter the listener to be removed
219 *
220 * @see #addPrenotifiedDocumentListener(IDocumentListener)
221 */
222 void removePrenotifiedDocumentListener(IDocumentListener documentAdapter);
223
224
225
226 /* -------------------------- positions ----------------------------------- */
227
228 /**
229 * Adds a new position category to the document. If the position category
230 * already exists nothing happens.
231 *
232 * @param category the category to be added
233 */
234 void addPositionCategory(String category);
235
236 /**
237 * Deletes the position category from the document. All positions
238 * in this category are thus deleted as well.
239 *
240 * @param category the category to be removed
241 * @exception BadPositionCategoryException if category is undefined in this document
242 */
243 void removePositionCategory(String category) throws BadPositionCategoryException;
244
245 /**
246 * Returns all position categories of this document. This
247 * includes the default position category.
248 *
249 * @return the document's position categories
250 */
251 String[] getPositionCategories();
252
253 /**
254 * Checks the presence of the specified position category.
255 *
256 * @param category the category to check
257 * @return <code>true</code> if category is defined
258 */
259 boolean containsPositionCategory(String category);
260
261 /**
262 * Adds the position to the document's default position category.
263 * This is a convenience method for <code>addPosition(DEFAULT_CATEGORY, position)</code>.
264 *
265 * @param position the position to be added
266 * @exception BadLocationException if position describes an invalid range in this document
267 */
268 void addPosition(Position position) throws BadLocationException;
269
270 /**
271 * Removes the given position from the document's default position category.
272 * This is a convenience method for <code>removePosition(DEFAULT_CATEGORY, position)</code>.
273 *
274 * @param position the position to be removed
275 */
276 void removePosition(Position position);
277
278 /**
279 * Adds the position to the specified position category of the document.
280 * A position that has been added to a position category is updated on each
281 * change applied to the document. Positions may be added multiple times.
282 * The order of the category is maintained.
283 *
284 * @param category the category to which to add
285 * @param position the position to be added
286 * @exception BadLocationException if position describes an invalid range in this document
287 * @exception BadPositionCategoryException if the category is undefined in this document
288 */
289 void addPosition(String category, Position position) throws BadLocationException, BadPositionCategoryException;
290
291 /**
292 * Removes the given position from the specified position category.
293 * If the position is not part of the specified category nothing happens.
294 * If the position has been added multiple times, only the first occurrence is deleted.
295 *
296 * @param category the category from which to delete
297 * @param position the position to be deleted
298 * @exception BadPositionCategoryException if category is undefined in this document
299 */
300 void removePosition(String category, Position position) throws BadPositionCategoryException;
301
302 /**
303 * Returns all positions of the given position category.
304 * The positions are ordered according to the category's order.
305 * Manipulating this list does not affect the document, but manipulating the
306 * position does affect the document.
307 *
308 * @param category the category
309 * @return the list of all positions
310 * @exception BadPositionCategoryException if category is undefined in this document
311 */
312 Position[] getPositions(String category) throws BadPositionCategoryException;
313
314 /**
315 * Determines whether a position described by the parameters is managed by this document.
316 *
317 * @param category the category to check
318 * @param offset the offset of the position to find
319 * @param length the length of the position to find
320 * @return <code>true</code> if position is found
321 */
322 boolean containsPosition(String category, int offset, int length);
323
324 /**
325 * Computes the index at which a <code>Position</code> with the
326 * specified offset would be inserted into the given category. As the
327 * ordering inside a category only depends on the offset, the index must be
328 * chosen to be the first of all positions with the same offset.
329 *
330 * @param category the category in which would be added
331 * @param offset the position offset to be considered
332 * @return the index into the category
333 * @exception BadLocationException if offset is invalid in this document
334 * @exception BadPositionCategoryException if category is undefined in this document
335 */
336 int computeIndexInCategory(String category, int offset) throws BadLocationException, BadPositionCategoryException;
337
338 /**
339 * Appends a new position updater to the document's list of position updaters.
340 * Position updaters may be added multiple times.<p>
341 * An <code>IPositionUpdater</code> may call back to this method
342 * when being inside a document notification.
343 *
344 * @param updater the updater to be added
345 */
346 void addPositionUpdater(IPositionUpdater updater);
347
348 /**
349 * Removes the position updater from the document's list of position updaters.
350 * If the position updater has multiple occurrences only the first occurrence is
351 * removed. If the position updater is not registered with this document, nothing
352 * happens.<p>
353 * An <code>IPositionUpdater</code> may call back to this method
354 * when being inside a document notification.
355 *
356 * @param updater the updater to be removed
357 */
358 void removePositionUpdater(IPositionUpdater updater);
359
360 /**
361 * Inserts the position updater at the specified index in the document's
362 * list of position updaters. Positions updaters may be inserted multiple times.<p>
363 * An <code>IPositionUpdater</code> may call back to this method
364 * when being inside a document notification.
365 *
366 * @param updater the updater to be inserted
367 * @param index the index in the document's updater list
368 */
369 void insertPositionUpdater(IPositionUpdater updater, int index);
370
371 /**
372 * Returns the list of position updaters attached to the document.
373 *
374 * @return the list of position updaters
375 */
376 IPositionUpdater[] getPositionUpdaters();
377
378
379
380
381 /* -------------------------- partitions ---------------------------------- */
382
383 /**
384 * Returns the set of legal content types of document partitions.
385 * This set can be empty. The set can contain more content types than
386 * contained by the result of <code>getPartitioning(0, getLength())</code>.
387 * <p>
388 * Use {@link IDocumentExtension3#getLegalContentTypes(String)} when the document
389 * supports multiple partitionings. In that case this method is equivalent to:
390 * <pre>
391 * IDocumentExtension3 extension= (IDocumentExtension3) document;
392 * return extension.getLegalContentTypes(IDocumentExtension3.DEFAULT_PARTITIONING);
393 * </pre>
394 *
395 * @return the set of legal content types
396 */
397 String[] getLegalContentTypes();
398
399 /**
400 * Returns the type of the document partition containing the given offset.
401 * This is a convenience method for <code>getPartition(offset).getType()</code>.
402 * <p>
403 * Use {@link IDocumentExtension3#getContentType(String, int, boolean)} when
404 * the document supports multiple partitionings. In that case this method is
405 * equivalent to:
406 * <pre>
407 * IDocumentExtension3 extension= (IDocumentExtension3) document;
408 * return extension.getContentTypes(IDocumentExtension3.DEFAULT_PARTITIONING, offset, false);
409 * </pre>
410 *
411 * @param offset the document offset
412 * @return the partition type
413 * @exception BadLocationException if offset is invalid in this document
414 */
415 String getContentType(int offset) throws BadLocationException;
416
417 /**
418 * Returns the document partition in which the position is located.
419 * <p>
420 * Use {@link IDocumentExtension3#getPartition(String, int, boolean)} when
421 * the document supports multiple partitionings. In that case this method is
422 * equivalent:
423 * <pre>
424 * IDocumentExtension3 extension= (IDocumentExtension3) document;
425 * return extension.getPartition(IDocumentExtension3.DEFAULT_PARTITIONING, offset, false);
426 * </pre>
427 *
428 * @param offset the document offset
429 * @return a specification of the partition
430 * @exception BadLocationException if offset is invalid in this document
431 */
432 ITypedRegion getPartition(int offset) throws BadLocationException;
433
434 /**
435 * Computes the partitioning of the given document range using the
436 * document's partitioner.
437 * <p>
438 * Use {@link IDocumentExtension3#computePartitioning(String, int, int, boolean)} when
439 * the document supports multiple partitionings. In that case this method is
440 * equivalent:
441 * <pre>
442 * IDocumentExtension3 extension= (IDocumentExtension3) document;
443 * return extension.computePartitioning(IDocumentExtension3.DEFAULT_PARTITIONING, offset, length, false);
444 * </pre>
445 *
446 * @param offset the document offset at which the range starts
447 * @param length the length of the document range
448 * @return a specification of the range's partitioning
449 * @exception BadLocationException if the range is invalid in this document
450 */
451 ITypedRegion[] computePartitioning(int offset, int length) throws BadLocationException;
452
453 /**
454 * Registers the document partitioning listener with the document. After registration
455 * the document partitioning listener is informed about each partition change
456 * cause by a document manipulation or by changing the document's partitioner.
457 * If a document partitioning listener is also
458 * a document listener, the following notification sequence is guaranteed if a
459 * document manipulation changes the document partitioning:
460 * <ul>
461 * <li>listener.documentAboutToBeChanged(DocumentEvent);
462 * <li>listener.documentPartitioningChanged();
463 * <li>listener.documentChanged(DocumentEvent);
464 * </ul>
465 * If the listener is already registered nothing happens.<p>
466 * An <code>IDocumentPartitioningListener</code> may call back to this method
467 * when being inside a document notification.
468 *
469 * @param listener the listener to be added
470 */
471 void addDocumentPartitioningListener(IDocumentPartitioningListener listener);
472
473 /**
474 * Removes the listener from this document's list of document partitioning
475 * listeners. If the listener is not registered with the document nothing
476 * happens.<p>
477 * An <code>IDocumentPartitioningListener</code> may call back to this method
478 * when being inside a document notification.
479 *
480 * @param listener the listener to be removed
481 */
482 void removeDocumentPartitioningListener(IDocumentPartitioningListener listener);
483
484 /**
485 * Sets this document's partitioner. The caller of this method is responsible for
486 * disconnecting the document's old partitioner from the document and to
487 * connect the new partitioner to the document. Informs all document partitioning
488 * listeners about this change.
489 * <p>
490 * Use {@link IDocumentExtension3#setDocumentPartitioner(String, IDocumentPartitioner)} when
491 * the document supports multiple partitionings. In that case this method is equivalent to:
492 * <pre>
493 * IDocumentExtension3 extension= (IDocumentExtension3) document;
494 * extension.setDocumentPartitioner(IDocumentExtension3.DEFAULT_PARTITIONING, partitioner);
495 * </pre>
496 *
497 * @param partitioner the document's new partitioner
498 *
499 * @see IDocumentPartitioningListener
500 */
501 void setDocumentPartitioner(IDocumentPartitioner partitioner);
502
503 /**
504 * Returns this document's partitioner.
505 * <p>
506 * Use {@link IDocumentExtension3#getDocumentPartitioner(String)} when
507 * the document supports multiple partitionings. In that case this method is
508 * equivalent to:
509 * <pre>
510 * IDocumentExtension3 extension= (IDocumentExtension3) document;
511 * return extension.getDocumentPartitioner(IDocumentExtension3.DEFAULT_PARTITIONING);
512 * </pre>
513 *
514 * @return this document's partitioner
515 */
516 IDocumentPartitioner getDocumentPartitioner();
517
518
519
520 /* ---------------------- line information -------------------------------- */
521
522 /**
523 * Returns the length of the given line including the line's delimiter.
524 *
525 * @param line the line of interest
526 * @return the length of the line
527 * @exception BadLocationException if the line number is invalid in this document
528 */
529 int getLineLength(int line) throws BadLocationException;
530
531 /**
532 * Returns the number of the line at which the character of the specified position is located.
533 * The first line has the line number 0. A new line starts directly after a line
534 * delimiter. <code>(offset == document length)</code> is a valid argument although there is no
535 * corresponding character.
536 *
537 * @param offset the document offset
538 * @return the number of the line
539 * @exception BadLocationException if the offset is invalid in this document
540 */
541 int getLineOfOffset(int offset) throws BadLocationException;
542
543 /**
544 * Determines the offset of the first character of the given line.
545 *
546 * @param line the line of interest
547 * @return the document offset
548 * @exception BadLocationException if the line number is invalid in this document
549 */
550 int getLineOffset(int line) throws BadLocationException;
551
552 /**
553 * Returns a description of the specified line. The line is described by its
554 * offset and its length excluding the line's delimiter.
555 *
556 * @param line the line of interest
557 * @return a line description
558 * @exception BadLocationException if the line number is invalid in this document
559 */
560 IRegion getLineInformation(int line) throws BadLocationException;
561
562 /**
563 * Returns a description of the line at the given offset.
564 * The description contains the offset and the length of the line
565 * excluding the line's delimiter.
566 *
567 * @param offset the offset whose line should be described
568 * @return a region describing the line
569 * @exception BadLocationException if offset is invalid in this document
570 */
571 IRegion getLineInformationOfOffset(int offset) throws BadLocationException;
572
573 /**
574 * Returns the number of lines in this document
575 *
576 * @return the number of lines in this document
577 */
578 int getNumberOfLines();
579
580 /**
581 * Returns the number of lines which are occupied by a given text range.
582 *
583 * @param offset the offset of the specified text range
584 * @param length the length of the specified text range
585 * @return the number of lines occupied by the specified range
586 * @exception BadLocationException if specified range is invalid in this tracker
587 */
588 int getNumberOfLines(int offset, int length) throws BadLocationException;
589
590 /**
591 * Computes the number of lines in the given text. For a given
592 * implementer of this interface this method returns the same
593 * result as <code>set(text); getNumberOfLines()</code>.
594 *
595 * @param text the text whose number of lines should be computed
596 * @return the number of lines in the given text
597 */
598 int computeNumberOfLines(String text);
599
600
601 /* ------------------ line delimiter conversion --------------------------- */
602
603 /**
604 * Returns the document's legal line delimiters.
605 *
606 * @return the document's legal line delimiters
607 */
608 String[] getLegalLineDelimiters();
609
610 /**
611 * Returns the line delimiter of that line or <code>null</code> if the
612 * line is not closed with a line delimiter.
613 *
614 * @param line the line of interest
615 * @return the line's delimiter or <code>null</code> if line does not have a delimiter
616 * @exception BadLocationException if the line number is invalid in this document
617 */
618 String getLineDelimiter(int line) throws BadLocationException;
619
620
621 /* ---------------------------- search ------------------------------------ */
622
623 /**
624 * Returns the offset of a given search string in the document based on a set of search criteria.
625 *
626 * @param startOffset document offset at which search starts
627 * @param findString the string to find
628 * @param forwardSearch the search direction
629 * @param caseSensitive indicates whether lower and upper case should be distinguished
630 * @param wholeWord indicates whether the findString should be limited by white spaces as
631 * defined by Character.isWhiteSpace
632 * @return the offset of the first occurrence of findString based on the parameters or -1 if no match is found
633 * @exception BadLocationException if startOffset is an invalid document offset
634 * @deprecated as of 3.0 search is provided by {@link FindReplaceDocumentAdapter}
635 */
636 int search(int startOffset, String findString, boolean forwardSearch, boolean caseSensitive, boolean wholeWord) throws BadLocationException;
637 }