1 |
|
|
2 |
|
|
3 |
|
|
4 |
|
|
5 |
|
|
6 |
|
|
7 |
|
|
8 |
|
|
9 |
|
|
10 |
|
|
11 |
|
|
12 |
|
|
13 |
|
|
14 |
|
|
15 |
|
|
16 |
|
|
17 |
|
|
18 |
|
|
19 |
|
|
20 |
|
package org.xwiki.annotation.io.internal; |
21 |
|
|
22 |
|
import java.util.ArrayList; |
23 |
|
import java.util.Arrays; |
24 |
|
import java.util.Collection; |
25 |
|
import java.util.Collections; |
26 |
|
import java.util.Date; |
27 |
|
import java.util.List; |
28 |
|
|
29 |
|
import javax.inject.Inject; |
30 |
|
import javax.inject.Named; |
31 |
|
import javax.inject.Singleton; |
32 |
|
|
33 |
|
import org.codehaus.plexus.util.StringUtils; |
34 |
|
import org.slf4j.Logger; |
35 |
|
import org.xwiki.annotation.Annotation; |
36 |
|
import org.xwiki.annotation.AnnotationConfiguration; |
37 |
|
import org.xwiki.annotation.io.IOService; |
38 |
|
import org.xwiki.annotation.io.IOServiceException; |
39 |
|
import org.xwiki.annotation.maintainer.AnnotationState; |
40 |
|
import org.xwiki.annotation.reference.TypedStringEntityReferenceResolver; |
41 |
|
import org.xwiki.component.annotation.Component; |
42 |
|
import org.xwiki.context.Execution; |
43 |
|
import org.xwiki.model.EntityType; |
44 |
|
import org.xwiki.model.reference.EntityReference; |
45 |
|
import org.xwiki.model.reference.EntityReferenceSerializer; |
46 |
|
|
47 |
|
import com.xpn.xwiki.XWikiContext; |
48 |
|
import com.xpn.xwiki.XWikiException; |
49 |
|
import com.xpn.xwiki.doc.XWikiDocument; |
50 |
|
import com.xpn.xwiki.objects.BaseObject; |
51 |
|
import com.xpn.xwiki.objects.BaseProperty; |
52 |
|
|
53 |
|
|
54 |
|
@link |
55 |
|
|
56 |
|
|
57 |
|
|
58 |
|
|
59 |
|
@version |
60 |
|
@since |
61 |
|
|
62 |
|
@Component |
63 |
|
@Singleton |
|
|
| 67.1% |
Uncovered Elements: 57 (173) |
Complexity: 49 |
Complexity Density: 0.4 |
|
64 |
|
public class DefaultIOService implements IOService |
65 |
|
{ |
66 |
|
|
67 |
|
|
68 |
|
|
69 |
|
@Inject |
70 |
|
private Execution execution; |
71 |
|
|
72 |
|
|
73 |
|
|
74 |
|
|
75 |
|
@Inject |
76 |
|
private TypedStringEntityReferenceResolver referenceResolver; |
77 |
|
|
78 |
|
|
79 |
|
|
80 |
|
|
81 |
|
@Inject |
82 |
|
private EntityReferenceSerializer<String> serializer; |
83 |
|
|
84 |
|
|
85 |
|
|
86 |
|
|
87 |
|
@Inject |
88 |
|
@Named("local") |
89 |
|
private EntityReferenceSerializer<String> localSerializer; |
90 |
|
|
91 |
|
|
92 |
|
|
93 |
|
|
94 |
|
@Inject |
95 |
|
private Logger logger; |
96 |
|
|
97 |
|
|
98 |
|
|
99 |
|
|
100 |
|
@Inject |
101 |
|
private AnnotationConfiguration configuration; |
102 |
|
|
103 |
|
|
104 |
|
@inheritDoc |
105 |
|
|
106 |
|
|
107 |
|
|
108 |
|
|
109 |
|
@see |
110 |
|
|
|
|
| 84% |
Uncovered Elements: 4 (25) |
Complexity: 5 |
Complexity Density: 0.24 |
|
111 |
4 |
@Override... |
112 |
|
public void addAnnotation(String target, Annotation annotation) throws IOServiceException |
113 |
|
{ |
114 |
4 |
try { |
115 |
|
|
116 |
|
|
117 |
4 |
String documentFullName = target; |
118 |
4 |
EntityReference targetReference = referenceResolver.resolve(target, EntityType.DOCUMENT); |
119 |
|
|
120 |
4 |
EntityReference docRef = targetReference.extractReference(EntityType.DOCUMENT); |
121 |
4 |
if (docRef != null) { |
122 |
4 |
documentFullName = serializer.serialize(docRef); |
123 |
|
} |
124 |
|
|
125 |
4 |
XWikiContext deprecatedContext = getXWikiContext(); |
126 |
4 |
XWikiDocument document = deprecatedContext.getWiki().getDocument(documentFullName, deprecatedContext); |
127 |
|
|
128 |
|
|
129 |
|
|
130 |
4 |
EntityReference annotationClassReference = configuration.getAnnotationClassReference(); |
131 |
4 |
annotationClassReference = |
132 |
|
annotationClassReference.removeParent(annotationClassReference.extractReference(EntityType.WIKI)); |
133 |
4 |
int id = document.createXObject(annotationClassReference, deprecatedContext); |
134 |
4 |
BaseObject object = document.getXObject(configuration.getAnnotationClassReference(), id); |
135 |
4 |
updateObject(object, annotation, deprecatedContext); |
136 |
|
|
137 |
4 |
object.set(Annotation.DATE_FIELD, new Date(), deprecatedContext); |
138 |
|
|
139 |
|
|
140 |
4 |
object.set(Annotation.AUTHOR_FIELD, annotation.getAuthor(), deprecatedContext); |
141 |
|
|
142 |
|
|
143 |
|
|
144 |
|
|
145 |
|
|
146 |
|
|
147 |
|
|
148 |
|
|
149 |
4 |
if (targetReference.getType() == EntityType.OBJECT_PROPERTY |
150 |
|
|| targetReference.getType() == EntityType.DOCUMENT) { |
151 |
4 |
object.set(Annotation.TARGET_FIELD, localSerializer.serialize(targetReference), deprecatedContext); |
152 |
|
} else { |
153 |
0 |
object.set(Annotation.TARGET_FIELD, target, deprecatedContext); |
154 |
|
} |
155 |
|
|
156 |
4 |
document.setAuthor(deprecatedContext.getUser()); |
157 |
|
|
158 |
|
|
159 |
4 |
deprecatedContext.getWiki().saveDocument(document, "Added annotation on \"" |
160 |
|
+ StringUtils.abbreviate(annotation.getSelection(), 30) + "\"", deprecatedContext); |
161 |
|
} catch (XWikiException e) { |
162 |
0 |
throw new IOServiceException("An exception message has occurred while saving the annotation", e); |
163 |
|
} |
164 |
|
} |
165 |
|
|
166 |
|
|
167 |
|
@inheritDoc |
168 |
|
|
169 |
|
|
170 |
|
|
171 |
|
|
172 |
|
|
173 |
|
@see |
174 |
|
|
|
|
| 92% |
Uncovered Elements: 2 (25) |
Complexity: 7 |
Complexity Density: 0.37 |
|
175 |
9 |
@Override... |
176 |
|
public Collection<Annotation> getAnnotations(String target) throws IOServiceException |
177 |
|
{ |
178 |
9 |
try { |
179 |
|
|
180 |
9 |
EntityReference targetReference = referenceResolver.resolve(target, EntityType.DOCUMENT); |
181 |
|
|
182 |
9 |
String localTargetId = target; |
183 |
|
|
184 |
9 |
String docName = target; |
185 |
9 |
if (targetReference.getType() == EntityType.DOCUMENT |
186 |
|
|| targetReference.getType() == EntityType.OBJECT_PROPERTY) { |
187 |
9 |
localTargetId = localSerializer.serialize(targetReference); |
188 |
9 |
docName = serializer.serialize(targetReference.extractReference(EntityType.DOCUMENT)); |
189 |
|
} |
190 |
|
|
191 |
9 |
XWikiContext deprecatedContext = getXWikiContext(); |
192 |
9 |
XWikiDocument document = deprecatedContext.getWiki().getDocument(docName, deprecatedContext); |
193 |
|
|
194 |
9 |
List<BaseObject> objects = document.getXObjects(configuration.getAnnotationClassReference()); |
195 |
|
|
196 |
9 |
List<Annotation> result = new ArrayList<Annotation>(); |
197 |
9 |
if (objects == null) { |
198 |
1 |
return Collections.<Annotation> emptySet(); |
199 |
|
} |
200 |
8 |
for (BaseObject object : objects) { |
201 |
|
|
202 |
26 |
if (object == null || !localTargetId.equals(object.getStringValue(Annotation.TARGET_FIELD))) { |
203 |
6 |
continue; |
204 |
|
} |
205 |
|
|
206 |
20 |
result.add(loadAnnotationFromObject(object, deprecatedContext)); |
207 |
|
} |
208 |
8 |
return result; |
209 |
|
} catch (XWikiException e) { |
210 |
0 |
throw new IOServiceException("An exception has occurred while loading the annotations", e); |
211 |
|
} |
212 |
|
} |
213 |
|
|
|
|
| 69.6% |
Uncovered Elements: 7 (23) |
Complexity: 9 |
Complexity Density: 0.53 |
|
214 |
8 |
@Override... |
215 |
|
public Annotation getAnnotation(String target, String annotationID) throws IOServiceException |
216 |
|
{ |
217 |
8 |
try { |
218 |
8 |
if (annotationID == null || target == null) { |
219 |
0 |
return null; |
220 |
|
} |
221 |
|
|
222 |
8 |
EntityReference targetReference = referenceResolver.resolve(target, EntityType.DOCUMENT); |
223 |
|
|
224 |
8 |
String localTargetId = target; |
225 |
|
|
226 |
8 |
String docName = target; |
227 |
8 |
if (targetReference.getType() == EntityType.DOCUMENT |
228 |
|
|| targetReference.getType() == EntityType.OBJECT_PROPERTY) { |
229 |
8 |
localTargetId = localSerializer.serialize(targetReference); |
230 |
8 |
docName = serializer.serialize(targetReference.extractReference(EntityType.DOCUMENT)); |
231 |
|
} |
232 |
|
|
233 |
8 |
XWikiContext deprecatedContext = getXWikiContext(); |
234 |
8 |
XWikiDocument document = deprecatedContext.getWiki().getDocument(docName, deprecatedContext); |
235 |
|
|
236 |
|
|
237 |
8 |
BaseObject object = |
238 |
|
document.getXObject(configuration.getAnnotationClassReference(), |
239 |
|
Integer.valueOf(annotationID.toString())); |
240 |
8 |
if (object == null || !localTargetId.equals(object.getStringValue(Annotation.TARGET_FIELD))) { |
241 |
0 |
return null; |
242 |
|
} |
243 |
|
|
244 |
8 |
return loadAnnotationFromObject(object, deprecatedContext); |
245 |
|
} catch (NumberFormatException e) { |
246 |
0 |
throw new IOServiceException("Could not parse annotation id " + annotationID, e); |
247 |
|
} catch (XWikiException e) { |
248 |
0 |
throw new IOServiceException("An exception has occurred while loading the annotation with id " |
249 |
|
+ annotationID, e); |
250 |
|
} |
251 |
|
} |
252 |
|
|
253 |
|
|
254 |
|
@inheritDoc |
255 |
|
|
256 |
|
|
257 |
|
|
258 |
|
|
259 |
|
|
260 |
|
@see |
261 |
|
|
|
|
| 71.4% |
Uncovered Elements: 8 (28) |
Complexity: 10 |
Complexity Density: 0.5 |
|
262 |
4 |
@Override... |
263 |
|
public void removeAnnotation(String target, String annotationID) throws IOServiceException |
264 |
|
{ |
265 |
4 |
try { |
266 |
4 |
if (annotationID == null || target == null) { |
267 |
0 |
return; |
268 |
|
} |
269 |
|
|
270 |
4 |
EntityReference targetReference = referenceResolver.resolve(target, EntityType.DOCUMENT); |
271 |
|
|
272 |
4 |
String localTargetId = target; |
273 |
4 |
String docName = target; |
274 |
4 |
if (targetReference.getType() == EntityType.DOCUMENT |
275 |
|
|| targetReference.getType() == EntityType.OBJECT_PROPERTY) { |
276 |
4 |
localTargetId = localSerializer.serialize(targetReference); |
277 |
4 |
docName = serializer.serialize(targetReference.extractReference(EntityType.DOCUMENT)); |
278 |
|
} |
279 |
|
|
280 |
4 |
XWikiContext deprecatedContext = getXWikiContext(); |
281 |
4 |
XWikiDocument document = deprecatedContext.getWiki().getDocument(docName, deprecatedContext); |
282 |
4 |
if (document.isNew()) { |
283 |
|
|
284 |
0 |
return; |
285 |
|
} |
286 |
|
|
287 |
4 |
BaseObject annotationObject = |
288 |
|
document.getXObject(configuration.getAnnotationClassReference(), |
289 |
|
Integer.valueOf(annotationID.toString())); |
290 |
|
|
291 |
|
|
292 |
4 |
if (annotationObject != null |
293 |
|
&& localTargetId.equals(annotationObject.getStringValue(Annotation.TARGET_FIELD))) { |
294 |
4 |
document.removeObject(annotationObject); |
295 |
4 |
document.setAuthor(deprecatedContext.getUser()); |
296 |
4 |
deprecatedContext.getWiki().saveDocument(document, "Deleted annotation " + annotationID, |
297 |
|
deprecatedContext); |
298 |
|
} |
299 |
|
} catch (NumberFormatException e) { |
300 |
0 |
throw new IOServiceException("An exception has occurred while parsing the annotation id", e); |
301 |
|
} catch (XWikiException e) { |
302 |
0 |
throw new IOServiceException("An exception has occurred while removing the annotation", e); |
303 |
|
} |
304 |
|
} |
305 |
|
|
306 |
|
|
307 |
|
@inheritDoc |
308 |
|
|
309 |
|
|
310 |
|
|
311 |
|
|
312 |
|
|
313 |
|
|
314 |
|
@see |
315 |
|
|
|
|
| 0% |
Uncovered Elements: 29 (29) |
Complexity: 7 |
Complexity Density: 0.3 |
|
316 |
0 |
@Override... |
317 |
|
public void updateAnnotations(String target, Collection<Annotation> annotations) throws IOServiceException |
318 |
|
{ |
319 |
0 |
try { |
320 |
0 |
EntityReference targetReference = referenceResolver.resolve(target, EntityType.DOCUMENT); |
321 |
|
|
322 |
0 |
String docName = target; |
323 |
0 |
if (targetReference.getType() == EntityType.DOCUMENT |
324 |
|
|| targetReference.getType() == EntityType.OBJECT_PROPERTY) { |
325 |
0 |
docName = serializer.serialize(targetReference.extractReference(EntityType.DOCUMENT)); |
326 |
|
} |
327 |
|
|
328 |
0 |
XWikiContext deprecatedContext = getXWikiContext(); |
329 |
0 |
XWikiDocument document = deprecatedContext.getWiki().getDocument(docName, deprecatedContext); |
330 |
0 |
List<String> updateNotifs = new ArrayList<String>(); |
331 |
0 |
boolean updated = false; |
332 |
0 |
for (Annotation annotation : annotations) { |
333 |
|
|
334 |
0 |
int annId = 0; |
335 |
0 |
try { |
336 |
0 |
annId = Integer.parseInt(annotation.getId()); |
337 |
|
} catch (NumberFormatException e) { |
338 |
0 |
continue; |
339 |
|
} |
340 |
0 |
BaseObject object = document.getXObject(configuration.getAnnotationClassReference(), annId); |
341 |
0 |
if (object == null) { |
342 |
0 |
continue; |
343 |
|
} |
344 |
0 |
updated = updateObject(object, annotation, deprecatedContext) || updated; |
345 |
0 |
updateNotifs.add(annotation.getId()); |
346 |
|
} |
347 |
0 |
if (updated) { |
348 |
|
|
349 |
0 |
document.setAuthor(deprecatedContext.getUser()); |
350 |
0 |
deprecatedContext.getWiki().saveDocument(document, "Updated annotations", deprecatedContext); |
351 |
|
} |
352 |
|
} catch (XWikiException e) { |
353 |
0 |
throw new IOServiceException("An exception has occurred while updating the annotation", e); |
354 |
|
} |
355 |
|
} |
356 |
|
|
357 |
|
|
358 |
|
|
359 |
|
|
360 |
|
@param |
361 |
|
@param |
362 |
|
@return |
363 |
|
|
|
|
| 81.2% |
Uncovered Elements: 3 (16) |
Complexity: 5 |
Complexity Density: 0.42 |
|
364 |
28 |
protected Annotation loadAnnotationFromObject(BaseObject object, XWikiContext deprecatedContext)... |
365 |
|
{ |
366 |
|
|
367 |
|
|
368 |
28 |
Annotation annotation = new Annotation(object.getNumber() + ""); |
369 |
28 |
annotation.setState(AnnotationState.valueOf(object.getStringValue(Annotation.STATE_FIELD))); |
370 |
28 |
String originalSelection = object.getStringValue(Annotation.ORIGINAL_SELECTION_FIELD); |
371 |
28 |
if (originalSelection != null && originalSelection.length() > 0) { |
372 |
0 |
annotation.setOriginalSelection(originalSelection); |
373 |
|
} |
374 |
|
|
375 |
28 |
Collection<String> skippedFields = |
376 |
|
Arrays.asList(new String[] {Annotation.ORIGINAL_SELECTION_FIELD, Annotation.STATE_FIELD}); |
377 |
|
|
378 |
|
|
379 |
28 |
for (String propName : object.getPropertyNames()) { |
380 |
224 |
if (!skippedFields.contains(propName)) { |
381 |
196 |
try { |
382 |
196 |
annotation.set(propName, ((BaseProperty) object.get(propName)).getValue()); |
383 |
|
} catch (XWikiException e) { |
384 |
0 |
this.logger.warn("Unable to get property " + propName + " from object " + object.getClassName() |
385 |
|
+ "[" + object.getNumber() + "]. Will not be saved in the annotation.", e); |
386 |
|
} |
387 |
|
} |
388 |
|
} |
389 |
28 |
return annotation; |
390 |
|
} |
391 |
|
|
392 |
|
|
393 |
|
|
394 |
|
|
395 |
|
@param |
396 |
|
@param |
397 |
|
@param |
398 |
|
@return |
399 |
|
|
|
|
| 90.9% |
Uncovered Elements: 1 (11) |
Complexity: 3 |
Complexity Density: 0.43 |
|
400 |
4 |
protected boolean updateObject(BaseObject object, Annotation annotation, XWikiContext deprecatedContext)... |
401 |
|
{ |
402 |
4 |
boolean updated = false; |
403 |
|
|
404 |
|
|
405 |
|
|
406 |
|
|
407 |
4 |
updated = |
408 |
4 |
setIfNotNull(object, Annotation.STATE_FIELD, annotation.getState() == null ? null : annotation.getState() |
409 |
|
.toString(), deprecatedContext) |
410 |
|
|| updated; |
411 |
|
|
412 |
|
|
413 |
4 |
Collection<String> skippedFields = |
414 |
|
Arrays.asList(new String[] {Annotation.STATE_FIELD, Annotation.DATE_FIELD, Annotation.AUTHOR_FIELD, |
415 |
|
Annotation.TARGET_FIELD}); |
416 |
|
|
417 |
4 |
for (String propName : annotation.getFieldNames()) { |
418 |
28 |
if (!skippedFields.contains(propName)) { |
419 |
16 |
updated = setIfNotNull(object, propName, annotation.get(propName), deprecatedContext) || updated; |
420 |
|
} |
421 |
|
} |
422 |
|
|
423 |
4 |
return updated; |
424 |
|
} |
425 |
|
|
426 |
|
|
427 |
|
|
428 |
|
|
429 |
|
|
430 |
|
@param |
431 |
|
@param |
432 |
|
@param |
433 |
|
@param |
434 |
|
@return |
435 |
|
|
|
|
| 66.7% |
Uncovered Elements: 2 (6) |
Complexity: 2 |
Complexity Density: 0.5 |
|
436 |
20 |
protected boolean setIfNotNull(BaseObject object, String fieldName, Object newValue, XWikiContext deprecatedContext)... |
437 |
|
{ |
438 |
20 |
if (newValue != null) { |
439 |
20 |
object.set(fieldName, newValue, deprecatedContext); |
440 |
20 |
return true; |
441 |
|
} |
442 |
0 |
return false; |
443 |
|
} |
444 |
|
|
445 |
|
|
446 |
|
@return |
447 |
|
|
|
|
| 100% |
Uncovered Elements: 0 (1) |
Complexity: 1 |
Complexity Density: 1 |
|
448 |
25 |
private XWikiContext getXWikiContext()... |
449 |
|
{ |
450 |
25 |
return (XWikiContext) execution.getContext().getProperty("xwikicontext"); |
451 |
|
} |
452 |
|
} |