had to rename the packages to make them compliant with buckminster
[taxeditor.git] / eu.etaxonomy.taxeditor.bulkeditor / src / main / java / eu / etaxonomy / taxeditor / annotatedlineeditor / LineAnnotationModel.java
1 // $Id$
2 /**
3 * Copyright (C) 2007 EDIT
4 * European Distributed Institute of Taxonomy
5 * http://www.e-taxonomy.eu
6 *
7 * The contents of this file are subject to the Mozilla Public License Version 1.1
8 * See LICENSE.TXT at the top of this package for the full license terms.
9 */
10
11 package eu.etaxonomy.taxeditor.annotatedlineeditor;
12
13 import java.util.ArrayList;
14 import java.util.Collections;
15 import java.util.Comparator;
16 import java.util.HashSet;
17 import java.util.Iterator;
18 import java.util.List;
19 import java.util.Set;
20
21 import org.apache.log4j.Logger;
22 import org.eclipse.jface.text.BadLocationException;
23 import org.eclipse.jface.text.IDocument;
24 import org.eclipse.jface.text.Position;
25 import org.eclipse.jface.text.source.Annotation;
26 import org.eclipse.jface.text.source.AnnotationModel;
27 import org.eclipse.jface.text.source.AnnotationModelEvent;
28
29 import eu.etaxonomy.taxeditor.bulkeditor.BulkEditorUtil;
30
31 /**
32 * An <code>AnnotationModel</code> which holds <code>LineAnnotation</code>'s.
33 * <p>
34 * Major difference with <code>AnnotationModel</code> is that <code>removeAnnotation(Annotation annotation,
35 * boolean fireModelChanged)</code> adds annotations marked for removal to a collection for further
36 * processing, i.e. when the document is saved. This collection is accessed via <code>getDeletedAnnotations()</code>
37 * and <code>clearDeletedAnnotations()</code>.
38 *
39 * @author p.ciardelli
40 * @created 25.06.2009
41 * @version 1.0
42 */
43 public class LineAnnotationModel extends AnnotationModel {
44
45 private Comparator<Annotation> comparator;
46 private IEntityCreator<?> entityCreator;
47 private Set<LineAnnotation> deletedAnnotations = new HashSet<LineAnnotation>();
48
49 private ILineDisplayStrategy lineDisplayStrategy;
50
51 /**
52 * <p>Constructor for LineAnnotationModel.</p>
53 *
54 * @param lineDisplayStrategy a {@link eu.etaxonomy.taxeditor.annotatedlineeditor.ILineDisplayStrategy} object.
55 */
56 public LineAnnotationModel(ILineDisplayStrategy lineDisplayStrategy) {
57 super();
58 this.lineDisplayStrategy = lineDisplayStrategy;
59 }
60
61 /**
62 * Changes the annotation's type and fires model changed
63 * notification. Resulting redraw will cause any change
64 * in annotation's decoration to be displayed.
65 *
66 * @param annotation a {@link org.eclipse.jface.text.source.Annotation} object.
67 * @param type a {@link java.lang.String} object.
68 */
69 public void changeAnnotationType(Annotation annotation, String type) {
70 annotation.setType(type);
71 fireModelChanged(new AnnotationModelEvent(this));
72 }
73
74 /* (non-Javadoc)
75 * @see org.eclipse.jface.text.source.AnnotationModel#removeAnnotation(org.eclipse.jface.text.source.Annotation, boolean)
76 */
77 /** {@inheritDoc} */
78 protected void removeAnnotation(Annotation annotation,
79 boolean fireModelChanged) {
80 // Set data model element for deletion
81 annotation.markDeleted(true);
82 if (annotation instanceof LineAnnotation) {
83 deletedAnnotations.add((LineAnnotation) annotation);
84 }
85 super.removeAnnotation(annotation, fireModelChanged);
86 }
87
88 /**
89 * <p>removeTypeFromAllAnnotations</p>
90 *
91 * @param type a {@link java.lang.String} object.
92 */
93 public void removeTypeFromAllAnnotations(String type) {
94 Iterator<?> iterator = getAnnotationIterator();
95 while (iterator.hasNext()) {
96 Annotation annotation = ((Annotation) iterator.next());
97 if (annotation.getType().equals(type)) {
98 annotation.setType(Annotation.TYPE_UNKNOWN);
99 }
100 }
101 }
102
103 /**
104 * <p>getAllAnnotationsOfType</p>
105 *
106 * @param type a {@link java.lang.String} object.
107 * @return a {@link java.util.Set} object.
108 */
109 public Set<LineAnnotation> getAllAnnotationsOfType(String type) {
110 Set<LineAnnotation> candidates = new HashSet<LineAnnotation>();
111 Iterator<?> iterator = getAnnotationIterator();
112 while (iterator.hasNext()) {
113 LineAnnotation annotation = ((LineAnnotation) iterator.next());
114 if (annotation.getType().equals(type)) {
115 candidates.add(annotation);
116 }
117 }
118 return candidates;
119 }
120
121 /**
122 * <p>getFirstAnnotationOfType</p>
123 *
124 * @param type a {@link java.lang.String} object.
125 * @return a {@link org.eclipse.jface.text.source.Annotation} object.
126 */
127 public Annotation getFirstAnnotationOfType(String type) {
128 Iterator<?> iterator = getAnnotationIterator();
129 while (iterator.hasNext()) {
130 Annotation annotation = ((Annotation) iterator.next());
131 if (annotation.getType().equals(type)) {
132 return annotation;
133 }
134 }
135 return null;
136 }
137
138 /**
139 * Gets first LineAnnotation in line
140 *
141 * @param line a int.
142 * @param document a {@link org.eclipse.jface.text.IDocument} object.
143 * @return a {@link org.eclipse.jface.text.source.Annotation} object.
144 */
145 public Annotation getAnnotationAtLine(int line, IDocument document) {
146 // Annotation annotation = null;
147 try {
148 int offset = document.getLineOffset(line);
149 int length = document.getLineLength(line);
150
151 Iterator<?> iterator = getAnnotationIterator(offset, length, true, true);
152 while (iterator.hasNext()) {
153 Object next = iterator.next();
154 if (next instanceof LineAnnotation) {
155 return (LineAnnotation) next;
156 }
157 // annotation = (Annotation) iterator.next();
158 }
159 } catch (BadLocationException e) {
160 // do nothing
161 }
162 return null;
163 }
164
165 /**
166 * <p>getOrderedAnnotations</p>
167 *
168 * @return a {@link java.util.List} object.
169 */
170 public List<Annotation> getOrderedAnnotations() {
171 List<Annotation> list = new ArrayList<Annotation>();
172 Iterator<?> iterator = getAnnotationIterator();
173 while (iterator.hasNext()) {
174 list.add((Annotation) iterator.next());
175 }
176 Collections.sort(list, getAnnotationComparator());
177 return list;
178 }
179
180 /**
181 * <p>printAnnotations</p>
182 */
183 public void printAnnotations() {
184 Logger logger = BulkEditorUtil.getLog4JLogger(getClass());
185 logger.debug("------------------------");
186 logger.debug("Active annotations");
187 logger.debug("------------------------");
188 List<Annotation> list = getOrderedAnnotations();
189
190 for (Annotation annotation : list) {
191 logger.debug(
192 (annotation.isMarkedDeleted() ? "DELETED " : "") +
193 (((LineAnnotation) annotation).isMarkedAsMerged() ? "MERGED " : "") +
194 (((LineAnnotation) annotation).isDirty() ? "DIRTY " : "") +
195 (((LineAnnotation) annotation).isMarkedAsNew() ? "NEW " : "") +
196 annotation.getText() + ": o " +
197 getPosition(annotation).getOffset() + ", l " +
198 getPosition(annotation).getLength());
199 }
200 logger.debug("------------------------");
201 logger.debug("Deleted annotations");
202 logger.debug("------------------------");
203 for (LineAnnotation annotation : deletedAnnotations) {
204 logger.debug(
205 (annotation.isMarkedDeleted() ? "DELETED " : "") +
206 (((LineAnnotation) annotation).isMarkedAsMerged() ? "MERGED " : "") +
207 (((LineAnnotation) annotation).isDirty() ? "DIRTY " : "") +
208 (((LineAnnotation) annotation).isMarkedAsNew() ? "NEW " : "") +
209 annotation.getText() + ": o ");
210 }
211 }
212
213 /**
214 * <p>getUndeletedAnnotations</p>
215 *
216 * @param offset a int.
217 * @param length a int.
218 * @return a {@link java.util.List} object.
219 */
220 public List<LineAnnotation> getUndeletedAnnotations(int offset, int length) {
221
222 List<LineAnnotation> list = new ArrayList<LineAnnotation>();
223
224 Iterator<?> iterator = getAnnotationIterator(offset, length, true, true);
225 while (iterator.hasNext()) {
226 Object next = iterator.next();
227 if (next instanceof LineAnnotation && !((Annotation) next).isMarkedDeleted()) {
228 list.add((LineAnnotation) next);
229 }
230 }
231 Collections.sort(list, getAnnotationComparator());
232 return list;
233 }
234
235 /**
236 * <p>Getter for the field <code>deletedAnnotations</code>.</p>
237 *
238 * @return a {@link java.util.Set} object.
239 */
240 public Set<LineAnnotation> getDeletedAnnotations() {
241 return deletedAnnotations;
242 }
243
244 /**
245 * <p>clearDeletedAnnotations</p>
246 */
247 public void clearDeletedAnnotations() {
248 deletedAnnotations.clear();
249 }
250
251 private Comparator<Annotation> getAnnotationComparator() {
252 if (comparator == null) {
253 this.comparator = new AnnotationComparator();
254 }
255 return comparator;
256 }
257
258 class AnnotationComparator implements Comparator<Annotation> {
259
260 /* (non-Javadoc)
261 * @see java.util.Comparator#compare(java.lang.Object, java.lang.Object)
262 */
263 public int compare(Annotation annotation1, Annotation annotation2) {
264 if (annotation1.isMarkedDeleted() && !annotation2.isMarkedDeleted()) {
265 return 1;
266 }
267 if (!annotation1.isMarkedDeleted() && annotation2.isMarkedDeleted()) {
268 return -1;
269 }
270 int offset1 = LineAnnotationModel.this.
271 getPosition(annotation1).getOffset();
272 int offset2 = LineAnnotationModel.this.
273 getPosition(annotation2).getOffset();
274 if (offset1 > offset2) {
275 return 1;
276 } else if (offset1 < offset2) {
277 return -1;
278 } else {
279 return 0;
280 }
281 }
282 }
283
284 /**
285 * The annotation model is assigned responsibility for creating new containers
286 * from blocks of text.
287 *
288 * @param entityCreator a {@link eu.etaxonomy.taxeditor.annotatedlineeditor.IEntityCreator} object.
289 */
290 public void setEntityCreator(IEntityCreator<?> entityCreator) {
291 this.entityCreator = entityCreator;
292 }
293
294 /**
295 * Creates an annotation without adding it to the model.
296 *
297 * This object must have its <code>cdmEntityCreator</code> set.
298 *
299 * @param text a {@link java.lang.String} object.
300 * @return a {@link org.eclipse.jface.text.source.Annotation} object.
301 */
302 public Annotation createAnnotation(String text) {
303 LineAnnotation annotation = null;
304 if (entityCreator != null) {
305 annotation = new LineAnnotation(entityCreator.createEntity(text), lineDisplayStrategy);
306 annotation.markAsNew(true);
307 }
308 return annotation;
309 }
310
311 /**
312 * Creates an annotation without adding it to the model.
313 *
314 * @param entity a {@link java.lang.Object} object.
315 * @return a {@link org.eclipse.jface.text.source.Annotation} object.
316 */
317 public Annotation createAnnotation(Object entity) {
318 LineAnnotation annotation = new LineAnnotation(entity, lineDisplayStrategy);
319 annotation.markAsNew(true);
320 return annotation;
321 }
322
323 /* (non-Javadoc)
324 * @see org.eclipse.jface.text.source.AnnotationModel#addAnnotation(org.eclipse.jface.text.source.Annotation, org.eclipse.jface.text.Position)
325 */
326 /** {@inheritDoc} */
327 @Override
328 public void addAnnotation(Annotation annotation, Position position) {
329 super.addAnnotation(annotation, position);
330 }
331
332 /**
333 * <p>getAnnotation</p>
334 *
335 * @param entity a {@link java.lang.Object} object.
336 * @return a {@link org.eclipse.jface.text.source.Annotation} object.
337 */
338 public Annotation getAnnotation(Object entity) {
339 if (entity != null) {
340 Iterator iterator = getAnnotationIterator();
341 while (iterator.hasNext()) {
342 LineAnnotation annotation = (LineAnnotation) iterator.next();
343 if (entity.equals(annotation.getEntity())) {
344 return annotation;
345 }
346 }
347 }
348 return null;
349 }
350 }