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

File AnnotationScriptService.java

 

Coverage histogram

../../../../img/srcFileCovDistChart3.png
80% of files have more coverage

Code metrics

16
71
17
1
408
184
33
0.46
4.18
17
1.94

Classes

Class Line # Actions
AnnotationScriptService 52 71 0% 33 81
0.2211538422.1%
 

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.script;
21   
22    import java.util.Collection;
23    import java.util.Map;
24   
25    import javax.inject.Inject;
26    import javax.inject.Named;
27    import javax.inject.Singleton;
28   
29    import org.xwiki.annotation.Annotation;
30    import org.xwiki.annotation.AnnotationService;
31    import org.xwiki.annotation.AnnotationServiceException;
32    import org.xwiki.annotation.rights.AnnotationRightService;
33    import org.xwiki.component.annotation.Component;
34    import org.xwiki.context.Execution;
35    import org.xwiki.model.reference.DocumentReference;
36    import org.xwiki.model.reference.EntityReference;
37    import org.xwiki.model.reference.EntityReferenceSerializer;
38    import org.xwiki.script.service.ScriptService;
39   
40    import com.xpn.xwiki.XWikiContext;
41    import com.xpn.xwiki.XWikiException;
42   
43    /**
44    * Wrapper for the annotation service functions to be exposed to scripting contexts.
45    *
46    * @version $Id: 493f7a1b862a14bd5786366a3feb026aa33d57d3 $
47    * @since 3.0RC1
48    */
49    @Component
50    @Named("annotations")
51    @Singleton
 
