Project

General

Profile

Download (12.6 KB) Statistics
| Branch: | Tag: | Revision:
1
/**
2
* Copyright (C) 2007 EDIT
3
* European Distributed Institute of Taxonomy
4
* http://www.e-taxonomy.eu
5
*
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.
8
*/
9
package eu.etaxonomy.taxeditor.annotatedlineeditor;
10

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

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

    
27
import eu.etaxonomy.cdm.api.conversation.ConversationHolder;
28
import eu.etaxonomy.cdm.api.service.exception.ReferencedObjectUndeletableException;
29
import eu.etaxonomy.taxeditor.bulkeditor.input.AbstractBulkEditorInput;
30
import eu.etaxonomy.taxeditor.model.MessagingUtils;
31

    
32

    
33

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

    
53
	private IDocument document;
54

    
55
	private LineAnnotationModel annotationModel;
56

    
57
	private IEntityCreator<?> entityCreator;
58

    
59
	private ILineDisplayStrategy lineDisplayStrategy;
60

    
61
	private final IEditorInput input;
62
	private ConversationHolder conversation;
63

    
64
	/**
65
	 * @return the conversation
66
	 */
67
	public ConversationHolder getConversation() {
68
		return conversation;
69
	}
70

    
71
	/**
72
	 * @param conversation the conversation to set
73
	 */
74
	public void setConversation(ConversationHolder conversation) {
75
		this.conversation = conversation;
76
	}
77

    
78
	/**
79
	 * <p>Constructor for AnnotatedLineDocumentProvider.</p>
80
	 *
81
	 * @param input a {@link org.eclipse.ui.IEditorInput} object.
82
	 */
83
	public AnnotatedLineDocumentProvider(IEditorInput input){
84
		this.input = input;
85
		this.conversation = ((AbstractBulkEditorInput)input).getConversation();
86
	}
87

    
88
	/** {@inheritDoc} */
89
	@Override
90
	public IAnnotationModel getAnnotationModel(Object element) {
91
		if (element == input) {
92

    
93
			// Create model as necessary
94
			if (annotationModel == null) {
95
				annotationModel = new LineAnnotationModel(getLineDisplayStrategy(element));
96
				annotationModel.setEntityCreator(getEntityCreator(input));
97
			}
98
			return annotationModel;
99
		}
100

    
101
		return null;
102
	}
103

    
104
	/** {@inheritDoc} */
105
	@Override
106
	protected IAnnotationModel createAnnotationModel(Object element)
107
			throws CoreException {
108
		return getAnnotationModel(element);
109
	}
110

    
111
	/** {@inheritDoc} */
112
	@Override
113
	public IDocument getDocument(Object element) {
114
		return document;
115
	}
116

    
117
	/** {@inheritDoc} */
118
	@Override
119
	protected IDocument createDocument(Object element) throws CoreException {
120

    
121
		if (element instanceof IEditorInput) {
122
			IEditorInput input = (IEditorInput) element;
123
			document = new Document("");
124
//			IAnnotationModel model = getAnnotationModel(element);
125

    
126
			List<?> entityList = getEntityList(element);
127

    
128
			if(entityList != null){
129
				for (Object entity : entityList) {
130
					try {
131
						createAnnotatedLine(input, entity);
132
					} catch (BadLocationException e) {
133
						MessagingUtils.error(getClass(), "Problems creating annotated line: ", e);
134
					}
135
				}
136
			}
137

    
138
			return document;
139
		}
140
		return null;
141
	}
142

    
143
	/**
144
	 * Creates an annotated line at the end of the document associated with the element
145
	 *
146
	 * @throws org.eclipse.jface.text.BadLocationException if any.
147
	 * @param element a {@link java.lang.Object} object.
148
	 * @param entity a {@link java.lang.Object} object.
149
	 * @return a {@link eu.etaxonomy.taxeditor.annotatedlineeditor.LineAnnotation} object.
150
	 */
151
	public LineAnnotation createAnnotatedLine(Object element, Object entity) throws BadLocationException {
152

    
153
		Document document = (Document) getDocument(element);
154
		ILineDisplayStrategy lineDisplayStrategy = getLineDisplayStrategy(element);
155

    
156
		LineAnnotation annotation = new LineAnnotation(entity, lineDisplayStrategy);
157

    
158
		// Is document zero length, or is last char in document line delimiter?
159
		int docLength = document.getLength();
160
		boolean useDelimiter = false;
161
		if (docLength > 0) {
162
			if (docLength > 1 && !document.get(docLength - 2, 2).equals(document.getDefaultLineDelimiter())) {
163
				useDelimiter = true;
164
			}
165
		}
166
		if (useDelimiter) {
167
			document.replace(docLength, 0, document.getDefaultLineDelimiter());
168
		}
169

    
170
		String text;
171
		if (lineDisplayStrategy.isEntityCacheEmpty(entity)) {
172
			text = lineDisplayStrategy.getEmptyCacheMessage(entity);
173
		} else {
174
			text = lineDisplayStrategy.getText(entity);
175
		}
176
		text += lineDisplayStrategy.getSupplementalText(entity);
177
		docLength = document.getLength();
178
		document.replace(docLength, 0, text);
179

    
180
		Position position = new Position(docLength, text.length());
181

    
182
		IAnnotationModel model = getAnnotationModel(element);
183
		if(model != null){
184
			model.addAnnotation(annotation, position);
185
		}
186

    
187
//		lineDisplayStrategy.addDisplayListener(entity,
188
//						new EntityListenerImpl((LineAnnotation) annotation, element));
189
//
190
		return annotation;
191
	}
