Project

General

Profile

Download (11.7 KB) Statistics
| Branch: | Tag: | Revision:
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
package eu.etaxonomy.taxeditor.annotatedlineeditor;
11

    
12
import java.util.Iterator;
13
import java.util.List;
14

    
15
import org.eclipse.core.runtime.Assert;
16
import org.eclipse.core.runtime.CoreException;
17
import org.eclipse.core.runtime.IProgressMonitor;
18
import org.eclipse.jface.operation.IRunnableContext;
19
import org.eclipse.jface.text.BadLocationException;
20
import org.eclipse.jface.text.Document;
21
import org.eclipse.jface.text.IDocument;
22
import org.eclipse.jface.text.Position;
23
import org.eclipse.jface.text.source.Annotation;
24
import org.eclipse.jface.text.source.IAnnotationModel;
25
import org.eclipse.ui.IEditorInput;
26
import org.eclipse.ui.texteditor.AbstractDocumentProvider;
27

    
28
import eu.etaxonomy.taxeditor.bulkeditor.input.AbstractBulkEditorInput;
29
import eu.etaxonomy.taxeditor.model.MessagingUtils;
30

    
31

    
32

    
33
/**
34
 * Using an <code>IEditorPart</code>, creates a document where each line is associated
35
 * with an entity. Mapping between document positions and entities is stored in
36
 * <code>LineAnnotation</code>s in a <code>LineAnnotationModel</code>.
37
 * <p>
38
 * Requires:
39
 * <ul>
40
 * <li>an <code>IEntityCreator</code> to create entities for new lines;
41
 * <li>an <code>IEntityPersistenceService</code> for interacting with the persistence layer; and
42
 * <li>an <code>ILineDisplayStrategy</code> for various visual manifestations of the domain object.
43
 * </ul>
44
 *
45
 * @author p.ciardelli
46
 * @author n.hoffmann
47
 * @created 25.06.2009
48
 * @version 1.0
49
 */
