diff options
6 files changed, 336 insertions, 17 deletions
diff --git a/org.eclipse.jface.text/src/org/eclipse/jface/text/ISynchronizable.java b/org.eclipse.jface.text/src/org/eclipse/jface/text/ISynchronizable.java new file mode 100644 index 00000000000..f604aee6631 --- /dev/null +++ b/org.eclipse.jface.text/src/org/eclipse/jface/text/ISynchronizable.java @@ -0,0 +1,36 @@ +/******************************************************************************* + * Copyright (c) 2000, 2003 IBM Corporation and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Common Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/cpl-v10.html + * + * Contributors: + * IBM Corporation - initial API and implementation + *******************************************************************************/ +package org.eclipse.jface.text; + +/** + * Interface for objects which can be set into a synchronized mode when needed. + * For that, the lock object must be set. + * + * @since 3.0 + */ +public interface ISynchronizable { + + /** + * Sets the lock object for this object. If the lock object is not <code>null</code> + * subsequent calls to methods of this object are synchronized on this lock + * object. + * + * @param lockObject the lock object. May be <code>null</code>. + */ + void setLockObject(Object lockObject); + + /** + * Returns the lock object or <code>null</code> if there is none. + * + * @return the lock object or <code>null</code> + */ + Object getLockObject(); +}
\ No newline at end of file diff --git a/org.eclipse.jface.text/src/org/eclipse/jface/text/source/AnnotationMap.java b/org.eclipse.jface.text/src/org/eclipse/jface/text/source/AnnotationMap.java new file mode 100644 index 00000000000..6fa57e17556 --- /dev/null +++ b/org.eclipse.jface.text/src/org/eclipse/jface/text/source/AnnotationMap.java @@ -0,0 +1,185 @@ +/******************************************************************************* + * Copyright (c) 2000, 2003 IBM Corporation and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Common Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/cpl-v10.html + * + * Contributors: + * IBM Corporation - initial API and implementation + *******************************************************************************/ +package org.eclipse.jface.text.source; + +import java.util.ArrayList; +import java.util.Collection; +import java.util.HashMap; +import java.util.Iterator; +import java.util.Map; +import java.util.Set; + +/** + * Internal implementation of <code>IAnnotationMap</code>. + * + * @since 3.0 + */ +class AnnotationMap implements IAnnotationMap { + + /** + * The lock object used to synchronize the operations explicitly defined by + * IAnnotationMap + */ + private Object fLockObject; + + /** The map holding the annotations */ + private Map fInternalMap; + + /** + * Creates a new annotation map with the given capacity. + * + * @param capacity the capacity + */ + public AnnotationMap(int capacity) { + fInternalMap = new HashMap(capacity); + } + + /* + * @see org.eclipse.jface.text.source.ISynchronizable#setLockObject(java.lang.Object) + */ + public void setLockObject(Object lockObject) { + fLockObject = lockObject; + } + + /* + * @see org.eclipse.jface.text.source.ISynchronizable#getLockObject() + */ + public Object getLockObject() { + if (fLockObject == null) return this; + return fLockObject; + } + + /* + * @see org.eclipse.jface.text.source.IAnnotationMap#valuesIterator() + */ + public Iterator valuesIterator() { + synchronized (getLockObject()) { + return new ArrayList(fInternalMap.values()).iterator(); + } + } + + /* + * @see org.eclipse.jface.text.source.IAnnotationMap#keySetIterator() + */ + public Iterator keySetIterator() { + synchronized (getLockObject()) { + return new ArrayList(fInternalMap.keySet()).iterator(); + } + } + + /* + * @see java.util.Map#containsKey(java.lang.Object) + */ + public boolean containsKey(Object annotation) { + synchronized (getLockObject()) { + return fInternalMap.containsKey(annotation); + } + } + + /* + * @see java.util.Map#put(java.lang.Object, java.lang.Object) + */ + public Object put(Object annotation, Object position) { + synchronized (getLockObject()) { + return fInternalMap.put(annotation, position); + } + } + + /* + * @see java.util.Map#get(java.lang.Object) + */ + public Object get(Object annotation) { + synchronized (getLockObject()) { + return fInternalMap.get(annotation); + } + } + + /* + * @see java.util.Map#clear() + */ + public void clear() { + synchronized (getLockObject()) { + fInternalMap.clear(); + } + } + + /* + * @see java.util.Map#remove(java.lang.Object) + */ + public Object remove(Object annotation) { + synchronized (getLockObject()) { + return fInternalMap.remove(annotation); + } + } + + /* + * @see java.util.Map#size() + */ + public int size() { + synchronized (getLockObject()) { + return fInternalMap.size(); + } + } + + /* + * @see java.util.Map#isEmpty() + */ + public boolean isEmpty() { + synchronized (getLockObject()) { + return fInternalMap.isEmpty(); + } + } + + /* + * @see java.util.Map#containsValue(java.lang.Object) + */ + public boolean containsValue(Object value) { + synchronized(getLockObject()) { + return fInternalMap.containsValue(value); + } + } + + /* + * @see java.util.Map#putAll(java.util.Map) + */ + public void putAll(Map map) { + synchronized (getLockObject()) { + fInternalMap.putAll(map); + } + } + + /* + * @see IAnnotationMap#entrySet() + */ + public Set entrySet() { + synchronized (getLockObject()) { + return fInternalMap.entrySet(); + } + } + + /* + * @see IAnnotationMap#keySet() + */ + public Set keySet() { + synchronized (getLockObject()) { + return fInternalMap.keySet(); + } + } + + /* + * @see IAnnotationMap#values() + */ + public Collection values() { + synchronized (getLockObject()) { + return fInternalMap.values(); + } + } +}
\ No newline at end of file diff --git a/org.eclipse.jface.text/src/org/eclipse/jface/text/source/AnnotationModel.java b/org.eclipse.jface.text/src/org/eclipse/jface/text/source/AnnotationModel.java index d1c632dfb46..acb3fbb267d 100644 --- a/org.eclipse.jface.text/src/org/eclipse/jface/text/source/AnnotationModel.java +++ b/org.eclipse.jface.text/src/org/eclipse/jface/text/source/AnnotationModel.java @@ -11,7 +11,6 @@ package org.eclipse.jface.text.source; import java.util.ArrayList; -import java.util.Collections; import java.util.HashMap; import java.util.Iterator; import java.util.List; @@ -23,6 +22,7 @@ import org.eclipse.jface.text.BadLocationException; 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; @@ -31,7 +31,7 @@ import org.eclipse.jface.text.Position; * be used by clients. Subclasses may adapt this annotation model to other existing * annotation mechanisms. */ -public class AnnotationModel implements IAnnotationModel, IAnnotationModelExtension { +public class AnnotationModel implements IAnnotationModel, IAnnotationModelExtension, ISynchronizable { /** * Internal annotation model listener for forwarding annotation model changes from the attached models to the @@ -56,7 +56,10 @@ public class AnnotationModel implements IAnnotationModel, IAnnotationModelExtens } } - /** The list of managed annotations */ + /** + * The list of managed annotations + * @deprecated since 3.0 use <code>getAnnotationMap</code> instead + */ protected Map fAnnotations; /** The list of annotation model listeners */ protected ArrayList fAnnotationModelListeners; @@ -92,7 +95,7 @@ public class AnnotationModel implements IAnnotationModel, IAnnotationModelExtens * manage any annotations and is not connected to any document. */ public AnnotationModel() { - fAnnotations= Collections.synchronizedMap(new HashMap(10)); + fAnnotations= new AnnotationMap(10); fAnnotationModelListeners= new ArrayList(2); fDocumentListener= new IDocumentListener() { @@ -105,6 +108,29 @@ public class AnnotationModel implements IAnnotationModel, IAnnotationModelExtens } }; } + + /** + * Returns the annotation map internally used by this annotation model. + * + * @return the annotation map internally used by this annotation model + */ + protected IAnnotationMap getAnnotationMap() { + return (IAnnotationMap) fAnnotations; + } + + /* + * @see org.eclipse.jface.text.ISynchronizable#getLockObject() + */ + public Object getLockObject() { + return getAnnotationMap().getLockObject(); + } + + /* + * @see org.eclipse.jface.text.ISynchronizable#setLockObject(java.lang.Object) + */ + public void setLockObject(Object lockObject) { + getAnnotationMap().setLockObject(lockObject); + } /* * @see IAnnotationModel#addAnnotation(Annotation, Position) @@ -238,7 +264,7 @@ public class AnnotationModel implements IAnnotationModel, IAnnotationModelExtens if (fDocument == null) { fDocument= document; - Iterator e= fAnnotations.values().iterator(); + Iterator e= getAnnotationMap().valuesIterator(); while (e.hasNext()) try { addPosition(fDocument, (Position) e.next()); @@ -292,7 +318,7 @@ public class AnnotationModel implements IAnnotationModel, IAnnotationModelExtens fDocument.removeDocumentListener(fDocumentListener); if (fDocument != null) { - Iterator e= fAnnotations.values().iterator(); + Iterator e= getAnnotationMap().valuesIterator(); while (e.hasNext()) { Position p= (Position) e.next(); removePosition(fDocument, p); @@ -379,7 +405,7 @@ public class AnnotationModel implements IAnnotationModel, IAnnotationModelExtens fDocumentChanged= false; ArrayList deleted= new ArrayList(); - Iterator e= new ArrayList(fAnnotations.keySet()).iterator(); + Iterator e= getAnnotationMap().keySetIterator(); while (e.hasNext()) { Annotation a= (Annotation) e.next(); Position p= (Position) fAnnotations.get(a); @@ -417,7 +443,7 @@ public class AnnotationModel implements IAnnotationModel, IAnnotationModelExtens List iterators= new ArrayList(fAttachments.size() + 1); iterators.add(getAnnotationIterator(cleanup)); for (Iterator it= fAttachments.keySet().iterator(); it.hasNext();) { - iterators.add(((IAnnotationModel)fAttachments.get(it.next())).getAnnotationIterator()); + iterators.add(((IAnnotationModel) fAttachments.get(it.next())).getAnnotationIterator()); } final Iterator iter= iterators.iterator(); @@ -464,9 +490,7 @@ public class AnnotationModel implements IAnnotationModel, IAnnotationModelExtens if (cleanup) cleanup(true); - synchronized (fAnnotations) { - return new ArrayList(fAnnotations.keySet()).iterator(); - } + return getAnnotationMap().keySetIterator(); } /* @@ -479,7 +503,7 @@ public class AnnotationModel implements IAnnotationModel, IAnnotationModelExtens Iterator it= fAttachments.values().iterator(); while (position == null && it.hasNext()) - position= ((IAnnotationModel)it.next()).getPosition(annotation); + position= ((IAnnotationModel) it.next()).getPosition(annotation); return position; } @@ -500,7 +524,7 @@ public class AnnotationModel implements IAnnotationModel, IAnnotationModelExtens protected void removeAllAnnotations(boolean fireModelChanged) { if (fDocument != null) { - Iterator e= fAnnotations.keySet().iterator(); + Iterator e= getAnnotationMap().keySetIterator(); while (e.hasNext()) { Annotation a= (Annotation) e.next(); Position p= (Position) fAnnotations.get(a); diff --git a/org.eclipse.jface.text/src/org/eclipse/jface/text/source/IAnnotationMap.java b/org.eclipse.jface.text/src/org/eclipse/jface/text/source/IAnnotationMap.java new file mode 100644 index 00000000000..b16b753a709 --- /dev/null +++ b/org.eclipse.jface.text/src/org/eclipse/jface/text/source/IAnnotationMap.java @@ -0,0 +1,71 @@ +/******************************************************************************* + * Copyright (c) 2000, 2003 IBM Corporation and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Common Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/cpl-v10.html + * + * Contributors: + * IBM Corporation - initial API and implementation + *******************************************************************************/ +package org.eclipse.jface.text.source; + +import java.util.Collection; +import java.util.Iterator; +import java.util.Map; +import java.util.Set; + +import org.eclipse.jface.text.ISynchronizable; + +/** + * An annotation map is a map specialized for the requirements of an annotation + * model. The annotation map supports a customizable lock object which is used + * to synchronize concurrent operations on the map. The map supports two + * iterator methods, one for the values and one for the keys of the map. The + * returned iterators are robust, i.e. they work on a copy of the values and + * keys set that is made at the point in time the iterator methods are called. + * <p> + * The returned collections of the methods <code>values</code>,<code>entrySet</code>, + * and <code>keySet</code> are not synchronized on the annotation map's lock + * object. + * <p> + * + * @since 3.0 + */ +public interface IAnnotationMap extends Map, ISynchronizable { + + /** + * Returns an iterator for a copy of this annotation map's values. + * + * @return an iterator for a copy of this map's values + */ + Iterator valuesIterator(); + + /** + * Returns an iterator for a copy of this map's key set. + * + * @return an iterator for a copy of this map's key set + */ + Iterator keySetIterator(); + + /** + * @inheritDoc + * + * The returned set is not synchronized on this annotation map's lock object. + */ + Set entrySet(); + + /** + * @inheritDoc + * + * The returned set is not synchronized on this annotation map's lock object. + */ + Set keySet(); + + /** + * @inheritDoc + * + * The returned collection is not synchronized on this annotation map's lock object. + */ + Collection values(); +}
\ No newline at end of file diff --git a/org.eclipse.jface.text/src/org/eclipse/jface/text/source/VisualAnnotationModel.java b/org.eclipse.jface.text/src/org/eclipse/jface/text/source/VisualAnnotationModel.java index a54a031892e..f757c30fbaf 100644 --- a/org.eclipse.jface.text/src/org/eclipse/jface/text/source/VisualAnnotationModel.java +++ b/org.eclipse.jface.text/src/org/eclipse/jface/text/source/VisualAnnotationModel.java @@ -111,7 +111,7 @@ class VisualAnnotationModel extends AnnotationModel implements IAnnotationModelL */ public Position getPosition(Annotation annotation) { - Position p= (Position) fAnnotations.get(annotation); + Position p= (Position) getAnnotationMap().get(annotation); if (p != null) return p; diff --git a/org.eclipse.ui.editors/src/org/eclipse/ui/texteditor/AbstractMarkerAnnotationModel.java b/org.eclipse.ui.editors/src/org/eclipse/ui/texteditor/AbstractMarkerAnnotationModel.java index c40a3b3a6c4..30412bc2107 100644 --- a/org.eclipse.ui.editors/src/org/eclipse/ui/texteditor/AbstractMarkerAnnotationModel.java +++ b/org.eclipse.ui.editors/src/org/eclipse/ui/texteditor/AbstractMarkerAnnotationModel.java @@ -32,6 +32,7 @@ import org.eclipse.jface.text.IDocument; import org.eclipse.jface.text.Position; import org.eclipse.jface.text.source.Annotation; import org.eclipse.jface.text.source.AnnotationModel; +import org.eclipse.jface.text.source.IAnnotationMap; import org.eclipse.ui.editors.text.EditorsUI; @@ -296,7 +297,7 @@ public abstract class AbstractMarkerAnnotationModel extends AnnotationModel { public Position getMarkerPosition(IMarker marker) { MarkerAnnotation a= getMarkerAnnotation(marker); if (a != null) { - return (Position) fAnnotations.get(a); + return (Position) getAnnotationMap().get(a); } return null; } @@ -513,7 +514,9 @@ public abstract class AbstractMarkerAnnotationModel extends AnnotationModel { Assert.isTrue(fDocument == document); - if (fAnnotations.size() == 0 && fDeletedAnnotations.size() == 0) + IAnnotationMap annotationMap= getAnnotationMap(); + + if (annotationMap.size() == 0 && fDeletedAnnotations.size() == 0) return; if (fMarkerUpdaterSpecifications == null) @@ -527,7 +530,7 @@ public abstract class AbstractMarkerAnnotationModel extends AnnotationModel { if (o instanceof MarkerAnnotation) { MarkerAnnotation a= (MarkerAnnotation) o; IMarker marker= a.getMarker(); - Position position= (Position) fAnnotations.get(a); + Position position= (Position) annotationMap.get(a); if ( !updateMarker(marker, document, position)) { if ( !fDeletedAnnotations.contains(a)) fDeletedAnnotations.add(a); |