192

    
193

    
194
	/**
195
	 * <p>updateLineFromAnnotation</p>
196
	 *
197
	 * @param annotation a {@link eu.etaxonomy.taxeditor.annotatedlineeditor.LineAnnotation} object.
198
	 */
199
	public void updateLineFromAnnotation(LineAnnotation annotation) {
200

    
201
		IAnnotationModel model = getAnnotationModel(input);
202
		IDocument document = getDocument(input);
203
		ILineDisplayStrategy lineDisplay = getLineDisplayStrategy(input);
204

    
205
		Object entity = annotation.getEntity();
206
		String text = "";
207
		if (getLineDisplayStrategy(input).isEntityCacheEmpty(entity)) {
208
			text = lineDisplay.getEmptyCacheMessage(entity);
209
		} else {
210
			text = lineDisplay.getText(entity);
211
		}
212
		text += lineDisplay.getSupplementalText(entity);
213

    
214
		try {
215
			if (model.getPosition(annotation) == null) {
216
				return;
217
			}
218
			int offset = model.getPosition(annotation).getOffset();
219
			int line = document.getLineOfOffset(offset);
220
			int lineLength = document.getLineLength(document.getLineOfOffset(offset));
221
			if (document.getLineDelimiter(line) != null) {
222
				lineLength -= document.getLineDelimiter(line).length();
223
			}
224
			document.replace(offset, lineLength, text);
225
		} catch (BadLocationException e) {
226
			MessagingUtils.error(getClass(), "Problem updating annotated line: " ,e);
227
		}
228
	}
229

    
230
	/**
231
	 * @param element
232
	 * @return
233
	 */
234
	private List<?> getEntityList(Object element) {
235
		if (element instanceof AbstractBulkEditorInput) {
236
			return ((AbstractBulkEditorInput)element).getModel();
237
		}
238
		return null;
239
	}
240

    
241
	/** {@inheritDoc} */
242
	@Override
243
	protected void doSaveDocument(IProgressMonitor monitor, Object element,
244
			IDocument document, boolean overwrite) throws CoreException {
245
		if (element instanceof AbstractBulkEditorInput) {
246

    
247
			IEntityPersistenceService persistenceService = (AbstractBulkEditorInput) element;
248

    
249
			// Get new containers from annotation model
250
			LineAnnotationModel model = (LineAnnotationModel) getAnnotationModel(element);
251
			Iterator iterator = model.getAnnotationIterator();
252
			if (!this.conversation.isBound()){
253
				this.conversation.bind();
254
			}
255

    
256
			while (iterator.hasNext()) {
257
				Annotation annotation = (Annotation) iterator.next();
258
				if (annotation instanceof IEntityContainer<?>) {
259
					IEntityContainer<?> container = (IEntityContainer<?>) annotation;
260

    
261
					if (container.isMarkedAsNew() || container.isDirty()) {
262

    
263
						Object entity = persistenceService.save(container.getEntity()); // save
264
						container.setEntity(entity);
265
						container.setDirty(false);
266
						container.markAsNew(false);
267
					}
268
				}
269
			}
270
			this.conversation.commit(true);
271
			for (LineAnnotation annotation : model.getDeletedAnnotations()) {
272
				if (annotation.isMarkedAsNew()) {
273
					continue;
274
				}
275
				if (annotation.isMarkedAsMerged()) {
276
					persistenceService.merge(annotation.getEntity(), annotation.getMergeTarget()); //  merge
277
				}
278
				if (annotation.isMarkedAsDeleted()) {
279
					try {
280
						persistenceService.delete(annotation.getEntity(), annotation.getDeleteConfigurator());
281
					} catch (ReferencedObjectUndeletableException e) {
282
						// TODO Auto-generated catch block
283
						e.printStackTrace();
284
					} //  merge
285
				}
286

    
287
				else {
288
					// TODO clarify w AM whether this needs to be executed on merged objects
289
					//persistenceService.delete(annotation.getEntity()); // delete
290
				}
291
			}
292
			model.clearDeletedAnnotations();
293
		}
294
	}
295

    
296
	/** {@inheritDoc} */
297
	@Override
298
	protected IRunnableContext getOperationRunner(IProgressMonitor monitor) {
299
		return null;
300
	}
301

    
302
	/** {@inheritDoc} */
303
	@Override
