Project

General

Profile

Download (12.7 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.config.DeleteConfiguratorBase;
29
import eu.etaxonomy.cdm.api.service.exception.ReferencedObjectUndeletableException;
30
import eu.etaxonomy.taxeditor.bulkeditor.input.AbstractBulkEditorInput;
31
import eu.etaxonomy.taxeditor.model.MessagingUtils;
32

    
33

    
34

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

    
54
	private IDocument document;
55

    
56
	private LineAnnotationModel annotationModel;
57

    
58
	private IEntityCreator<?> entityCreator;
59

    
60
	private ILineDisplayStrategy lineDisplayStrategy;
61

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

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

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

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

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

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

    
102
		return null;
103
	}
104

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

    
194

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

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

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

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

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

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

    
248
			IEntityPersistenceService persistenceService = (AbstractBulkEditorInput) element;
249

    
250
			// Get new containers from annotation model
251
			LineAnnotationModel model = (LineAnnotationModel) getAnnotationModel(element);
252
			Iterator iterator = model.getAnnotationIterator();
253
			if (!this.conversation.isBound()){
254
				this.conversation.bind();
255
			}
256
			
257
			while (iterator.hasNext()) {
258
				Annotation annotation = (Annotation) iterator.next();
259
				if (annotation instanceof IEntityContainer<?>) {
260
					IEntityContainer<?> container = (IEntityContainer<?>) annotation;
261
					
262
					if (container.isMarkedAsNew() || container.isDirty()) {
263
						
264
						Object entity = persistenceService.save(container.getEntity()); // save
265
						container.setEntity(entity);
266
						container.setDirty(false);
267
						container.markAsNew(false);
268
					}
269
				}
270
			}
271
			this.conversation.commit(true);
272
			for (LineAnnotation annotation : model.getDeletedAnnotations()) {
273
				if (annotation.isMarkedAsNew()) {
274
					continue;
275
				}
276
				if (annotation.isMarkedAsMerged()) {
277
					persistenceService.merge(annotation.getEntity(), annotation.getMergeTarget()); //  merge
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)