3 * Copyright (C) 2007 EDIT
4 * European Distributed Institute of Taxonomy
5 * http://www.e-taxonomy.eu
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.
10 package eu
.etaxonomy
.taxeditor
.annotatedlineeditor
;
12 import java
.util
.HashMap
;
13 import java
.util
.Iterator
;
14 import java
.util
.List
;
17 import org
.apache
.log4j
.Logger
;
18 import org
.eclipse
.core
.runtime
.Assert
;
19 import org
.eclipse
.core
.runtime
.CoreException
;
20 import org
.eclipse
.core
.runtime
.IProgressMonitor
;
21 import org
.eclipse
.jface
.operation
.IRunnableContext
;
22 import org
.eclipse
.jface
.text
.BadLocationException
;
23 import org
.eclipse
.jface
.text
.Document
;
24 import org
.eclipse
.jface
.text
.IDocument
;
25 import org
.eclipse
.jface
.text
.Position
;
26 import org
.eclipse
.jface
.text
.source
.Annotation
;
27 import org
.eclipse
.jface
.text
.source
.IAnnotationModel
;
28 import org
.eclipse
.swt
.SWT
;
29 import org
.eclipse
.swt
.custom
.StyleRange
;
30 import org
.eclipse
.ui
.IEditorInput
;
31 import org
.eclipse
.ui
.texteditor
.AbstractDocumentProvider
;
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>LineAnnotationModdel</code>.
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.
50 public class AnnotatedLineDocumentProvider
extends AbstractDocumentProvider
{
52 private static final Logger logger
= Logger
53 .getLogger(AnnotatedLineDocumentProvider
.class);
55 private Map
<IEditorInput
, IDocument
> documents
=
56 new HashMap
<IEditorInput
, IDocument
>();
58 private Map
<IEditorInput
, IAnnotationModel
> annotationModels
=
59 new HashMap
<IEditorInput
, IAnnotationModel
>();
61 private Map
<IEditorInput
, IEntityCreator
<?
>> entityCreators
=
62 new HashMap
<IEditorInput
, IEntityCreator
<?
>>();
64 private Map
<IEditorInput
, IEntityPersistenceService
> persistenceServices
=
65 new HashMap
<IEditorInput
, IEntityPersistenceService
>();
67 private Map
<IEditorInput
, ILineDisplayStrategy
> lineDisplayStrategies
=
68 new HashMap
<IEditorInput
, ILineDisplayStrategy
>();
70 // private ITextViewer viewer;
72 // public AnnotatedLineEditorDocumentProvider(ITextViewer viewer) {
73 // this.viewer = viewer;
77 public IAnnotationModel
getAnnotationModel(Object element
) {
78 if (element
instanceof IEditorInput
) {
80 IEditorInput input
= (IEditorInput
) element
;
81 IAnnotationModel model
= annotationModels
.get((IEditorInput
) element
);
83 // Create model as necessary
85 model
= new LineAnnotationModel(getLineDisplayStrategy(element
));
86 ((LineAnnotationModel
) model
).setEntityCreator(getEntityCreator(element
));
87 annotationModels
.put(input
, model
);
96 protected IAnnotationModel
createAnnotationModel(Object element
)
97 throws CoreException
{
98 return getAnnotationModel(element
);
102 public IDocument
getDocument(Object element
) {
103 if (element
instanceof IEditorInput
) {
104 return documents
.get((IEditorInput
) element
);
110 protected IDocument
createDocument(Object element
) throws CoreException
{
112 if (element
instanceof IEditorInput
) {
113 IEditorInput input
= (IEditorInput
) element
;
114 Document document
= new Document("");
115 IAnnotationModel model
= getAnnotationModel(element
);
116 documents
.put(input
, document
);
118 for (Object entity
: getEntityList(element
)) {
121 createAnnotatedLine(input
, entity
);
122 } catch (BadLocationException e
) {
123 // TODO Auto-generated catch block
133 * Creates an annotated line at the end of the document associated with the element
135 * @throws BadLocationException
137 protected LineAnnotation
createAnnotatedLine(Object element
, Object entity
) throws BadLocationException
{
139 Document document
= (Document
) getDocument(element
);
140 ILineDisplayStrategy lineDisplay
= getLineDisplayStrategy(element
);
142 LineAnnotation annotation
= new LineAnnotation(entity
, lineDisplay
);
144 // Is document zero length, or is last char in document line delimiter?
145 int docLength
= document
.getLength();
146 boolean useDelimiter
= false;
148 if (docLength
> 1 && !document
.get(docLength
- 2, 2).equals(document
.getDefaultLineDelimiter())) {
153 document
.replace(docLength
, 0, document
.getDefaultLineDelimiter());
157 boolean doItalics
= false;
158 if (lineDisplay
.isEntityCacheEmpty(entity
)) {
159 text
= lineDisplay
.getEmptyCacheMessage(entity
);
162 text
= lineDisplay
.getText(entity
);
164 docLength
= document
.getLength();
165 document
.replace(docLength
, 0, text
);
167 Position position
= new Position(docLength
, text
.length());
169 IAnnotationModel model
= getAnnotationModel(element
);
170 model
.addAnnotation(annotation
, position
);
172 logger
.info("Annotation added " + entity
);
176 // TODO implement italics for non-named objects in presentation repairer � la
177 // http://www.wsmostudio.org/multiproject/org.wsmostudio.grounding.wsdls/xref/org/wsmostudio/grounding/sawsdl/ui/text/NonRuleBasedDamagerRepairer.html
179 StyleRange styleRange
= new StyleRange();
180 styleRange
.start
= docLength
;
181 styleRange
.length
= text
.length();
182 styleRange
.fontStyle
= SWT
.ITALIC
;
185 lineDisplay
.addDisplayListener(entity
,
186 new EntityListenerImpl((LineAnnotation
) annotation
, element
, lineDisplay
));
191 public void updateLineFromAnnotation(Object element
, LineAnnotation annotation
, String text
) {
192 IAnnotationModel model
= getAnnotationModel(element
);
193 IDocument document
= getDocument(element
);
195 if (model
.getPosition(annotation
) == null) {
198 int offset
= model
.getPosition(annotation
).getOffset();
199 int line
= document
.getLineOfOffset(offset
);
200 int lineLength
= document
.getLineLength(document
.getLineOfOffset(offset
));
201 if (document
.getLineDelimiter(line
) != null) {
202 lineLength
-= document
.getLineDelimiter(line
).length();
204 document
.replace(offset
, lineLength
, text
);
205 } catch (BadLocationException e
) {
206 // TODO Auto-generated catch block
211 class EntityListenerImpl
extends EntityListener
{
213 private LineAnnotation annotation
;
214 private ILineDisplayStrategy lineDisplay
;
215 private Object element
;
217 EntityListenerImpl(LineAnnotation annotation
, Object element
, ILineDisplayStrategy lineDisplay
) {
218 this.annotation
= annotation
;
219 this.element
= element
;
220 this.lineDisplay
= lineDisplay
;
223 * @see eu.etaxonomy.taxeditor.annotatedlineeditor.EntityDisplayListener#updateDisplay()
226 protected void updateEntity() {
228 annotation
.setDirty(true);
230 Object entity
= annotation
.getEntity();
232 if (lineDisplay
.isEntityCacheEmpty(entity
)) {
233 text
= lineDisplay
.getEmptyCacheMessage(entity
);
235 text
= lineDisplay
.getText(entity
);
238 updateLineFromAnnotation(element
, annotation
, text
);
246 private List
<?
> getEntityList(Object element
) {
247 if (element
instanceof IEditorInput
) {
248 return getPersistenceService(element
).getEntityList(element
);
254 protected void doSaveDocument(IProgressMonitor monitor
, Object element
,
255 IDocument document
, boolean overwrite
) throws CoreException
{
256 if (element
instanceof IEditorInput
) {
258 IEntityPersistenceService persistenceService
= getPersistenceService(element
);
260 // Get new containers from annotation model
261 LineAnnotationModel model
= (LineAnnotationModel
) getAnnotationModel(element
);
262 Iterator iterator
= model
.getAnnotationIterator();
263 while (iterator
.hasNext()) {
264 Annotation annotation
= (Annotation
) iterator
.next();
265 if (annotation
instanceof IEntityContainer
<?
>) {
266 IEntityContainer
<?
> container
= (IEntityContainer
<?
>) annotation
;
267 if (container
.isMarkedAsNew() || container
.isDirty()) {
268 persistenceService
.save(container
.getEntity(), element
); // save
269 container
.setDirty(false);
270 container
.markAsNew(false);
274 for (LineAnnotation annotation
: model
.getDeletedAnnotations()) {
275 if (annotation
.isMarkedAsNew()) {
278 if (annotation
.isMarkedAsMerged()) {
279 persistenceService
.merge(annotation
.getEntity(), annotation
.getMergeTarget(), element
); // merge
281 // TODO clarify w AM whether this needs to be executed on merged objects
282 persistenceService
.delete(annotation
.getEntity(), element
); // delete
285 model
.clearDeletedAnnotations();
290 protected IRunnableContext
getOperationRunner(IProgressMonitor monitor
) {
295 public boolean isModifiable(Object element
) {
300 public boolean isReadOnly(Object element
) {
301 // enables copy & paste
306 * @param entityCreator
309 public void setEntityCreator(IEntityCreator
<?
> entityCreator
, Object element
) {
310 if (element
instanceof IEditorInput
) {
311 entityCreators
.put((IEditorInput
) element
, entityCreator
);
319 public IEntityCreator
<?
> getEntityCreator(Object element
) {
320 if (element
instanceof IEditorInput
) {
321 IEntityCreator
<?
> entityCreator
= entityCreators
.get(element
);
322 Assert
.isNotNull(entityCreator
, "No IEntityCreator set for this element.");
323 return entityCreator
;
329 * @param persistenceService
332 public void setPersistenceService(
333 IEntityPersistenceService persistenceService
, Object element
) {
334 if (element
instanceof IEditorInput
) {
335 persistenceServices
.put((IEditorInput
) element
, persistenceService
);
339 public IEntityPersistenceService
getPersistenceService(Object element
) {
340 if (element
instanceof IEditorInput
) {
341 IEntityPersistenceService persistenceService
= persistenceServices
.get((IEditorInput
) element
);
342 Assert
.isNotNull(persistenceService
, "No IEntityPersistenceService set for this element.");
343 return persistenceService
;
349 * @param lineDisplayStrategy
352 public void setLineDisplayStrategy(
353 ILineDisplayStrategy lineDisplayStrategy
, Object element
) {
354 if (element
instanceof IEditorInput
) {
355 lineDisplayStrategies
.put((IEditorInput
) element
, lineDisplayStrategy
);
363 protected ILineDisplayStrategy
getLineDisplayStrategy(Object element
) {
364 if (element
instanceof IEditorInput
) {
365 ILineDisplayStrategy lineDisplayStrategy
= lineDisplayStrategies
.get((IEditorInput
) element
);
366 Assert
.isNotNull(lineDisplayStrategy
, "No ILineDisplayStrategy set for this element.");
367 return lineDisplayStrategy
;
376 public void removeAnnotatedLine(Object element
, int lineno
) {
377 Document document
= (Document
) getDocument(element
);
378 LineAnnotationModel model
= (LineAnnotationModel
) getAnnotationModel(element
);
379 LineAnnotation annotation
= (LineAnnotation
) model
.getAnnotationAtLine(lineno
, document
);
380 removeAnnotatedLine(element
, annotation
);
383 public void removeAnnotatedLine(Object element
, LineAnnotation annotation
) {
384 if (annotation
!= null) {
385 Document document
= (Document
) getDocument(element
);
386 LineAnnotationModel model
= (LineAnnotationModel
) getAnnotationModel(element
);
388 Position position
= model
.getPosition(annotation
);
389 int offset
= position
.getOffset();
390 int length
= position
.getLength();
392 Object entity
= annotation
.getEntity();
393 annotation
.markAsDeleted();
394 model
.removeAnnotation(annotation
);
396 // Immediately followed by a delimiter?
397 int annotationEnd
= offset
+ length
;
399 if (document
.getLength() > annotationEnd
+ 1 && document
.get(annotationEnd
, 2).equals(document
.getDefaultLineDelimiter())) {
402 } catch (BadLocationException e1
) {
403 // TODO Auto-generated catch block
404 e1
.printStackTrace();
408 document
.replace(offset
, length
, "");
409 } catch (BadLocationException e
) {
410 // TODO Auto-generated catch block