1. Project Clover database Tue Dec 20 2016 21:24:09 CET
  2. Package org.xwiki.annotation.internal

File AnnotationEventGeneratorEventListener.java

 

Coverage histogram

../../../../img/srcFileCovDistChart8.png
54% of files have more coverage

Code metrics

16
39
4
1
199
112
14
0.36
9.75
4
3.5

Classes

Class Line # Actions
AnnotationEventGeneratorEventListener 64 39 0% 14 13
0.77966178%
 

Contributing tests

No tests hitting this source file were found.

Source view

1    /*
2    * See the NOTICE file distributed with this work for additional
3    * information regarding copyright ownership.
4    *
5    * This is free software; you can redistribute it and/or modify it
6    * under the terms of the GNU Lesser General Public License as
7    * published by the Free Software Foundation; either version 2.1 of
8    * the License, or (at your option) any later version.
9    *
10    * This software is distributed in the hope that it will be useful,
11    * but WITHOUT ANY WARRANTY; without even the implied warranty of
12    * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13    * Lesser General Public License for more details.
14    *
15    * You should have received a copy of the GNU Lesser General Public
16    * License along with this software; if not, write to the Free
17    * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
18    * 02110-1301 USA, or see the FSF site: http://www.fsf.org.
19    */
20    package org.xwiki.annotation.internal;
21   
22    import java.util.Arrays;
23    import java.util.List;
24   
25    import javax.inject.Inject;
26    import javax.inject.Named;
27    import javax.inject.Provider;
28    import javax.inject.Singleton;
29   
30    import org.slf4j.Logger;
31    import org.xwiki.annotation.Annotation;
32    import org.xwiki.annotation.AnnotationConfiguration;
33    import org.xwiki.annotation.event.AnnotationAddedEvent;
34    import org.xwiki.annotation.event.AnnotationDeletedEvent;
35    import org.xwiki.annotation.event.AnnotationUpdatedEvent;
36    import org.xwiki.component.annotation.Role;
37    import org.xwiki.context.Execution;
38    import org.xwiki.model.reference.DocumentReference;
39    import org.xwiki.model.reference.EntityReference;
40    import org.xwiki.model.reference.EntityReferenceSerializer;
41    import org.xwiki.observation.EventListener;
42    import org.xwiki.observation.ObservationManager;
43    import org.xwiki.observation.event.Event;
44   
45    import com.xpn.xwiki.XWikiContext;
46    import com.xpn.xwiki.doc.XWikiDocument;
47    import com.xpn.xwiki.internal.event.XObjectAddedEvent;
48    import com.xpn.xwiki.internal.event.XObjectDeletedEvent;
49    import com.xpn.xwiki.internal.event.XObjectEvent;
50    import com.xpn.xwiki.internal.event.XObjectUpdatedEvent;
51    import com.xpn.xwiki.objects.BaseObject;
52    import com.xpn.xwiki.objects.BaseObjectReference;
53   
54    /**
55    * Listens to object events of the same class as the currently configured annotation class and launches corresponding
56    * {@link org.xwiki.annotation.event.AnnotationEvent}s.
57    *
58    * @version $Id: e32629f365f10261fbab4c26673d9260673d0806 $
59    * @since 4.0RC1
60    */
61    @Role
62    @Named("AnnotationEventGeneratorEventListener")
63    @Singleton
 