304
	public boolean isModifiable(Object element) {
305
		return true;
306
	}
307

    
308
	/** {@inheritDoc} */
309
	@Override
310
	public boolean isReadOnly(Object element) {
311
		// enables copy & paste
312
		return false;
313
	}
314

    
315
	/**
316
	 * <p>Getter for the field <code>entityCreator</code>.</p>
317
	 *
318
	 * @param element a {@link java.lang.Object} object.
319
	 * @return a {@link eu.etaxonomy.taxeditor.annotatedlineeditor.IEntityCreator} object.
320
	 */
321
	public IEntityCreator<?> getEntityCreator(IEditorInput input) {
322
		if (input instanceof AbstractBulkEditorInput) {
323
			entityCreator = ((AbstractBulkEditorInput) input).getEntityCreator();
324
		}
325
		return entityCreator;
326
	}
327

    
328
	/**
329
	 * <p>Setter for the field <code>lineDisplayStrategy</code>.</p>
330
	 *
331
	 * @param lineDisplayStrategy a {@link eu.etaxonomy.taxeditor.annotatedlineeditor.ILineDisplayStrategy} object.
332
	 * @param element a {@link java.lang.Object} object.
333
	 */
334
	public void setLineDisplayStrategy(
335
			ILineDisplayStrategy lineDisplayStrategy, Object element) {
336
		if (element instanceof IEditorInput) {
337
			this.lineDisplayStrategy = lineDisplayStrategy;
338
		}
339
	}
340

    
341
	/**
342
	 * <p>Getter for the field <code>lineDisplayStrategy</code>.</p>
343
	 *
344
	 * @param element a {@link java.lang.Object} object.
345
	 * @return a {@link eu.etaxonomy.taxeditor.annotatedlineeditor.ILineDisplayStrategy} object.
346
	 */
347
	protected ILineDisplayStrategy getLineDisplayStrategy(Object element) {
348
		if (element instanceof IEditorInput) {
349
			Assert.isNotNull(lineDisplayStrategy, "No ILineDisplayStrategy set for this element.");
350
			return lineDisplayStrategy;
351
		}
352
		return null;
353
	}
354

    
355
	/**
356
	 * <p>removeAnnotatedLine</p>
357
	 *
358
	 * @param entity a {@link java.lang.Object} object.
359
	 */
360
	public void removeAnnotatedLine(Object entity){
361
		LineAnnotation annotation = (LineAnnotation) annotationModel.getAnnotation(entity);
362
		removeAnnotatedLine(annotation);
363
	}
364

    
365
	/**
366
	 * <p>removeAnnotatedLine</p>
367
	 *
368
	 * @param lineno a int.
369
	 * @param element a {@link java.lang.Object} object.
370
	 */
371
	public void removeAnnotatedLine(Object element, int lineno) {
372
		LineAnnotation annotation = (LineAnnotation) annotationModel.getAnnotationAtLine(lineno, document);
373
		removeAnnotatedLine(annotation);
374
	}
375

    
376
	/**
377
	 * <p>removeAnnotatedLine</p>
378
	 *
379
	 * @param annotation a {@link eu.etaxonomy.taxeditor.annotatedlineeditor.LineAnnotation} object.
380
	 */
381
	public void removeAnnotatedLine(LineAnnotation annotation) {
382
		if (annotation != null) {
383
			Document document = (Document) getDocument(input);
384
			LineAnnotationModel model = (LineAnnotationModel) getAnnotationModel(input);
385

    
386
			Position position = model.getPosition(annotation);
387
			int offset = position.getOffset();
388
			int length = position.getLength();
389

    
390
			Object entity = annotation.getEntity();
391
			//annotation.markAsDeleted(configurator);
392
			model.removeAnnotation(annotation);
393

    
394
			// Immediately followed by a delimiter?
395
			int annotationEnd = offset + length;
396
			try {
397
				if (document.getLength() > annotationEnd + 1 && document.get(annotationEnd, 2).equals(document.getDefaultLineDelimiter())) {
398
					length += 2;
399
				}
400
			} catch (BadLocationException e1) {
401
				MessagingUtils.error(getClass(), "Problems removing annotated line", e1);
402
			}
403

    
404
			try {
405

    
406
				document.replace(offset, length, "");
407

    
408
			} catch (BadLocationException e) {
409
				MessagingUtils.error(getClass(), "Problems removing annotated line", e);
410
			}
411
		}
412
	}
413

    
414
	/* (non-Javadoc)
415
	 * @see org.eclipse.ui.texteditor.AbstractDocumentProvider#changed(java.lang.Object)
416
	 */
417
	/** {@inheritDoc} */
418
	@Override
419
	public void changed(Object entity) {
420
		LineAnnotation annotation = (LineAnnotation) annotationModel.getAnnotation(entity);
421
		if(annotation != null){
422
			annotation.setDirty(true);
423
			updateLineFromAnnotation(annotation);
424
		}
425
	}
426

    
427

    
428
}
(1-1/16)