Copyright (c) 2000, 2015 IBM Corporation and others. This program and the accompanying materials are made available under the terms of the Eclipse Public License 2.0 which accompanies this distribution, and is available at https://www.eclipse.org/legal/epl-2.0/ SPDX-License-Identifier: EPL-2.0 Contributors: IBM Corporation - initial API and implementation Anton Leherbauer - [implementation] AnnotationModel.fModificationStamp leaks annotations - http://bugs.eclipse.org/345715
/******************************************************************************* * Copyright (c) 2000, 2015 IBM Corporation and others. * * This program and the accompanying materials * are made available under the terms of the Eclipse Public License 2.0 * which accompanies this distribution, and is available at * https://www.eclipse.org/legal/epl-2.0/ * * SPDX-License-Identifier: EPL-2.0 * * Contributors: * IBM Corporation - initial API and implementation * Anton Leherbauer <anton.leherbauer@windriver.com> - [implementation] AnnotationModel.fModificationStamp leaks annotations - http://bugs.eclipse.org/345715 *******************************************************************************/
package org.eclipse.jface.text.source; import java.util.ArrayList; import java.util.Collections; import java.util.HashMap; import java.util.IdentityHashMap; import java.util.Iterator; import java.util.List; import java.util.Map; import java.util.Map.Entry; import java.util.NoSuchElementException; import org.eclipse.core.runtime.Assert; import org.eclipse.jface.text.AbstractDocument; import org.eclipse.jface.text.BadLocationException; import org.eclipse.jface.text.BadPositionCategoryException; import org.eclipse.jface.text.DocumentEvent; import org.eclipse.jface.text.IDocument; import org.eclipse.jface.text.IDocumentListener; import org.eclipse.jface.text.ISynchronizable; import org.eclipse.jface.text.Position;
Standard implementation of IAnnotationModel and its extension interfaces. This class can directly be used by clients. Subclasses may adapt this annotation model to other existing annotation mechanisms. This class also implements ISynchronizable. All modifications of the model's internal annotation map are synchronized using the model's lock object.
/** * Standard implementation of {@link IAnnotationModel} and its extension * interfaces. This class can directly be used by clients. Subclasses may adapt * this annotation model to other existing annotation mechanisms. This class * also implements {@link org.eclipse.jface.text.ISynchronizable}. All * modifications of the model's internal annotation map are synchronized using * the model's lock object. */
public class AnnotationModel implements IAnnotationModel, IAnnotationModelExtension, IAnnotationModelExtension2, ISynchronizable {
Iterator that returns the annotations for a given region.
See Also:
Since:3.4
/** * Iterator that returns the annotations for a given region. * * @since 3.4 * @see AnnotationModel.RegionIterator#RegionIterator(Iterator, IAnnotationModel, int, int, boolean, boolean) */
private static final class RegionIterator implements Iterator<Annotation> { private final Iterator<Annotation> fParentIterator; private final boolean fCanEndAfter; private final boolean fCanStartBefore; private final IAnnotationModel fModel; private Annotation fNext; private Position fRegion;
Iterator that returns all annotations from the parent iterator which have a position in the given model inside the given region.

See IAnnotationModelExtension2 for a definition of inside.

Params:
  • parentIterator – iterator containing all annotations
  • model – the model to use to retrieve positions from for each annotation
  • offset – start position of the region
  • length – length of the region
  • canStartBefore – include annotations starting before region
  • canEndAfter – include annotations ending after region
See Also:
/** * Iterator that returns all annotations from the parent iterator which * have a position in the given model inside the given region. * <p> * See {@link IAnnotationModelExtension2} for a definition of inside. * </p> * * @param parentIterator iterator containing all annotations * @param model the model to use to retrieve positions from for each * annotation * @param offset start position of the region * @param length length of the region * @param canStartBefore include annotations starting before region * @param canEndAfter include annotations ending after region * @see IAnnotationModelExtension2 */
public RegionIterator(Iterator<Annotation> parentIterator, IAnnotationModel model, int offset, int length, boolean canStartBefore, boolean canEndAfter) { fParentIterator= parentIterator; fModel= model; fRegion= new Position(offset, length); fCanEndAfter= canEndAfter; fCanStartBefore= canStartBefore; fNext= findNext(); } @Override public boolean hasNext() { return fNext != null; } @Override public Annotation next() { if (!hasNext()) throw new NoSuchElementException(); Annotation result= fNext; fNext= findNext(); return result; } @Override public void remove() { throw new UnsupportedOperationException(); } private Annotation findNext() { while (fParentIterator.hasNext()) { Annotation next= fParentIterator.next(); Position position= fModel.getPosition(next); if (position != null) { int offset= position.getOffset(); if (isWithinRegion(offset, position.getLength())) return next; } } return null; } private boolean isWithinRegion(int start, int length) { if (fCanStartBefore && fCanEndAfter) return fRegion.overlapsWith(start, length); else if (fCanStartBefore) return fRegion.includes(start + length - (length > 0 ? 1 : 0)); else if (fCanEndAfter) return fRegion.includes(start); else return fRegion.includes(start) && fRegion.includes(start + length - (length > 0 ? 1 : 0)); } }
An iterator iteration over a Positions and mapping positions to annotations using a provided map if the provided map contains the element.
Since:3.4
/** * An iterator iteration over a Positions and mapping positions to * annotations using a provided map if the provided map contains the element. * * @since 3.4 */
private static final class AnnotationsInterator implements Iterator<Annotation> { private Annotation fNext; private final Position[] fPositions; private int fIndex; private final Map<Position, Annotation> fMap;
Params:
  • positions – positions to iterate over
  • map – a map to map positions to annotations
/** * @param positions positions to iterate over * @param map a map to map positions to annotations */
public AnnotationsInterator(Position[] positions, Map<Position, Annotation> map) { fPositions= positions; fIndex= 0; fMap= map; fNext= findNext(); } @Override public boolean hasNext() { return fNext != null; } @Override public Annotation next() { Annotation result= fNext; fNext= findNext(); return result; } @Override public void remove() { throw new UnsupportedOperationException(); } private Annotation findNext() { while (fIndex < fPositions.length) { Position position= fPositions[fIndex]; fIndex++; if (fMap.containsKey(position)) return fMap.get(position); } return null; } }
A single iterator builds its behavior based on a sequence of iterators.
Type parameters:
  • <E> – the type of elements returned by this iterator
Since:3.1
/** * A single iterator builds its behavior based on a sequence of iterators. * * @param <E> the type of elements returned by this iterator * @since 3.1 */
private static class MetaIterator<E> implements Iterator<E> {
The iterator over a list of iterators.
/** The iterator over a list of iterators. */
private Iterator<? extends Iterator<? extends E>> fSuperIterator;
The current iterator.
/** The current iterator. */
private Iterator<? extends E> fCurrent;
The current element.
/** The current element. */
private E fCurrentElement; public MetaIterator(Iterator<? extends Iterator<? extends E>> iterator) { fSuperIterator= iterator; fCurrent= fSuperIterator.next(); // there is at least one. } @Override public void remove() { throw new UnsupportedOperationException(); } @Override public boolean hasNext() { if (fCurrentElement != null) return true; if (fCurrent.hasNext()) { fCurrentElement= fCurrent.next(); return true; } else if (fSuperIterator.hasNext()) { fCurrent= fSuperIterator.next(); return hasNext(); } else return false; } @Override public E next() { if (!hasNext()) throw new NoSuchElementException(); E element= fCurrentElement; fCurrentElement= null; return element; } }
Internal annotation model listener for forwarding annotation model changes from the attached models to the registered listeners of the outer most annotation model.
Since:3.0
/** * Internal annotation model listener for forwarding annotation model changes from the attached models to the * registered listeners of the outer most annotation model. * * @since 3.0 */
private class InternalModelListener implements IAnnotationModelListener, IAnnotationModelListenerExtension { @Override public void modelChanged(IAnnotationModel model) { AnnotationModel.this.fireModelChanged(new AnnotationModelEvent(model, true)); } @Override public void modelChanged(AnnotationModelEvent event) { AnnotationModel.this.fireModelChanged(event); } }
The list of managed annotations
Deprecated:since 3.0 use getAnnotationMap instead
/** * The list of managed annotations * @deprecated since 3.0 use <code>getAnnotationMap</code> instead */
@Deprecated protected Map<Annotation, Position> fAnnotations;
The map which maps Position to Annotation.
Since:3.4
/** * The map which maps {@link Position} to {@link Annotation}. * @since 3.4 **/
private IdentityHashMap<Position, Annotation> fPositions;
The list of annotation model listeners
/** The list of annotation model listeners */
protected ArrayList<IAnnotationModelListener> fAnnotationModelListeners;
The document connected with this model
/** The document connected with this model */
protected IDocument fDocument;
The number of open connections to the same document
/** The number of open connections to the same document */
private int fOpenConnections= 0;
The document listener for tracking whether document positions might have been changed.
/** The document listener for tracking whether document positions might have been changed. */
private IDocumentListener fDocumentListener;
The flag indicating whether the document positions might have been changed.
/** The flag indicating whether the document positions might have been changed. */
private boolean fDocumentChanged= true;
The model's attachment.
Since:3.0
/** * The model's attachment. * @since 3.0 */
private Map<Object, IAnnotationModel> fAttachments= new HashMap<>();
The annotation model listener on attached sub-models.
Since:3.0
/** * The annotation model listener on attached sub-models. * @since 3.0 */
private IAnnotationModelListener fModelListener= new InternalModelListener();
The current annotation model event.
Since:3.0
/** * The current annotation model event. * @since 3.0 */
private AnnotationModelEvent fModelEvent;
The modification stamp.
Since:3.0
/** * The modification stamp. * @since 3.0 */
private Object fModificationStamp= new Object();
Creates a new annotation model. The annotation is empty, i.e. does not manage any annotations and is not connected to any document.
/** * Creates a new annotation model. The annotation is empty, i.e. does not * manage any annotations and is not connected to any document. */
public AnnotationModel() { fAnnotations= new AnnotationMap(10); fPositions= new IdentityHashMap<>(10); fAnnotationModelListeners= new ArrayList<>(2); fDocumentListener= new IDocumentListener() { @Override public void documentAboutToBeChanged(DocumentEvent event) { } @Override public void documentChanged(DocumentEvent event) { fDocumentChanged= true; } }; }
Returns the annotation map internally used by this annotation model.
Returns:the annotation map internally used by this annotation model
Since:3.0
/** * Returns the annotation map internally used by this annotation model. * * @return the annotation map internally used by this annotation model * @since 3.0 */
protected IAnnotationMap getAnnotationMap() { return (IAnnotationMap) fAnnotations; } @Override public Object getLockObject() { return getAnnotationMap().getLockObject(); } @Override public void setLockObject(Object lockObject) { getAnnotationMap().setLockObject(lockObject); }
Returns the current annotation model event. This is the event that will be sent out when calling fireModelChanged.
Returns:the current annotation model event
Since:3.0
/** * Returns the current annotation model event. This is the event that will be sent out * when calling <code>fireModelChanged</code>. * * @return the current annotation model event * @since 3.0 */
protected final AnnotationModelEvent getAnnotationModelEvent() { synchronized (getLockObject()) { if (fModelEvent == null) { fModelEvent= createAnnotationModelEvent(); fModelEvent.markWorldChange(false); fModificationStamp= new Object(); } return fModelEvent; } } @Override public void addAnnotation(Annotation annotation, Position position) { try { addAnnotation(annotation, position, true); } catch (BadLocationException e) { // ignore invalid position } } @Override public void replaceAnnotations(Annotation[] annotationsToRemove, Map<? extends Annotation, ? extends Position> annotationsToAdd) { try { replaceAnnotations(annotationsToRemove, annotationsToAdd, true); } catch (BadLocationException x) { } }
Replaces the given annotations in this model and if advised fires a model change event.
Params:
  • annotationsToRemove – the annotations to be removed
  • annotationsToAdd – the annotations to be added
  • fireModelChanged – true if a model change event should be fired, false otherwise
Throws:
Since:3.0
/** * Replaces the given annotations in this model and if advised fires a * model change event. * * @param annotationsToRemove the annotations to be removed * @param annotationsToAdd the annotations to be added * @param fireModelChanged <code>true</code> if a model change event * should be fired, <code>false</code> otherwise * @throws BadLocationException in case an annotation should be added at an * invalid position * @since 3.0 */
protected void replaceAnnotations(Annotation[] annotationsToRemove, Map<? extends Annotation, ? extends Position> annotationsToAdd, boolean fireModelChanged) throws BadLocationException { if (annotationsToRemove != null) { for (Annotation element : annotationsToRemove) removeAnnotation(element, false); } if (annotationsToAdd != null) { Iterator<? extends Entry<? extends Annotation, ? extends Position>> iter= annotationsToAdd.entrySet().iterator(); while (iter.hasNext()) { Map.Entry<? extends Annotation, ? extends Position> mapEntry= iter.next(); Annotation annotation= mapEntry.getKey(); Position position= mapEntry.getValue(); addAnnotation(annotation, position, false); } } if (fireModelChanged) fireModelChanged(); }
Adds the given annotation to this model. Associates the annotation with the given position. If requested, all annotation model listeners are informed about this model change. If the annotation is already managed by this model nothing happens.
Params:
  • annotation – the annotation to add
  • position – the associate position
  • fireModelChanged – indicates whether to notify all model listeners
Throws:
/** * Adds the given annotation to this model. Associates the * annotation with the given position. If requested, all annotation * model listeners are informed about this model change. If the annotation * is already managed by this model nothing happens. * * @param annotation the annotation to add * @param position the associate position * @param fireModelChanged indicates whether to notify all model listeners * @throws BadLocationException if the position is not a valid document position */
protected void addAnnotation(Annotation annotation, Position position, boolean fireModelChanged) throws BadLocationException { if (!fAnnotations.containsKey(annotation)) { addPosition(fDocument, position); fAnnotations.put(annotation, position); fPositions.put(position, annotation); synchronized (getLockObject()) { getAnnotationModelEvent().annotationAdded(annotation); } if (fireModelChanged) fireModelChanged(); } } @Override public void addAnnotationModelListener(IAnnotationModelListener listener) { if (!fAnnotationModelListeners.contains(listener)) { fAnnotationModelListeners.add(listener); if (listener instanceof IAnnotationModelListenerExtension) { IAnnotationModelListenerExtension extension= (IAnnotationModelListenerExtension) listener; AnnotationModelEvent event= createAnnotationModelEvent(); event.markSealed(); extension.modelChanged(event); } else listener.modelChanged(this); } }
Adds the given position to the default position category of the given document.
Params:
  • document – the document to which to add the position
  • position – the position to add
Throws:
/** * Adds the given position to the default position category of the * given document. * * @param document the document to which to add the position * @param position the position to add * @throws BadLocationException if the position is not a valid document position */
protected void addPosition(IDocument document, Position position) throws BadLocationException { if (document != null) document.addPosition(position); }
Removes the given position from the default position category of the given document.
Params:
  • document – the document to which to add the position
  • position – the position to add
Since:3.0
/** * Removes the given position from the default position category of the * given document. * * @param document the document to which to add the position * @param position the position to add * * @since 3.0 */
protected void removePosition(IDocument document, Position position) { if (document != null) document.removePosition(position); } @Override public void connect(IDocument document) { Assert.isTrue(fDocument == null || fDocument == document); if (fDocument == null) { fDocument= document; Iterator<Position> e= getAnnotationMap().valuesIterator(); while (e.hasNext()) try { addPosition(document, e.next()); } catch (BadLocationException x) { // ignore invalid position } } ++ fOpenConnections; if (fOpenConnections == 1) { document.addDocumentListener(fDocumentListener); connected(); } for (IAnnotationModel model : fAttachments.values()) { model.connect(document); } }
Hook method. Is called as soon as this model becomes connected to a document. Subclasses may re-implement.
/** * Hook method. Is called as soon as this model becomes connected to a document. * Subclasses may re-implement. */
protected void connected() { }
Hook method. Is called as soon as this model becomes disconnected from its document. Subclasses may re-implement.
/** * Hook method. Is called as soon as this model becomes disconnected from its document. * Subclasses may re-implement. */
protected void disconnected() { } @Override public void disconnect(IDocument document) { Assert.isTrue(fDocument == document); for (IAnnotationModel model : fAttachments.values()) { model.disconnect(document); } -- fOpenConnections; if (fOpenConnections == 0) { disconnected(); document.removeDocumentListener(fDocumentListener); Iterator<Position> e= getAnnotationMap().valuesIterator(); while (e.hasNext()) { Position p= e.next(); removePosition(document, p); } fDocument= null; } }
Informs all annotation model listeners that this model has been changed.
/** * Informs all annotation model listeners that this model has been changed. */
protected void fireModelChanged() { AnnotationModelEvent modelEvent= null; synchronized(getLockObject()) { if (fModelEvent != null) { modelEvent= fModelEvent; fModelEvent= null; } } if (modelEvent != null) fireModelChanged(modelEvent); }
Creates and returns a new annotation model event. Subclasses may override.
Returns:a new and empty annotation model event
Since:3.0
/** * Creates and returns a new annotation model event. Subclasses may override. * * @return a new and empty annotation model event * @since 3.0 */
protected AnnotationModelEvent createAnnotationModelEvent() { return new AnnotationModelEvent(this); }
Informs all annotation model listeners that this model has been changed as described in the annotation model event. The event is sent out to all listeners implementing IAnnotationModelListenerExtension. All other listeners are notified by just calling modelChanged(IAnnotationModel).
Params:
  • event – the event to be sent out to the listeners
Since:2.0
/** * Informs all annotation model listeners that this model has been changed * as described in the annotation model event. The event is sent out * to all listeners implementing <code>IAnnotationModelListenerExtension</code>. * All other listeners are notified by just calling <code>modelChanged(IAnnotationModel)</code>. * * @param event the event to be sent out to the listeners * @since 2.0 */
protected void fireModelChanged(AnnotationModelEvent event) { event.markSealed(); if (event.isEmpty()) return; ArrayList<IAnnotationModelListener> v= new ArrayList<>(fAnnotationModelListeners); Iterator<IAnnotationModelListener> e= v.iterator(); while (e.hasNext()) { IAnnotationModelListener l= e.next(); if (l instanceof IAnnotationModelListenerExtension) ((IAnnotationModelListenerExtension) l).modelChanged(event); else if (l != null) l.modelChanged(this); } }
Removes the given annotations from this model. If requested all annotation model listeners will be informed about this change. modelInitiated indicates whether the deletion has been initiated by this model or by one of its clients.
Params:
  • annotations – the annotations to be removed
  • fireModelChanged – indicates whether to notify all model listeners
  • modelInitiated – indicates whether this changes has been initiated by this model
/** * Removes the given annotations from this model. If requested all * annotation model listeners will be informed about this change. * <code>modelInitiated</code> indicates whether the deletion has * been initiated by this model or by one of its clients. * * @param annotations the annotations to be removed * @param fireModelChanged indicates whether to notify all model listeners * @param modelInitiated indicates whether this changes has been initiated by this model */
protected void removeAnnotations(List<? extends Annotation> annotations, boolean fireModelChanged, boolean modelInitiated) { if (!annotations.isEmpty()) { Iterator<? extends Annotation> e= annotations.iterator(); while (e.hasNext()) removeAnnotation(e.next(), false); if (fireModelChanged) fireModelChanged(); } }
Removes all annotations from the model whose associated positions have been deleted. If requested inform all model listeners about the change.
Params:
  • fireModelChanged – indicates whether to notify all model listeners
/** * Removes all annotations from the model whose associated positions have been * deleted. If requested inform all model listeners about the change. * * @param fireModelChanged indicates whether to notify all model listeners */
protected void cleanup(boolean fireModelChanged) { cleanup(fireModelChanged, true); }
Removes all annotations from the model whose associated positions have been deleted. If requested inform all model listeners about the change. If requested a new thread is created for the notification of the model listeners.
Params:
  • fireModelChanged – indicates whether to notify all model listeners
  • forkNotification – true iff notification should be done in a new thread
Since:3.0
/** * Removes all annotations from the model whose associated positions have been * deleted. If requested inform all model listeners about the change. If requested * a new thread is created for the notification of the model listeners. * * @param fireModelChanged indicates whether to notify all model listeners * @param forkNotification <code>true</code> iff notification should be done in a new thread * @since 3.0 */
private void cleanup(boolean fireModelChanged, boolean forkNotification) { if (fDocumentChanged) { fDocumentChanged= false; ArrayList<Annotation> deleted= new ArrayList<>(); Iterator<Annotation> e= getAnnotationMap().keySetIterator(); while (e.hasNext()) { Annotation a= e.next(); Position p= fAnnotations.get(a); if (p == null || p.isDeleted()) deleted.add(a); } if (fireModelChanged && forkNotification) { removeAnnotations(deleted, false, false); synchronized (getLockObject()) { if (fModelEvent != null) new Thread() { @Override public void run() { fireModelChanged(); } }.start(); } } else removeAnnotations(deleted, fireModelChanged, false); } } @Override public Iterator<Annotation> getAnnotationIterator() { return getAnnotationIterator(true, true); }
{@inheritDoc}
Since:3.4
/** * {@inheritDoc} * * @since 3.4 */
@Override public Iterator<Annotation> getAnnotationIterator(int offset, int length, boolean canStartBefore, boolean canEndAfter) { Iterator<Annotation> regionIterator= getRegionAnnotationIterator(offset, length, canStartBefore, canEndAfter); if (fAttachments.isEmpty()) return regionIterator; List<Iterator<Annotation>> iterators= new ArrayList<>(fAttachments.size() + 1); iterators.add(regionIterator); Iterator<Object> it= fAttachments.keySet().iterator(); while (it.hasNext()) { IAnnotationModel attachment= fAttachments.get(it.next()); if (attachment instanceof IAnnotationModelExtension2) iterators.add(((IAnnotationModelExtension2) attachment).getAnnotationIterator(offset, length, canStartBefore, canEndAfter)); else iterators.add(new RegionIterator(attachment.getAnnotationIterator(), attachment, offset, length, canStartBefore, canEndAfter)); } return new MetaIterator<>(iterators.iterator()); }
Params:
  • offset – region start
  • length – region length
  • canStartBefore – position can start before region
  • canEndAfter – position can end after region
See Also:
Returns:an iterator to iterate over annotations in region
Since:3.4
/** * Returns an iterator as specified in {@link IAnnotationModelExtension2#getAnnotationIterator(int, int, boolean, boolean)} * * @param offset region start * @param length region length * @param canStartBefore position can start before region * @param canEndAfter position can end after region * @return an iterator to iterate over annotations in region * @see IAnnotationModelExtension2#getAnnotationIterator(int, int, boolean, boolean) * @since 3.4 */
private Iterator<Annotation> getRegionAnnotationIterator(int offset, int length, boolean canStartBefore, boolean canEndAfter) { if (!(fDocument instanceof AbstractDocument)) return new RegionIterator(getAnnotationIterator(true), this, offset, length, canStartBefore, canEndAfter); AbstractDocument document= (AbstractDocument) fDocument; cleanup(true); try { Position[] positions= document.getPositions(IDocument.DEFAULT_CATEGORY, offset, length, canStartBefore, canEndAfter); return new AnnotationsInterator(positions, fPositions); } catch (BadPositionCategoryException e) { // can happen if e.g. the document doesn't contain such a category, or when removed in a different thread return Collections.<Annotation>emptyList().iterator(); } }
Returns all annotations managed by this model. cleanup indicates whether all annotations whose associated positions are deleted should previously be removed from the model. recurse indicates whether annotations of attached sub-models should also be returned.
Params:
  • cleanup – indicates whether annotations with deleted associated positions are removed
  • recurse – whether to return annotations managed by sub-models.
Returns:all annotations managed by this model
Since:3.0
/** * Returns all annotations managed by this model. <code>cleanup</code> * indicates whether all annotations whose associated positions are * deleted should previously be removed from the model. <code>recurse</code> indicates * whether annotations of attached sub-models should also be returned. * * @param cleanup indicates whether annotations with deleted associated positions are removed * @param recurse whether to return annotations managed by sub-models. * @return all annotations managed by this model * @since 3.0 */
private Iterator<Annotation> getAnnotationIterator(boolean cleanup, boolean recurse) { Iterator<Annotation> iter= getAnnotationIterator(cleanup); if (!recurse || fAttachments.isEmpty()) return iter; List<Iterator<Annotation>> iterators= new ArrayList<>(fAttachments.size() + 1); iterators.add(iter); Iterator<Object> it= fAttachments.keySet().iterator(); while (it.hasNext()) iterators.add(fAttachments.get(it.next()).getAnnotationIterator()); return new MetaIterator<>(iterators.iterator()); }
Returns all annotations managed by this model. cleanup indicates whether all annotations whose associated positions are deleted should previously be removed from the model.
Params:
  • cleanup – indicates whether annotations with deleted associated positions are removed
Returns:all annotations managed by this model
/** * Returns all annotations managed by this model. <code>cleanup</code> * indicates whether all annotations whose associated positions are * deleted should previously be removed from the model. * * @param cleanup indicates whether annotations with deleted associated positions are removed * @return all annotations managed by this model */
protected Iterator<Annotation> getAnnotationIterator(boolean cleanup) { if (cleanup) cleanup(true); return getAnnotationMap().keySetIterator(); } @Override public Position getPosition(Annotation annotation) { Position position= fAnnotations.get(annotation); if (position != null) return position; Iterator<IAnnotationModel> it= fAttachments.values().iterator(); while (position == null && it.hasNext()) position= it.next().getPosition(annotation); return position; } @Override public void removeAllAnnotations() { removeAllAnnotations(true); }
Removes all annotations from the annotation model. If requested inform all model change listeners about this change.
Params:
  • fireModelChanged – indicates whether to notify all model listeners
/** * Removes all annotations from the annotation model. If requested * inform all model change listeners about this change. * * @param fireModelChanged indicates whether to notify all model listeners */
protected void removeAllAnnotations(boolean fireModelChanged) { if (fDocument != null) { Iterator<Annotation> e= getAnnotationMap().keySetIterator(); while (e.hasNext()) { Annotation a= e.next(); Position p= fAnnotations.get(a); removePosition(fDocument, p); // p.delete(); synchronized (getLockObject()) { getAnnotationModelEvent().annotationRemoved(a, p); } } } fAnnotations.clear(); fPositions.clear(); if (fireModelChanged) fireModelChanged(); } @Override public void removeAnnotation(Annotation annotation) { removeAnnotation(annotation, true); }
Removes the given annotation from the annotation model. If requested inform all model change listeners about this change.
Params:
  • annotation – the annotation to be removed
  • fireModelChanged – indicates whether to notify all model listeners
/** * Removes the given annotation from the annotation model. * If requested inform all model change listeners about this change. * * @param annotation the annotation to be removed * @param fireModelChanged indicates whether to notify all model listeners */
protected void removeAnnotation(Annotation annotation, boolean fireModelChanged) { if (fAnnotations.containsKey(annotation)) { Position p= null; p= fAnnotations.get(annotation); if (fDocument != null) { removePosition(fDocument, p); // p.delete(); } fAnnotations.remove(annotation); fPositions.remove(p); synchronized (getLockObject()) { getAnnotationModelEvent().annotationRemoved(annotation, p); } if (fireModelChanged) fireModelChanged(); } } @Override public void modifyAnnotationPosition(Annotation annotation, Position position) { modifyAnnotationPosition(annotation, position, true); }
Modifies the associated position of the given annotation to the given position. If the annotation is not yet managed by this annotation model, the annotation is added. When the position is null, the annotation is removed from the model.

If requested, all annotation model change listeners will be informed about the change.

Params:
  • annotation – the annotation whose associated position should be modified
  • position – the position to whose values the associated position should be changed
  • fireModelChanged – indicates whether to notify all model listeners
Since:3.0
/** * Modifies the associated position of the given annotation to the given * position. If the annotation is not yet managed by this annotation model, * the annotation is added. When the position is <code>null</code>, the * annotation is removed from the model. * <p> * If requested, all annotation model change listeners will be informed * about the change. * * @param annotation the annotation whose associated position should be * modified * @param position the position to whose values the associated position * should be changed * @param fireModelChanged indicates whether to notify all model listeners * @since 3.0 */
protected void modifyAnnotationPosition(Annotation annotation, Position position, boolean fireModelChanged) { if (position == null) { removeAnnotation(annotation, fireModelChanged); } else { Position p= fAnnotations.get(annotation); if (p != null) { if (position.getOffset() != p.getOffset() || position.getLength() != p.getLength()) { fDocument.removePosition(p); p.setOffset(position.getOffset()); p.setLength(position.getLength()); try { fDocument.addPosition(p); } catch (BadLocationException e) { // ignore invalid position } } synchronized (getLockObject()) { getAnnotationModelEvent().annotationChanged(annotation); } if (fireModelChanged) fireModelChanged(); } else { try { addAnnotation(annotation, position, fireModelChanged); } catch (BadLocationException x) { // ignore invalid position } } } }
Modifies the given annotation if the annotation is managed by this annotation model.

If requested, all annotation model change listeners will be informed about the change.

Params:
  • annotation – the annotation to be modified
  • fireModelChanged – indicates whether to notify all model listeners
Since:3.0
/** * Modifies the given annotation if the annotation is managed by this * annotation model. * <p> * If requested, all annotation model change listeners will be informed * about the change. * * @param annotation the annotation to be modified * @param fireModelChanged indicates whether to notify all model listeners * @since 3.0 */
protected void modifyAnnotation(Annotation annotation, boolean fireModelChanged) { if (fAnnotations.containsKey(annotation)) { synchronized (getLockObject()) { getAnnotationModelEvent().annotationChanged(annotation); } if (fireModelChanged) fireModelChanged(); } } @Override public void removeAnnotationModelListener(IAnnotationModelListener listener) { fAnnotationModelListeners.remove(listener); } /* * @see org.eclipse.jface.text.source.IAnnotationModelExtension#attach(java.lang.Object, java.lang.Object) * @since 3.0 */ @Override public void addAnnotationModel(Object key, IAnnotationModel attachment) { Assert.isNotNull(attachment); if (!fAttachments.containsValue(attachment)) { fAttachments.put(key, attachment); for (int i= 0; i < fOpenConnections; i++) attachment.connect(fDocument); attachment.addAnnotationModelListener(fModelListener); } } /* * @see org.eclipse.jface.text.source.IAnnotationModelExtension#get(java.lang.Object) * @since 3.0 */ @Override public IAnnotationModel getAnnotationModel(Object key) { return fAttachments.get(key); } /* * @see org.eclipse.jface.text.source.IAnnotationModelExtension#detach(java.lang.Object) * @since 3.0 */ @Override public IAnnotationModel removeAnnotationModel(Object key) { IAnnotationModel ret= fAttachments.remove(key); if (ret != null) { for (int i= 0; i < fOpenConnections; i++) ret.disconnect(fDocument); ret.removeAnnotationModelListener(fModelListener); } return ret; } @Override public Object getModificationStamp() { return fModificationStamp; } }