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.
9 package eu
.etaxonomy
.taxeditor
.annotatedlineeditor
;
11 import java
.util
.Iterator
;
12 import java
.util
.List
;
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
;
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
;
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>.
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.
52 public class AnnotatedLineDocumentProvider
extends AbstractDocumentProvider
{
54 private IDocument document
;
56 private LineAnnotationModel annotationModel
;
58 private IEntityCreator
<?
> entityCreator
;
60 private ILineDisplayStrategy lineDisplayStrategy
;
62 private final IEditorInput input
;
63 private ConversationHolder conversation
;
66 * @return the conversation
68 public ConversationHolder
getConversation() {
73 * @param conversation the conversation to set
75 public void setConversation(ConversationHolder conversation
) {
76 this.conversation
= conversation
;
80 * <p>Constructor for AnnotatedLineDocumentProvider.</p>
82 * @param input a {@link org.eclipse.ui.IEditorInput} object.
84 public AnnotatedLineDocumentProvider(IEditorInput input
){
86 this.conversation
= ((AbstractBulkEditorInput
)input
).getConversation();
91 public IAnnotationModel
getAnnotationModel(Object element
) {
92 if (element
== input
) {
94 // Create model as necessary
95 if (annotationModel
== null) {
96 annotationModel
= new LineAnnotationModel(getLineDisplayStrategy(element
));
97 annotationModel
.setEntityCreator(getEntityCreator(input
));
99 return annotationModel
;
107 protected IAnnotationModel
createAnnotationModel(Object element
)
108 throws CoreException
{
109 return getAnnotationModel(element
);
114 public IDocument
getDocument(Object element
) {
120 protected IDocument
createDocument(Object element
) throws CoreException
{
122 if (element
instanceof IEditorInput
) {
123 IEditorInput input
= (IEditorInput
) element
;
124 document
= new Document("");
125 // IAnnotationModel model = getAnnotationModel(element);
127 List
<?
> entityList
= getEntityList(element
);
129 if(entityList
!= null){
130 for (Object entity
: entityList
) {
132 createAnnotatedLine(input
, entity
);
133 } catch (BadLocationException e
) {
134 MessagingUtils
.error(getClass(), "Problems creating annotated line: ", e
);
145 * Creates an annotated line at the end of the document associated with the element
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.
152 protected LineAnnotation
createAnnotatedLine(Object element
, Object entity
) throws BadLocationException
{
154 Document document
= (Document
) getDocument(element
);
155 ILineDisplayStrategy lineDisplayStrategy
= getLineDisplayStrategy(element
);
157 LineAnnotation annotation
= new LineAnnotation(entity
, lineDisplayStrategy
);
159 // Is document zero length, or is last char in document line delimiter?
160 int docLength
= document
.getLength();
161 boolean useDelimiter
= false;
163 if (docLength
> 1 && !document
.get(docLength
- 2, 2).equals(document
.getDefaultLineDelimiter())) {
168 document
.replace(docLength
, 0, document
.getDefaultLineDelimiter());
172 if (lineDisplayStrategy
.isEntityCacheEmpty(entity
)) {
173 text
= lineDisplayStrategy
.getEmptyCacheMessage(entity
);
175 text
= lineDisplayStrategy
.getText(entity
);
177 text
+= lineDisplayStrategy
.getSupplementalText(entity
);
178 docLength
= document
.getLength();
179 document
.replace(docLength
, 0, text
);
181 Position position
= new Position(docLength
, text
.length());
183 IAnnotationModel model
= getAnnotationModel(element
);
185 model
.addAnnotation(annotation
, position
);
188 // lineDisplayStrategy.addDisplayListener(entity,
189 // new EntityListenerImpl((LineAnnotation) annotation, element));
196 * <p>updateLineFromAnnotation</p>
198 * @param annotation a {@link eu.etaxonomy.taxeditor.annotatedlineeditor.LineAnnotation} object.
200 public void updateLineFromAnnotation(LineAnnotation annotation
) {
202 IAnnotationModel model
= getAnnotationModel(input
);
203 IDocument document
= getDocument(input
);
204 ILineDisplayStrategy lineDisplay
= getLineDisplayStrategy(input
);
206 Object entity
= annotation
.getEntity();
208 if (getLineDisplayStrategy(input
).isEntityCacheEmpty(entity
)) {
209 text
= lineDisplay
.getEmptyCacheMessage(entity
);
211 text
= lineDisplay
.getText(entity
);
213 text
+= lineDisplay
.getSupplementalText(entity
);
216 if (model
.getPosition(annotation
) == null) {
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();
225 document
.replace(offset
, lineLength
, text
);
226 } catch (BadLocationException e
) {
227 MessagingUtils
.error(getClass(), "Problem updating annotated line: " ,e
);
235 private List
<?
> getEntityList(Object element
) {
236 if (element
instanceof AbstractBulkEditorInput
) {
237 return ((AbstractBulkEditorInput
)element
).getModel();
244 protected void doSaveDocument(IProgressMonitor monitor
, Object element
,
245 IDocument document
, boolean overwrite
) throws CoreException
{
246 if (element
instanceof AbstractBulkEditorInput
) {
248 IEntityPersistenceService persistenceService
= (AbstractBulkEditorInput
) element
;
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();
257 while (iterator
.hasNext()) {
258 Annotation annotation
= (Annotation
) iterator
.next();
259 if (annotation
instanceof IEntityContainer
<?
>) {
260 IEntityContainer
<?
> container
= (IEntityContainer
<?
>) annotation
;
262 if (container
.isMarkedAsNew() || container
.isDirty()) {
264 Object entity
= persistenceService
.save(container
.getEntity()); // save
265 container
.setEntity(entity
);
266 container
.setDirty(false);
267 container
.markAsNew(false);
271 this.conversation
.commit(true);
272 for (LineAnnotation annotation
: model
.getDeletedAnnotations()) {
273 if (annotation
.isMarkedAsNew()) {
276 if (annotation
.isMarkedAsMerged()) {
277 persistenceService
.merge(annotation
.getEntity(), annotation
.getMergeTarget()); // merge
278 } if (annotation
.isMarkedAsDeleted()) {
280 persistenceService
.delete(annotation
.getEntity(), annotation
.getDeleteConfigurator());
281 } catch (ReferencedObjectUndeletableException e
) {
282 // TODO Auto-generated catch block
288 // TODO clarify w AM whether this needs to be executed on merged objects
289 //persistenceService.delete(annotation.getEntity()); // delete
292 model
.clearDeletedAnnotations();
298 protected IRunnableContext
getOperationRunner(IProgressMonitor monitor
) {
304 public boolean isModifiable(Object element
) {
310 public boolean isReadOnly(Object element
) {
311 // enables copy & paste
316 * <p>Getter for the field <code>entityCreator</code>.</p>
318 * @param element a {@link java.lang.Object} object.
319 * @return a {@link eu.etaxonomy.taxeditor.annotatedlineeditor.IEntityCreator} object.
321 public IEntityCreator
<?
> getEntityCreator(IEditorInput input
) {
322 if (input
instanceof AbstractBulkEditorInput
) {
323 entityCreator
= ((AbstractBulkEditorInput
) input
).getEntityCreator();
325 return entityCreator
;
329 * <p>Setter for the field <code>lineDisplayStrategy</code>.</p>
331 * @param lineDisplayStrategy a {@link eu.etaxonomy.taxeditor.annotatedlineeditor.ILineDisplayStrategy} object.
332 * @param element a {@link java.lang.Object} object.
334 public void setLineDisplayStrategy(
335 ILineDisplayStrategy lineDisplayStrategy
, Object element
) {
336 if (element
instanceof IEditorInput
) {
337 this.lineDisplayStrategy
= lineDisplayStrategy
;
342 * <p>Getter for the field <code>lineDisplayStrategy</code>.</p>
344 * @param element a {@link java.lang.Object} object.
345 * @return a {@link eu.etaxonomy.taxeditor.annotatedlineeditor.ILineDisplayStrategy} object.
347 protected ILineDisplayStrategy
getLineDisplayStrategy(Object element
) {
348 if (element
instanceof IEditorInput
) {
349 Assert
.isNotNull(lineDisplayStrategy
, "No ILineDisplayStrategy set for this element.");
350 return lineDisplayStrategy
;
356 * <p>removeAnnotatedLine</p>
358 * @param entity a {@link java.lang.Object} object.
360 public void removeAnnotatedLine(Object entity
){
361 LineAnnotation annotation
= (LineAnnotation
) annotationModel
.getAnnotation(entity
);
362 removeAnnotatedLine(annotation
);
366 * <p>removeAnnotatedLine</p>
368 * @param lineno a int.
369 * @param element a {@link java.lang.Object} object.
371 public void removeAnnotatedLine(Object element
, int lineno
) {
372 LineAnnotation annotation
= (LineAnnotation
) annotationModel
.getAnnotationAtLine(lineno
, document
);
373 removeAnnotatedLine(annotation
);
377 * <p>removeAnnotatedLine</p>
379 * @param annotation a {@link eu.etaxonomy.taxeditor.annotatedlineeditor.LineAnnotation} object.
381 public void removeAnnotatedLine(LineAnnotation annotation
) {
382 if (annotation
!= null) {
383 Document document
= (Document
) getDocument(input
);
384 LineAnnotationModel model
= (LineAnnotationModel
) getAnnotationModel(input
);
386 Position position
= model
.getPosition(annotation
);
387 int offset
= position
.getOffset();
388 int length
= position
.getLength();
390 Object entity
= annotation
.getEntity();
391 //annotation.markAsDeleted(configurator);
392 model
.removeAnnotation(annotation
);
394 // Immediately followed by a delimiter?
395 int annotationEnd
= offset
+ length
;
397 if (document
.getLength() > annotationEnd
+ 1 && document
.get(annotationEnd
, 2).equals(document
.getDefaultLineDelimiter())) {
400 } catch (BadLocationException e1
) {
401 MessagingUtils
.error(getClass(), "Problems removing annotated line", e1
);
406 document
.replace(offset
, length
, "");
408 } catch (BadLocationException e
) {
409 MessagingUtils
.error(getClass(), "Problems removing annotated line", e
);
415 * @see org.eclipse.ui.texteditor.AbstractDocumentProvider#changed(java.lang.Object)
419 public void changed(Object entity
) {
420 LineAnnotation annotation
= (LineAnnotation
) annotationModel
.getAnnotation(entity
);
421 if(annotation
!= null){
422 annotation
.setDirty(true);
423 updateLineFromAnnotation(annotation
);