2 * Copyright (C) 2007 EDIT
3 * European Distributed Institute of Taxonomy
4 * http://www.e-taxonomy.eu
6 * The contents of this file are subject to the Mozilla Public License Version 1.1
7 * See LICENSE.TXT at the top of this package for the full license terms.
10 package eu
.etaxonomy
.taxeditor
.annotatedlineeditor
;
12 import java
.util
.ArrayList
;
13 import java
.util
.Collections
;
14 import java
.util
.Comparator
;
15 import java
.util
.HashSet
;
16 import java
.util
.Iterator
;
17 import java
.util
.List
;
20 import org
.apache
.log4j
.Logger
;
21 import org
.eclipse
.jface
.text
.BadLocationException
;
22 import org
.eclipse
.jface
.text
.IDocument
;
23 import org
.eclipse
.jface
.text
.Position
;
24 import org
.eclipse
.jface
.text
.source
.Annotation
;
25 import org
.eclipse
.jface
.text
.source
.AnnotationModel
;
26 import org
.eclipse
.jface
.text
.source
.AnnotationModelEvent
;
28 import eu
.etaxonomy
.taxeditor
.model
.MessagingUtils
;
31 * An <code>AnnotationModel</code> which holds <code>LineAnnotation</code>'s.
33 * Major difference with <code>AnnotationModel</code> is that <code>removeAnnotation(Annotation annotation,
34 * boolean fireModelChanged)</code> adds annotations marked for removal to a collection for further
35 * processing, i.e. when the document is saved. This collection is accessed via <code>getDeletedAnnotations()</code>
36 * and <code>clearDeletedAnnotations()</code>.
42 public class LineAnnotationModel
extends AnnotationModel
{
44 private Comparator
<Annotation
> comparator
;
45 private IEntityCreator
<?
> entityCreator
;
46 private Set
<LineAnnotation
> deletedAnnotations
= new HashSet
<LineAnnotation
>();
48 private ILineDisplayStrategy lineDisplayStrategy
;
51 * <p>Constructor for LineAnnotationModel.</p>
53 * @param lineDisplayStrategy a {@link eu.etaxonomy.taxeditor.annotatedlineeditor.ILineDisplayStrategy} object.
55 public LineAnnotationModel(ILineDisplayStrategy lineDisplayStrategy
) {
57 this.lineDisplayStrategy
= lineDisplayStrategy
;
61 * Changes the annotation's type and fires model changed
62 * notification. Resulting redraw will cause any change
63 * in annotation's decoration to be displayed.
65 * @param annotation a {@link org.eclipse.jface.text.source.Annotation} object.
66 * @param type a {@link java.lang.String} object.
68 public void changeAnnotationType(Annotation annotation
, String type
) {
69 annotation
.setType(type
);
70 fireModelChanged(new AnnotationModelEvent(this));
74 * @see org.eclipse.jface.text.source.AnnotationModel#removeAnnotation(org.eclipse.jface.text.source.Annotation, boolean)
77 protected void removeAnnotation(Annotation annotation
,
78 boolean fireModelChanged
) {
79 // Set data model element for deletion
80 annotation
.markDeleted(true);
81 if (annotation
instanceof LineAnnotation
) {
82 deletedAnnotations
.add((LineAnnotation
) annotation
);
84 super.removeAnnotation(annotation
, fireModelChanged
);
88 * <p>removeTypeFromAllAnnotations</p>
90 * @param type a {@link java.lang.String} object.
92 public void removeTypeFromAllAnnotations(String type
) {
93 Iterator
<?
> iterator
= getAnnotationIterator();
94 while (iterator
.hasNext()) {
95 Annotation annotation
= ((Annotation
) iterator
.next());
96 if (annotation
.getType().equals(type
)) {
97 annotation
.setType(Annotation
.TYPE_UNKNOWN
);
103 * <p>getAllAnnotationsOfType</p>
105 * @param type a {@link java.lang.String} object.
106 * @return a {@link java.util.Set} object.
108 public Set
<LineAnnotation
> getAllAnnotationsOfType(String type
) {
109 Set
<LineAnnotation
> candidates
= new HashSet
<LineAnnotation
>();
110 Iterator
<?
> iterator
= getAnnotationIterator();
111 while (iterator
.hasNext()) {
112 LineAnnotation annotation
= ((LineAnnotation
) iterator
.next());
113 if (annotation
.getType().equals(type
)) {
114 candidates
.add(annotation
);
121 * <p>getFirstAnnotationOfType</p>
123 * @param type a {@link java.lang.String} object.
124 * @return a {@link org.eclipse.jface.text.source.Annotation} object.
126 public Annotation
getFirstAnnotationOfType(String type
) {
127 Iterator
<?
> iterator
= getAnnotationIterator();
128 while (iterator
.hasNext()) {
129 Annotation annotation
= ((Annotation
) iterator
.next());
130 if (annotation
.getType().equals(type
)) {
138 * Gets first LineAnnotation in line
141 * @param document a {@link org.eclipse.jface.text.IDocument} object.
142 * @return a {@link org.eclipse.jface.text.source.Annotation} object.
144 public Annotation
getAnnotationAtLine(int line
, IDocument document
) {
145 // Annotation annotation = null;
147 int offset
= document
.getLineOffset(line
);
148 int length
= document
.getLineLength(line
);
150 Iterator
<?
> iterator
= getAnnotationIterator(offset
, length
, true, true);
151 while (iterator
.hasNext()) {
152 Object next
= iterator
.next();
153 if (next
instanceof LineAnnotation
) {
154 return (LineAnnotation
) next
;
156 // annotation = (Annotation) iterator.next();
158 } catch (BadLocationException e
) {
165 * <p>getOrderedAnnotations</p>
167 * @return a {@link java.util.List} object.
169 public List
<Annotation
> getOrderedAnnotations() {
170 List
<Annotation
> list
= new ArrayList
<Annotation
>();
171 Iterator
<?
> iterator
= getAnnotationIterator();
172 while (iterator
.hasNext()) {
173 list
.add((Annotation
) iterator
.next());
175 Collections
.sort(list
, getAnnotationComparator());
180 * <p>printAnnotations</p>
182 public void printAnnotations() {
183 Logger logger
= MessagingUtils
.getLog4JLogger(getClass());
184 logger
.debug("------------------------");
185 logger
.debug("Active annotations");
186 logger
.debug("------------------------");
187 List
<Annotation
> list
= getOrderedAnnotations();
189 for (Annotation annotation
: list
) {
191 (annotation
.isMarkedDeleted() ?
"DELETED " : "") +
192 (((LineAnnotation
) annotation
).isMarkedAsMerged() ?
"MERGED " : "") +
193 (((LineAnnotation
) annotation
).isDirty() ?
"DIRTY " : "") +
194 (((LineAnnotation
) annotation
).isMarkedAsNew() ?
"NEW " : "") +
195 annotation
.getText() + ": o " +
196 getPosition(annotation
).getOffset() + ", l " +
197 getPosition(annotation
).getLength());
199 logger
.debug("------------------------");
200 logger
.debug("Deleted annotations");
201 logger
.debug("------------------------");
202 for (LineAnnotation annotation
: deletedAnnotations
) {
204 (annotation
.isMarkedDeleted() ?
"DELETED " : "") +
205 (((LineAnnotation
) annotation
).isMarkedAsMerged() ?
"MERGED " : "") +
206 (((LineAnnotation
) annotation
).isDirty() ?
"DIRTY " : "") +
207 (((LineAnnotation
) annotation
).isMarkedAsNew() ?
"NEW " : "") +
208 annotation
.getText() + ": o ");
213 * <p>getUndeletedAnnotations</p>
215 * @param offset a int.
216 * @param length a int.
217 * @return a {@link java.util.List} object.
219 public List
<LineAnnotation
> getUndeletedAnnotations(int offset
, int length
) {
221 List
<LineAnnotation
> list
= new ArrayList
<LineAnnotation
>();
223 Iterator
<?
> iterator
= getAnnotationIterator(offset
, length
, true, true);
224 while (iterator
.hasNext()) {
225 Object next
= iterator
.next();
226 if (next
instanceof LineAnnotation
&& !((Annotation
) next
).isMarkedDeleted()) {
227 list
.add((LineAnnotation
) next
);
230 Collections
.sort(list
, getAnnotationComparator());
235 * <p>Getter for the field <code>deletedAnnotations</code>.</p>
237 * @return a {@link java.util.Set} object.
239 public Set
<LineAnnotation
> getDeletedAnnotations() {
240 return deletedAnnotations
;
244 * <p>clearDeletedAnnotations</p>
246 public void clearDeletedAnnotations() {
247 deletedAnnotations
.clear();
250 private Comparator
<Annotation
> getAnnotationComparator() {
251 if (comparator
== null) {
252 this.comparator
= new AnnotationComparator();
257 class AnnotationComparator
implements Comparator
<Annotation
> {
260 * @see java.util.Comparator#compare(java.lang.Object, java.lang.Object)
262 public int compare(Annotation annotation1
, Annotation annotation2
) {
263 if (annotation1
.isMarkedDeleted() && !annotation2
.isMarkedDeleted()) {
266 if (!annotation1
.isMarkedDeleted() && annotation2
.isMarkedDeleted()) {
269 int offset1
= LineAnnotationModel
.this.
270 getPosition(annotation1
).getOffset();
271 int offset2
= LineAnnotationModel
.this.
272 getPosition(annotation2
).getOffset();
273 if (offset1
> offset2
) {
275 } else if (offset1
< offset2
) {
284 * The annotation model is assigned responsibility for creating new containers
285 * from blocks of text.
287 * @param entityCreator a {@link eu.etaxonomy.taxeditor.annotatedlineeditor.IEntityCreator} object.
289 public void setEntityCreator(IEntityCreator
<?
> entityCreator
) {
290 this.entityCreator
= entityCreator
;
294 * Creates an annotation without adding it to the model.
296 * This object must have its <code>cdmEntityCreator</code> set.
298 * @param text a {@link java.lang.String} object.
299 * @return a {@link org.eclipse.jface.text.source.Annotation} object.
301 public Annotation
createAnnotation(String text
) {
302 LineAnnotation annotation
= null;
303 if (entityCreator
!= null) {
304 annotation
= new LineAnnotation(entityCreator
.createEntity(text
), lineDisplayStrategy
);
305 annotation
.markAsNew(true);
311 * Creates an annotation without adding it to the model.
313 * @param entity a {@link java.lang.Object} object.
314 * @return a {@link org.eclipse.jface.text.source.Annotation} object.
316 public Annotation
createAnnotation(Object entity
) {
317 LineAnnotation annotation
= new LineAnnotation(entity
, lineDisplayStrategy
);
318 annotation
.markAsNew(true);
323 * @see org.eclipse.jface.text.source.AnnotationModel#addAnnotation(org.eclipse.jface.text.source.Annotation, org.eclipse.jface.text.Position)
327 public void addAnnotation(Annotation annotation
, Position position
) {
328 super.addAnnotation(annotation
, position
);
332 * <p>getAnnotation</p>
334 * @param entity a {@link java.lang.Object} object.
335 * @return a {@link org.eclipse.jface.text.source.Annotation} object.
337 public Annotation
getAnnotation(Object entity
) {
338 if (entity
!= null) {
339 Iterator iterator
= getAnnotationIterator();
340 while (iterator
.hasNext()) {
341 LineAnnotation annotation
= (LineAnnotation
) iterator
.next();
342 if (entity
.equals(annotation
.getEntity())) {