64    public class AnnotationEventGeneratorEventListener implements EventListener
65    {
66    /**
67    * The matched events.
68    */
69    private static final List<Event> EVENTS = Arrays.<Event> asList(new XObjectAddedEvent(), new XObjectUpdatedEvent(),
70    new XObjectDeletedEvent());
71   
72    /**
73    * Used to check if the Annotations Application is installed on the current wiki.
74    */
75    @Inject
76    protected AnnotationConfiguration annotationConfiguration;
77   
78    /**
79    * Used to launch annotation events. Lazy loaded to avoid cycles.
80    */
81    @Inject
82    protected Provider<ObservationManager> observationManager;
83   
84    /**
85    * Execution context used to get the current wiki.
86    */
87    @Inject
88    protected Execution execution;
89   
90    /**
91    * Used to serializer document.
92    */
93    @Inject
94    protected EntityReferenceSerializer<String> defaultEntityReferenceSerializer;
95   
96    /**
97    * Logging framework.
98    */
99    @Inject
100    protected Logger logger;
101   
 
102  8 toggle @Override
103    public String getName()
104    {
105  8 return this.getClass().getAnnotation(Named.class).value();
106    }
107   
 
108  1 toggle @Override
109    public List<Event> getEvents()
110    {
111  1 return EVENTS;
112    }
113   
 
114  8 toggle @Override
115    public void onEvent(Event event, Object source, Object data)
116    {
117    // Don`t rely on the context from the data parameter.
118  8 XWikiContext context = (XWikiContext) execution.getContext().getProperty("xwikicontext");
119  8 String currentWiki = context.getWikiId();
120   
121  8 try {
122  8 XWikiDocument document = (XWikiDocument) source;
123  8 String wikiOfAffectedDocument = document.getDocumentReference().getWikiReference().getName();
124   
125    // Always work on the wiki of the source document. The Annotation Application's configuration looks at the
126    // context to provide values for the current wiki. Objects could be modified cross-wiki and the context
127    // database might not be right.
128  8 context.setWikiId(wikiOfAffectedDocument);
129   
130    // Only work if the Annotations Application is installed on the wiki.
131  8 if (!annotationConfiguration.isInstalled()) {
132  0 return;
133    }
134   
135    // Extract the BaseObjectReference to be able to inspect the XClassReference.
136  8 BaseObjectReference objectReference = getBaseObjectReference((XObjectEvent) event);
137  8 DocumentReference objectClassReference = objectReference.getXClassReference();
138   
139    // Only interested in objects that are of the same class as the currently configured annotation class.
140  8 if (!objectClassReference.equals(annotationConfiguration.getAnnotationClassReference())) {
141  0 return;
142    }
143   
144    // The object is needed for the final check. See below.
145  8 BaseObject object = document.getXObject(objectReference);
146   
147    // Build the new event to launch using the current document reference and object number.
148  8 Event newEvent = null;
149  8 String documentReference = defaultEntityReferenceSerializer.serialize(document.getDocumentReference());
150  8 String number = String.valueOf(objectReference.getObjectNumber());
151  8 if (event instanceof XObjectAddedEvent) {
152  4 newEvent = new AnnotationAddedEvent(documentReference, number);
153  4 } else if (event instanceof XObjectUpdatedEvent) {
154  0 newEvent = new AnnotationUpdatedEvent(documentReference, number);
155  4 } else if (event instanceof XObjectDeletedEvent) {
156    // Current document might be deleted. Always use the original document for *Deleted events.
157  4 object = document.getOriginalDocument().getXObject(objectReference);
158  4 newEvent = new AnnotationDeletedEvent(documentReference, number);
159    }
160   
161    // Handle specially the default annotations class which coincides with the default comments class. We need
162    // to avoid mistaking comments for annotations.
163  8 DocumentReference defaultCommentsClassReference =
164    context.getWiki().getCommentsClass(context).getDocumentReference();
165  8 if (defaultCommentsClassReference.equals(object.getXClassReference())) {
166    // A comment is considered an annotation when it has a text selection.
167  8 String selection = object.getStringValue(Annotation.SELECTION_FIELD);
168  8 if (selection == null || selection.trim().length() == 0) {
169    // This is a simple comment. Skip it.
170  0 return;
171    }
172    }
173   
174    // Launch the new event.
175  8 observationManager.get().notify(newEvent, source, context);
176    } catch (Exception e) {
177  0 logger.error("Failed to handle event of type [{}]", event.getClass().getName(), e);
178    } finally {
179    // Restore the context database.
180  8 context.setWikiId(currentWiki);
181    }
182    }
183   
184    /**
185    * @param objectEvent the event involving an object
186    * @return the {@link BaseObjectReference} of the object corresponding to the object event
187    */
 
188  8 toggle private BaseObjectReference getBaseObjectReference(XObjectEvent objectEvent)
189    {
190  8 EntityReference objectReference = objectEvent.getReference();
191  8 BaseObjectReference baseObjectReference = null;
192  8 if (objectReference instanceof BaseObjectReference) {
193  8 baseObjectReference = (BaseObjectReference) objectEvent.getReference();
194    } else {
195  0 baseObjectReference = new BaseObjectReference(objectEvent.getReference());
196    }
197  8 return baseObjectReference;
198    }
199    }