50
public class AnnotatedLineDocumentProvider extends AbstractDocumentProvider {
51

    
52
	private IDocument document;
53

    
54
	private LineAnnotationModel annotationModel;
55

    
56
	private IEntityCreator<?> entityCreator;
57

    
58
	private ILineDisplayStrategy lineDisplayStrategy;
59

    
60
	private final IEditorInput input;
61

    
62
	/**
63
	 * <p>Constructor for AnnotatedLineDocumentProvider.</p>
64
	 *
65
	 * @param input a {@link org.eclipse.ui.IEditorInput} object.
66
	 */
67
	public AnnotatedLineDocumentProvider(IEditorInput input){
68
		this.input = input;
69
	}
70

    
71
	/** {@inheritDoc} */
72
	@Override
73
	public IAnnotationModel getAnnotationModel(Object element) {
74
		if (element == input) {
75

    
76
			// Create model as necessary
77
			if (annotationModel == null) {
78
				annotationModel = new LineAnnotationModel(getLineDisplayStrategy(element));
79
				annotationModel.setEntityCreator(getEntityCreator(input));
80
			}
81
			return annotationModel;
82
		}
83

    
84
		return null;
85
	}
86

    
87
	/** {@inheritDoc} */
88
	@Override
89
	protected IAnnotationModel createAnnotationModel(Object element)
90
			throws CoreException {
91
		return getAnnotationModel(element);
92
	}
93

    
94
	/** {@inheritDoc} */
95
	@Override
96
	public IDocument getDocument(Object element) {
97
		return document;
98
	}
99

    
100
	/** {@inheritDoc} */
101
	@Override
102
	protected IDocument createDocument(Object element) throws CoreException {
103

    
104
		if (element instanceof IEditorInput) {
105
			IEditorInput input = (IEditorInput) element;
106
			document = new Document("");
107
//			IAnnotationModel model = getAnnotationModel(element);
108

    
109
			List<?> entityList = getEntityList(element);
110

    
111
			if(entityList != null){
112
				for (Object entity : entityList) {
113
					try {
114
						createAnnotatedLine(input, entity);
115
					} catch (BadLocationException e) {
116
						MessagingUtils.error(getClass(), "Problems creating annotated line: ", e);
117
					}
118
				}
119
			}
120

    
121
			return document;
122
		}
123
		return null;
124
	}
125

    
126
	/**
127
	 * Creates an annotated line at the end of the document associated with the element
128
	 *
129
	 * @throws org.eclipse.jface.text.BadLocationException if any.
130
	 * @param element a {@link java.lang.Object} object.
131
	 * @param entity a {@link java.lang.Object} object.
132
	 * @return a {@link eu.etaxonomy.taxeditor.annotatedlineeditor.LineAnnotation} object.
133
	 */
134
	protected LineAnnotation createAnnotatedLine(Object element, Object entity) throws BadLocationException {
135

    
136
		Document document = (Document) getDocument(element);
137
		ILineDisplayStrategy lineDisplayStrategy = getLineDisplayStrategy(element);
138

    
139
		LineAnnotation annotation = new LineAnnotation(entity, lineDisplayStrategy);
140

    
141
		// Is document zero length, or is last char in document line delimiter?
142
		int docLength = document.getLength();
143
		boolean useDelimiter = false;
144
		if (docLength > 0) {
145
			if (docLength > 1 && !document.get(docLength - 2, 2).equals(document.getDefaultLineDelimiter())) {
146
				useDelimiter = true;
147
			}
148
		}
149
		if (useDelimiter) {
150
			document.replace(docLength, 0, document.getDefaultLineDelimiter());
151
		}
152

    
153
		String text;
154
		if (lineDisplayStrategy.isEntityCacheEmpty(entity)) {
155
			text = lineDisplayStrategy.getEmptyCacheMessage(entity);
156
		} else {
157
			text = lineDisplayStrategy.getText(entity);
158
		}
159
		text += lineDisplayStrategy.getSupplementalText(entity);
160
		docLength = document.getLength();
161
		document.replace(docLength, 0, text);
162

    
163
		Position position = new Position(docLength, text.length());
164

    
165
		IAnnotationModel model = getAnnotationModel(element);
166
		if(model != null){
167
			model.addAnnotation(annotation, position);
168
		}
169

    
170
//		lineDisplayStrategy.addDisplayListener(entity,
171
//						new EntityListenerImpl((LineAnnotation) annotation, element));
172
//
173
		return annotation;
174
	}
175

    
176

    
177
	/**
178
	 * <p>updateLineFromAnnotation</p>
179
	 *
180
	 * @param annotation a {@link eu.etaxonomy.taxeditor.annotatedlineeditor.LineAnnotation} object.
181
	 */
182
	public void updateLineFromAnnotation(LineAnnotation annotation) {
183

    
184
		IAnnotationModel model = getAnnotationModel(input);
185
		IDocument document = getDocument(input);
186
		ILineDisplayStrategy lineDisplay = getLineDisplayStrategy(input);
187

    
188
		Object entity = annotation.getEntity();
189
		String text = "";
190
		if (getLineDisplayStrategy(input).isEntityCacheEmpty(entity)) {
191
			text = lineDisplay.getEmptyCacheMessage(entity);
192
		} else {
193
			text = lineDisplay.getText(entity);
194
		}
195
		text += lineDisplay.getSupplementalText(entity);
196

    
197
		try {
198
			if (model.getPosition(annotation) == null) {
199
				return;
200
			}
201
			int offset = model.getPosition(annotation).getOffset();
202
			int line = document.getLineOfOffset(offset);
203
			int lineLength = document.getLineLength(document.getLineOfOffset(offset));
204
			if (document.getLineDelimiter(line) != null) {
205
				lineLength -= document.getLineDelimiter(line).length();
206
			}
207
			document.replace(offset, lineLength, text);
208
		} catch (BadLocationException e) {
209
			MessagingUtils.error(getClass(), "Problem updating annotated line: " ,e);
210
		}
211
	}
212

    
213
	/**
214
	 * @param element
215
	 * @return
216
	 */
217
	private List<?> getEntityList(Object element) {
218
		if (element instanceof AbstractBulkEditorInput) {
219
			return ((AbstractBulkEditorInput)element).getModel();
220
		}
221
		return null;
222
	}
223

    
224
	/** {@inheritDoc} */
225
	@Override
226
	protected void doSaveDocument(IProgressMonitor monitor, Object element,
227
			IDocument document, boolean overwrite) throws CoreException {
228
		if (element instanceof AbstractBulkEditorInput) {
229

    
230
			IEntityPersistenceService persistenceService = (AbstractBulkEditorInput) element;
231

    
232
			// Get new containers from annotation model
233
			LineAnnotationModel model = (LineAnnotationModel) getAnnotationModel(element);
234
			Iterator iterator = model.getAnnotationIterator();
235
			while (iterator.hasNext()) {
236
				Annotation annotation = (Annotation) iterator.next();
237
				if (annotation instanceof IEntityContainer<?>) {
238
					IEntityContainer<?> container = (IEntityContainer<?>) annotation;
239
					if (container.isMarkedAsNew() || container.isDirty()) {
240
						Object entity = persistenceService.save(container.getEntity()); // save
241
						container.setEntity(entity);
242
						container.setDirty(false);
243
						container.markAsNew(false);
244
					}
245
				}
246
			}
247
			for (LineAnnotation annotation : model.getDeletedAnnotations()) {
248
				if (annotation.isMarkedAsNew()) {
249
					continue;
250
				}
251
				if (annotation.isMarkedAsMerged()) {
252
					persistenceService.merge(annotation.getEntity(), annotation.getMergeTarget()); //  merge
253
				} else {
254
					// TODO clarify w AM whether this needs to be executed on merged objects
255
					//persistenceService.delete(annotation.getEntity()); // delete
256
				}
257
			}
258
			model.clearDeletedAnnotations();
259
		}
260
	}
261

    
262
	/** {@inheritDoc} */
263
	@Override
264
	protected IRunnableContext getOperationRunner(IProgressMonitor monitor) {
265
		return null;
266
	}
267

    
268
	/** {@inheritDoc} */
269
	@Override
270
	public boolean isModifiable(Object element) {
271
		return true;
272
	}
273

    
274
	/** {@inheritDoc} */
275
	@Override
276
	public boolean isReadOnly(Object element) {
277
		// enables copy & paste
278
		return false;
279
	}
280

    
281
	/**
282
	 * <p>Getter for the field <code>entityCreator</code>.</p>
283
	 *
284
	 * @param element a {@link java.lang.Object} object.
285
	 * @return a {@link eu.etaxonomy.taxeditor.annotatedlineeditor.IEntityCreator} object.
286
	 */
287
	public IEntityCreator<?> getEntityCreator(IEditorInput input) {
288
		if (input instanceof AbstractBulkEditorInput) {
289
			entityCreator = ((AbstractBulkEditorInput) input).getEntityCreator();
290
		}
291
		return entityCreator;
292
	}
293

    
294
	/**
295
	 * <p>Setter for the field <code>lineDisplayStrategy</code>.</p>
296
	 *
297
	 * @param lineDisplayStrategy a {@link eu.etaxonomy.taxeditor.annotatedlineeditor.ILineDisplayStrategy} object.
298
	 * @param element a {@link java.lang.Object} object.
299
	 */
300
	public void setLineDisplayStrategy(
301
			ILineDisplayStrategy lineDisplayStrategy, Object element) {
302
		if (element instanceof IEditorInput) {
303
			this.lineDisplayStrategy = lineDisplayStrategy;
304
		}
305
	}
306

    
307
	/**
308
	 * <p>Getter for the field <code>lineDisplayStrategy</code>.</p>
309
	 *
310
	 * @param element a {@link java.lang.Object} object.
311
	 * @return a {@link eu.etaxonomy.taxeditor.annotatedlineeditor.ILineDisplayStrategy} object.
312
	 */
313
	protected ILineDisplayStrategy getLineDisplayStrategy(Object element) {
314
		if (element instanceof IEditorInput) {
315
			Assert.isNotNull(lineDisplayStrategy, "No ILineDisplayStrategy set for this element.");
316
			return lineDisplayStrategy;
317
		}
318
		return null;
319
	}
320

    
321
	/**
322
	 * <p>removeAnnotatedLine</p>
323
	 *
324
	 * @param entity a {@link java.lang.Object} object.
325
	 */
326
	public void removeAnnotatedLine(Object entity){
327
		LineAnnotation annotation = (LineAnnotation) annotationModel.getAnnotation(entity);
328
		removeAnnotatedLine(annotation);
329
	}
330

    
331
	/**
332
	 * <p>removeAnnotatedLine</p>
333
	 *
334
	 * @param lineno a int.
335
	 * @param element a {@link java.lang.Object} object.
336
	 */
337
	public void removeAnnotatedLine(Object element, int lineno) {
338
		LineAnnotation annotation = (LineAnnotation) annotationModel.getAnnotationAtLine(lineno, document);
339
		removeAnnotatedLine(annotation);
340
	}
341

    
342
	/**
343
	 * <p>removeAnnotatedLine</p>
344
	 *
345
	 * @param annotation a {@link eu.etaxonomy.taxeditor.annotatedlineeditor.LineAnnotation} object.
346
	 */
347
	public void removeAnnotatedLine(LineAnnotation annotation) {
348
		if (annotation != null) {
349
			Document document = (Document) getDocument(input);
350
			LineAnnotationModel model = (LineAnnotationModel) getAnnotationModel(input);
351

    
352
			Position position = model.getPosition(annotation);
353
			int offset = position.getOffset();
354
			int length = position.getLength();
355

    
356
			Object entity = annotation.getEntity();
357
			annotation.markAsDeleted();
358
			model.removeAnnotation(annotation);
359

    
360
			// Immediately followed by a delimiter?
361
			int annotationEnd = offset + length;
362
			try {
363
				if (document.getLength() > annotationEnd + 1 && document.get(annotationEnd, 2).equals(document.getDefaultLineDelimiter())) {
364
					length += 2;
365
				}
366
			} catch (BadLocationException e1) {
367
				MessagingUtils.error(getClass(), "Problems removing annotated line", e1);
368
			}
369

    
370
			try {
371
				document.replace(offset, length, "");
372
			} catch (BadLocationException e) {
373
				MessagingUtils.error(getClass(), "Problems removing annotated line", e);
374
			}
375
		}
376
	}
377

    
378
	/* (non-Javadoc)
379
	 * @see org.eclipse.ui.texteditor.AbstractDocumentProvider#changed(java.lang.Object)
380
	 */
381
	/** {@inheritDoc} */
382
	@Override
383
	public void changed(Object entity) {
384
		LineAnnotation annotation = (LineAnnotation) annotationModel.getAnnotation(entity);
385
		if(annotation != null){
386
			annotation.setDirty(true);
387
			updateLineFromAnnotation(annotation);
388
		}
389
	}
390
}
(1-1/16)