52    public class AnnotationScriptService implements ScriptService
53    {
54    /**
55    * The annotation service to execute annotation functions.
56    */
57    @Inject
58    private AnnotationService annotationService;
59   
60    /**
61    * The annotations rights service.
62    */
63    @Inject
64    private AnnotationRightService rightsService;
65   
66    /**
67    * The execution to get the context.
68    */
69    @Inject
70    private Execution execution;
71   
72    /**
73    * Entity reference serializer, to create references to the documents to which annotation targets refer.
74    */
75    @Inject
76    private EntityReferenceSerializer<String> serializer;
77   
78    /**
79    * Adds an the specified annotation for the specified target.
80    *
81    * @param target serialized reference of the target of the annotation
82    * @param selection HTML selection concerned by annotations
83    * @param selectionContext HTML selection context
84    * @param offset offset of the selection in context
85    * @param author the author of the annotation
86    * @param metadata annotation metadata, as key, value pairs
87    * @return {@code true} if the adding succeeds, {@code false} if an exception occurs and the exception is saved on
88    * the xwiki context
89    */
 
90  0 toggle public boolean addAnnotation(String target, String selection, String selectionContext, int offset, String author,
91    Map<String, Object> metadata)
92    {
93  0 if (!this.rightsService.canAddAnnotation(target, getCurrentUser())) {
94  0 setAccessExceptionOnContext();
95  0 return false;
96    }
97  0 try {
98  0 this.annotationService.addAnnotation(target, selection, selectionContext, offset, author, metadata);
99  0 return true;
100    } catch (AnnotationServiceException e) {
101  0 setExceptionOnContext(e);
102  0 return false;
103    }
104    }
105   
106    /**
107    * Returns the XHTML of the requested source, along with annotations inserted as {@code span} elements inside it.
108    * It's a particular case of {@link #getAnnotatedRenderedContent(String, String, String, Collection)} for
109    * unspecified input syntax, {@code xhtml/1.0} output syntax and the list of annotations returned by
110    * {@link #getValidAnnotations(String)} for this source reference.
111    *
112    * @param sourceReference reference to the source to be rendered in XHTML with annotations
113    * @return rendered and annotated document or {@code null} if an exception occurs and the exception is saved on the
114    * xwiki context
115    * @see #getAnnotatedRenderedContent(String, String, String, Collection)
116    * @see AnnotationService#getAnnotatedHTML(String)
117    */
 
118  0 toggle public String getAnnotatedHTML(String sourceReference)
119    {
120  0 if (!this.rightsService.canViewAnnotatedTarget(sourceReference, getCurrentUser())) {
121  0 setAccessExceptionOnContext();
122  0 return null;
123    }
124  0 try {
125  0 return this.annotationService.getAnnotatedHTML(sourceReference);
126    } catch (AnnotationServiceException e) {
127  0 setExceptionOnContext(e);
128  0 return null;
129    }
130    }
131   
132    /**
133    * Returns result obtained by rendering with annotations markers the source referenced by the
134    * {@code sourceReference} parsed in {@code sourceSyntax}. The list of annotations to be added markers for is passed
135    * in the {@code annotations} parameter. Note that no test is done on the actual target of the annotations in the
136    * passed list, they will all be rendered, as long as their selected text and context can be identified in the
137    * content.
138    *
139    * @param sourceReference the reference to the source to be rendered in XHTML with annotations
140    * @param sourceSyntax the syntax to parse the source in. If this parameter is null, the default source syntax will
141    * be used, as returned by the target IO service.
142    * @param outputSyntax the syntax to render in (e.g. "xhtml/1.0")
143    * @param annotations the annotations to render on the content referred by the {@code sourceReference}. Can be the
144    * whole set of annotations on that source or a subset, filtered by various criteria
145    * @return the annotated rendered source, or @code null} if an exception occurs and the exception is saved on the
146    * xwiki context
147    * @see AnnotationService#getAnnotatedRenderedContent(String, String, String, Collection)
148    */
 
149  0 toggle public String getAnnotatedRenderedContent(String sourceReference, String sourceSyntax, String outputSyntax,
150    Collection<Annotation> annotations)
151    {
152  0 if (!this.rightsService.canViewAnnotatedTarget(sourceReference, getCurrentUser())) {
153  0 setAccessExceptionOnContext();
154  0 return null;
155    }
156  0 try {
157  0 return this.annotationService.getAnnotatedRenderedContent(sourceReference, sourceSyntax, outputSyntax,
158    annotations);
159    } catch (AnnotationServiceException e) {
160  0 setExceptionOnContext(e);
161  0 return null;
162    }
163    }
164   
165    /**
166    * Returns the annotation identified by {@code id} on the specified target.
167    *
168    * @param target the serialized reference to the content on which the annotation is added
169    * @param id the identifier of the annotation
170    * @return the annotation identified by {@code id}, or {@code null} if an exception occurs and the exception is
171    * saved on the xwiki context
172    * @see AnnotationService#getAnnotation(String, String)
173    */
 
174  8 toggle public Annotation getAnnotation(String target, String id)
175    {
176  8 if (!this.rightsService.canViewAnnotations(target, getCurrentUser())) {
177  0 setAccessExceptionOnContext();
178  0 return null;
179    }
180  8 try {
181  8 return this.annotationService.getAnnotation(target, id);
182    } catch (AnnotationServiceException e) {
183  0 setExceptionOnContext(e);
184  0 return null;
185    }
186    }
187   
188    /**
189    * Returns the annotation identified by {@code id} on the specified target.
190    *
191    * @param reference the reference to the content on which the annotation is added
192    * @param id the identifier of the annotation
193    * @return the annotation identified by {@code id}, or {@code null} if an exception occurs and the exception is
194    * saved on the xwiki context
195    * @see AnnotationService#getAnnotation(String, String)
196    */
 
197  8 toggle public Annotation getAnnotation(EntityReference reference, String id)
198    {
199  8 String serializedRef = this.serializer.serialize(reference);
200   
201  8 return getAnnotation(serializedRef, id);
202    }
203   
204    /**
205    * Returns all the annotations on the passed content.
206    *
207    * @param target the string serialized reference to the content for which to get the annotations
208    * @return all annotations which target the specified content, or {@code null} if an exception occurs and the
209    * exception is saved on the xwiki context
210    * @see AnnotationService#getAnnotations(String)
211    */
 
212  1 toggle public Collection<Annotation> getAnnotations(String target)
213    {
214  1 if (!this.rightsService.canViewAnnotations(target, getCurrentUser())) {
215  0 setAccessExceptionOnContext();
216  0 return null;
217    }
218  1 try {
219  1 return this.annotationService.getAnnotations(target);
220    } catch (AnnotationServiceException e) {
221  0 setExceptionOnContext(e);
222  0 return null;
223    }
224    }
225   
226    /**
227    * Shortcut function to get all annotations which are valid on the specified target, regardless of the updates the
228    * document and its annotations suffered from creation ('safe' or 'updated' state).
229    *
230    * @param target the string serialized reference to the content for which to get the annotations
231    * @return all annotations which are valid on the specified content, or {@code null} if an exception occurs and the
232    * exception is saved on the xwiki context
233    * @see org.xwiki.annotation.maintainer.AnnotationState
234    * @see AnnotationService#getValidAnnotations(String)
235    */
 
236  0 toggle public Collection<Annotation> getValidAnnotations(String target)
237    {
238  0 if (!this.rightsService.canViewAnnotations(target, getCurrentUser())) {
239  0 setAccessExceptionOnContext();
240  0 return null;
241    }
242  0 try {
243  0 return this.annotationService.getValidAnnotations(target);
244    } catch (AnnotationServiceException e) {
245  0 setExceptionOnContext(e);
246  0 return null;
247    }
248    }
249   
250    /**
251    * Remove an annotation given by its identifier, which should be unique among all annotations on the same target.
252    *
253    * @param target the string serialized reference to the content on which the annotation is added
254    * @param annotationID annotation identifier
255    * @return {@code true} if removing succeeds, {@code false} if an exception occurs and the exception is saved on the
256    * xwiki context
257    * @see AnnotationService#removeAnnotation(String, String)
258    */
 
259  0 toggle public boolean removeAnnotation(String target, String annotationID)
260    {
261  0 if (!this.rightsService.canEditAnnotation(annotationID, target, getCurrentUser())) {
262  0 setAccessExceptionOnContext();
263  0 return false;
264    }
265  0 try {
266  0 this.annotationService.removeAnnotation(target, annotationID);
267  0 return true;
268    } catch (AnnotationServiceException e) {
269  0 setExceptionOnContext(e);
270  0 return false;
271    }
272    }
273   
274    /**
275    * Updates the passed annotation with the new values. Matching of the annotation is done by the annotation id field,
276    * among all annotations on the same target.
277    *
278    * @param target the string serialized reference to the content on which the annotation is added
279    * @param annotation the new description of the annotation to update, with a valid id
280    * @return {@code true} if update succeeds, {@code false} if an exception occurs and the exception is saved on the
281    * xwiki context
282    * @see AnnotationService#updateAnnotation(String, Annotation)
283    */
 
284  0 toggle public boolean updateAnnotation(String target, Annotation annotation)
285    {
286  0 if (!this.rightsService.canEditAnnotation(annotation.getId(), target, getCurrentUser())) {
287  0 setAccessExceptionOnContext();
288  0 return false;
289    }
290  0 try {
291  0 this.annotationService.updateAnnotation(target, annotation);
292  0 return true;
293    } catch (AnnotationServiceException e) {
294  0 setExceptionOnContext(e);
295  0 return false;
296    }
297    }
298   
299    /**
300    * Checks if the current user can edit an annotation on the document given by wiki, space and page. This function is
301    * a helper function, using wiki, space and page instead of the target to avoid target generation in velocity
302    * scripting.<br>
303    * TODO: annotations should only operate on targets, and velocity context should only operate with targets so that
304    * they can pass a target to this function. This also assumes refactoring of the REST service to always get target
305    * references instead of wiki, space and pages in the path.
306    *
307    * @param annotationId the id of the annotation to edit
308    * @param wiki the wiki of the document where the annotation is added
309    * @param space the space of the document where the annotation is added
310    * @param page the document page
311    * @return {@code true} if the current user can edit the annotation identified by the id on the specified document,
312    * {@code false} otherwise
313    * @deprecated since 7.2M3, use {@link #canEditAnnotation(String, DocumentReference)} instead
314    */
 
315  0 toggle @Deprecated
316    public boolean canEditAnnotation(String annotationId, String wiki, String space, String page)
317    {
318  0 return canEditAnnotation(annotationId, new DocumentReference(wiki, space, page));
319    }
320   
321    /**
322    * Checks if the current user can edit an annotation on the document given by wiki, space and page.
323    *
324    * @param annotationId the id of the annotation to edit
325    * @param reference the reference of the document where the annotation is added
326    * @return {@code true} if the current user can edit the annotation identified by the id on the specified document,
327    * {@code false} otherwise
328    * @since 7.2M3
329    */
 
330  8 toggle public boolean canEditAnnotation(String annotationId, DocumentReference reference)
331    {
332  8 String target = this.serializer.serialize(reference);
333   
334  8 return this.rightsService.canEditAnnotation(annotationId, target, getCurrentUser());
335    }
336   
337    /**
338    * Checks if the current user can add an annotation on the document given by the wiki, space and page. This function
339    * is a helper function, using wiki, space and page instead of the target to avoid target generation in velocity
340    * scripting.<br>
341    *
342    * @param wiki the wiki of the document where the annotation is added
343    * @param space the space of the document where the annotation is added
344    * @param page the document page
345    * @return {@code true} if the current user can add an annotation on the specified document, {@code false} otherwise
346    * @see #canEditAnnotation(String, String, String, String)
347    * @deprecated since 7.2M3, use {@link #canAddAnnotation(DocumentReference)} instead
348    */
 
349  0 toggle @Deprecated
350    public boolean canAddAnnotation(String wiki, String space, String page)
351    {
352  0 return canAddAnnotation(new DocumentReference(wiki, space, page));
353    }
354   
355    /**
356    * Checks if the current user can add an annotation on the document given by the reference.
357    *
358    * @param reference the reference of the document where the annotation is added
359    * @return {@code true} if the current user can add an annotation on the specified document, {@code false} otherwise
360    * @see #canEditAnnotation(String, String, String, String)
361    * @since 7.2M3
362    */
 
363  4 toggle public boolean canAddAnnotation(DocumentReference reference)
364    {
365  4 String target = this.serializer.serialize(reference);
366   
367  4 return this.rightsService.canAddAnnotation(target, getCurrentUser());
368    }
369   
370    /**
371    * Helper function to get the currently logged in user.
372    *
373    * @return the currently logged in user
374    */
 
375  21 toggle private String getCurrentUser()
376    {
377  21 return getXWikiContext().getUser();
378    }
379   
380    /**
381    * Helper function to get the XWiki Context.
382    *
383    * @return the xwiki context
384    */
 
385  21 toggle private XWikiContext getXWikiContext()
386    {
387  21 return (XWikiContext) this.execution.getContext().getProperty("xwikicontext");
388    }
389   
390    /**
391    * Helper function to set an exception on the xwiki context, as the last exception.
392    *
393    * @param exception the exception to set on the context
394    */
 
395  0 toggle private void setExceptionOnContext(Exception exception)
396    {
397  0 getXWikiContext().put("lastexception", exception);
398    }
399   
400    /**
401    * Helper function to set an access exception on the xwiki context, as the last exception.
402    */
 
403  0 toggle private void setAccessExceptionOnContext()
404    {
405  0 setExceptionOnContext(new XWikiException(XWikiException.MODULE_XWIKI_ACCESS,
406    XWikiException.ERROR_XWIKI_ACCESS_DENIED, "You are not allowed to perform this action"));
407    }
408    }