1. Project Clover database Tue Dec 20 2016 21:24:09 CET
  2. Package com.xpn.xwiki.api

File Document.java

 

Coverage histogram

../../../../img/srcFileCovDistChart5.png
74% of files have more coverage

Code metrics

212
689
242
1
3,078
1,773
397
0.58
2.85
242
1.64

Classes

Class Line # Actions
Document 89 689 0% 397 639
0.4409448844.1%
 

Contributing tests

This file is covered by 55 tests. .

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 com.xpn.xwiki.api;
21   
22    import java.io.IOException;
23    import java.io.InputStream;
24    import java.util.ArrayList;
25    import java.util.Collections;
26    import java.util.Date;
27    import java.util.HashMap;
28    import java.util.List;
29    import java.util.Locale;
30    import java.util.Map;
31    import java.util.Vector;
32   
33    import org.apache.commons.fileupload.FileItem;
34    import org.apache.commons.lang3.StringUtils;
35    import org.slf4j.Logger;
36    import org.slf4j.LoggerFactory;
37    import org.suigeneris.jrcs.diff.DifferentiationFailedException;
38    import org.suigeneris.jrcs.diff.delta.Delta;
39    import org.suigeneris.jrcs.rcs.Version;
40    import org.xwiki.context.Execution;
41    import org.xwiki.context.ExecutionContext;
42    import org.xwiki.display.internal.DocumentDisplayerParameters;
43    import org.xwiki.filter.output.OutputTarget;
44    import org.xwiki.model.reference.DocumentReference;
45    import org.xwiki.model.reference.DocumentReferenceResolver;
46    import org.xwiki.model.reference.EntityReferenceSerializer;
47    import org.xwiki.rendering.block.XDOM;
48    import org.xwiki.rendering.parser.ParseException;
49    import org.xwiki.rendering.syntax.Syntax;
50    import org.xwiki.rendering.syntax.SyntaxFactory;
51    import org.xwiki.security.authorization.ContextualAuthorizationManager;
52   
53    import com.xpn.xwiki.XWiki;
54    import com.xpn.xwiki.XWikiConstant;
55    import com.xpn.xwiki.XWikiContext;
56    import com.xpn.xwiki.XWikiException;
57    import com.xpn.xwiki.criteria.impl.Period;
58    import com.xpn.xwiki.criteria.impl.PeriodFactory;
59    import com.xpn.xwiki.criteria.impl.Range;
60    import com.xpn.xwiki.criteria.impl.RangeFactory;
61    import com.xpn.xwiki.criteria.impl.RevisionCriteria;
62    import com.xpn.xwiki.criteria.impl.Scope;
63    import com.xpn.xwiki.criteria.impl.ScopeFactory;
64    import com.xpn.xwiki.doc.MetaDataDiff;
65    import com.xpn.xwiki.doc.XWikiAttachment;
66    import com.xpn.xwiki.doc.XWikiDocument;
67    import com.xpn.xwiki.doc.XWikiDocumentArchive;
68    import com.xpn.xwiki.doc.XWikiLink;
69    import com.xpn.xwiki.doc.XWikiLock;
70    import com.xpn.xwiki.objects.BaseObject;
71    import com.xpn.xwiki.objects.BaseProperty;
72    import com.xpn.xwiki.objects.ObjectDiff;
73    import com.xpn.xwiki.objects.classes.BaseClass;
74    import com.xpn.xwiki.plugin.fileupload.FileUploadPlugin;
75    import com.xpn.xwiki.stats.api.XWikiStatsService;
76    import com.xpn.xwiki.stats.impl.DocumentStats;
77    import com.xpn.xwiki.stats.impl.RefererStats;
78    import com.xpn.xwiki.util.TOCGenerator;
79    import com.xpn.xwiki.util.Util;
80    import com.xpn.xwiki.web.Utils;
81   
82    /**
83    * This class represents a document or page in the wiki. This is a security and usability wrapper which wraps
84    * {@link com.xpn.xwiki.doc.XWikiDocument} In scripting, an object representing the document in which the script resides
85    * will be bound to a variable called doc.
86    *
87    * @version $Id: 039f9cc83c29abae191e55008e591d95778dfb46 $
88    */
 
89    public class Document extends Api
90    {
91    /** Logging helper object. */
92    private static final Logger LOGGER = LoggerFactory.getLogger(Document.class);
93   
94    /**
95    * The XWikiDocument object wrapped by this API.
96    */
97    protected XWikiDocument initialDoc;
98   
99    /**
100    * The XWikiDocument object wrapped by this API.
101    */
102    protected XWikiDocument doc;
103   
104    /**
105    * Convenience object used by object related methods.
106    */
107    protected Object currentObj;
108   
109    /**
110    * Used to resolve a string into a proper Document Reference using the current document's reference to fill the
111    * blanks, except for the page name for which the default page name is used instead and for the wiki name for which
112    * the current wiki is used instead of the current document reference's wiki.
113    */
114    private DocumentReferenceResolver<String> currentMixedDocumentReferenceResolver;
115   
116    /**
117    * Used to convert a proper Document Reference to string (standard form).
118    */
119    private EntityReferenceSerializer<String> defaultEntityReferenceSerializer;
120   
121    /**
122    * Used to convert a proper Document Reference to a string but without the wiki name.
123    */
124    private EntityReferenceSerializer<String> localEntityReferenceSerializer;
125   
126    /**
127    * Used to convert user references to string.
128    */
129    private EntityReferenceSerializer<String> compactWikiEntityReferenceSerializer;
130   
131    /**
132    * Authorization manager used to check rights.
133    */
134    private ContextualAuthorizationManager authorizationManager;
135   
 
136  2 toggle private DocumentReferenceResolver<String> getCurrentMixedDocumentReferenceResolver()
137    {
138  2 if (this.currentMixedDocumentReferenceResolver == null) {
139  2 this.currentMixedDocumentReferenceResolver =
140    Utils.getComponent(DocumentReferenceResolver.TYPE_STRING, "currentmixed");
141    }
142   
143  2 return this.currentMixedDocumentReferenceResolver;
144    }
145   
 
146  1477 toggle private EntityReferenceSerializer<String> getDefaultEntityReferenceSerializer()
147    {
148  1477 if (this.defaultEntityReferenceSerializer == null) {
149  988 this.defaultEntityReferenceSerializer = Utils.getComponent(EntityReferenceSerializer.TYPE_STRING);
150    }
151   
152  1477 return this.defaultEntityReferenceSerializer;
153    }
154   
 
155  6768 toggle private EntityReferenceSerializer<String> getLocalEntityReferenceSerializer()
156    {
157  6768 if (this.localEntityReferenceSerializer == null) {
158  3385 this.localEntityReferenceSerializer = Utils.getComponent(EntityReferenceSerializer.TYPE_STRING, "local");
159    }
160   
161  6768 return this.localEntityReferenceSerializer;
162    }
163   
 
164  0 toggle private EntityReferenceSerializer<String> getCompactWikiEntityReferenceSerializer()
165    {
166  0 if (this.compactWikiEntityReferenceSerializer == null) {
167  0 this.compactWikiEntityReferenceSerializer =
168    Utils.getComponent(EntityReferenceSerializer.TYPE_STRING, "compactwiki");
169    }
170   
171  0 return this.compactWikiEntityReferenceSerializer;
172    }
173   
174    /**
175    * Document constructor.
176    *
177    * @param doc The XWikiDocument object to wrap.
178    * @param context The current request context.
179    */
 
180  193439 toggle public Document(XWikiDocument doc, XWikiContext context)
181    {
182  193470 super(context);
183   
184  193433 this.initialDoc = doc;
185  193432 this.doc = this.initialDoc;
186    }
187   
188    /**
189    * Get the XWikiDocument wrapped by this API. This function is accessible only if you have the programming rights
190    * give access to the priviledged API of the Document.
191    *
192    * @return The XWikiDocument wrapped by this API.
193    */
 
194  8 toggle public XWikiDocument getDocument()
195    {
196  8 if (hasProgrammingRights()) {
197  8 return this.doc;
198    } else {
199  0 return null;
200    }
201    }
202   
203    /**
204    * Get a clone of the XWikiDocument wrapped by this API.
205    *
206    * @return A clone of the XWikiDocument wrapped by this API.
207    */
 
208  27192 toggle protected XWikiDocument getDoc()
209    {
210  27192 if (this.initialDoc == this.doc) {
211  18529 this.doc = this.initialDoc.clone();
212    }
213   
214  27194 return this.doc;
215    }
216   
217    /**
218    * return the ID of the document. this ID is unique across the wiki.
219    *
220    * @return the id of the document.
221    */
 
222  0 toggle public long getId()
223    {
224  0 return this.doc.getId();
225    }
226   
227    /**
228    * returns the DocumentReference for the current document
229    *
230    * @return the DocumentReference of the current document
231    * @since 2.3M1
232    */
 
233  14240 toggle public DocumentReference getDocumentReference()
234    {
235  14239 return this.doc.getDocumentReference();
236    }
237   
238    /**
239    * return the name of a document. for example if the fullName of a document is "MySpace.Mydoc", the name is MyDoc.
240    *
241    * @return the name of the document
242    */
 
243  9101 toggle public String getName()
244    {
245  9099 return this.doc.getDocumentReference().getName();
246    }
247   
248    /**
249    * Return the full local space reference of the Document. For example a document located in sub-space
250    * <code>space11</code> of space <code>space1</code> will return <code>space1.space11</code>.
251    *
252    * @return the name of the spaces of the document
253    */
 
254  8570 toggle public String getSpace()
255    {
256  8569 return this.doc.getSpace();
257    }
258   
259    /**
260    * Get the name wiki where the document is stored.
261    *
262    * @return The name of the wiki where this document is stored.
263    * @since 1.1.2
264    * @since 1.2M2
265    */
 
266  4282 toggle public String getWiki()
267    {
268  4282 return this.doc.getDocumentReference().getWikiReference().getName();
269    }
270   
271    /**
272    * Get the fullName of the document. If a document is named "MyDoc" in space "MySpace", the fullname is
273    * "MySpace.MyDoc". In a wiki, all the documents have a different fullName.
274    *
275    * @return fullName of the document.
276    */
 
277  6460 toggle public String getFullName()
278    {
279  6460 return getLocalEntityReferenceSerializer().serialize(this.doc.getDocumentReference());
280    }
281   
282    /**
283    * Get the complete fullName of the document. The real full name of the document containing the name of the wiki
284    * where the document is stored. For a document stored in the wiki "xwiki", in space "MySpace", named "MyDoc", its
285    * complete full name is "xwiki:MySpace.MyDoc".
286    *
287    * @return The complete fullName of the document.
288    * @since 1.1.2
289    * @since 1.2M2
290    */
 
291  1476 toggle public String getPrefixedFullName()
292    {
293  1476 return getDefaultEntityReferenceSerializer().serialize(this.doc.getDocumentReference());
294    }
295   
296    /**
297    * Get a Version object representing the current version of the document.
298    *
299    * @return A Version object representing the current version of the document
300    */
 
301  852 toggle public Version getRCSVersion()
302    {
303  852 return this.doc.getRCSVersion();
304    }
305   
306    /**
307    * Get a string representing the current version of the document.
308    *
309    * @return A string representing the current version of the document.
310    */
 
311  1848 toggle public String getVersion()
312    {
313  1848 return this.doc.getVersion();
314    }
315   
316    /**
317    * Get a string representing the previous version of the document.
318    *
319    * @return A string representing the previous version of the document. If this is the first version then it returns
320    * null.
321    */
 
322  0 toggle public String getPreviousVersion()
323    {
324  0 return this.doc.getPreviousVersion();
325    }
326   
327    /**
328    * Get the value of the title field of the document.
329    *
330    * @return The value of the title field of the document.
331    */
 
332  454 toggle public String getTitle()
333    {
334  454 return this.doc.getTitle();
335    }
336   
337    /**
338    * Get document title. If a title has not been provided through the title field, it looks for a section title in the
339    * document's content and if not found return the page name. The returned title is also interpreted which means it's
340    * allowed to use Velocity, Groovy, etc syntax within a title.
341    *
342    * @return The document title as XHTML
343    */
 
344  15896 toggle public String getDisplayTitle()
345    {
346  15896 return this.doc.getRenderedTitle(getXWikiContext());
347    }
348   
349    /**
350    * Returns the document title as plain text
351    *
352    * @return the document title as plain text (all markup removed)
353    * @since 3.0M1
354    */
 
355  2493 toggle public String getPlainTitle()
356    {
357  2493 return this.doc.getRenderedTitle(Syntax.PLAIN_1_0, getXWikiContext());
358    }
359   
360    /**
361    * Returns the title of the document rendered through wiki syntax and velocity
362    *
363    * @return the title rendered through wiki syntax and velocity
364    * @see XWikiDocument#getRenderedTitle(Syntax, XWikiContext)
365    */
 
366  373 toggle public String getRenderedTitle(String syntaxId) throws XWikiException
367    {
368  373 try {
369  373 return this.doc.getRenderedTitle(Utils.getComponent(SyntaxFactory.class).createSyntaxFromIdString(syntaxId),
370    getXWikiContext());
371    } catch (ParseException e) {
372  0 LOGGER.error("Failed to parse provided syntax identifier [" + syntaxId + "]", e);
373   
374  0 throw new XWikiException(XWikiException.MODULE_XWIKI_RENDERING, XWikiException.ERROR_XWIKI_UNKNOWN,
375    "Failed to parse syntax identifier [" + syntaxId + "]", e);
376    } catch (Exception e) {
377  0 LOGGER.error("Failed to render document [" + getPrefixedFullName() + "] title content", e);
378   
379  0 throw new XWikiException(XWikiException.MODULE_XWIKI_RENDERING, XWikiException.ERROR_XWIKI_UNKNOWN,
380    "Failed to render document [" + getPrefixedFullName() + "] content title", e);
381    }
382    }
383   
384    /**
385    * TODO document this or mark it deprecated
386    */
 
387  0 toggle public String getFormat()
388    {
389  0 return this.doc.getFormat();
390    }
391   
392    /**
393    * Get fullName of the profile document of the author of the current version of the document. Example: XWiki.Admin.
394    *
395    * @return The fullName of the profile document of the author of the current version of the document.
396    */
 
397  1202 toggle public String getAuthor()
398    {
399  1202 return this.doc.getAuthor();
400    }
401   
402    /**
403    * @return the document author reference
404    * @since 6.4RC1
405    */
 
406  84 toggle public DocumentReference getAuthorReference()
407    {
408  84 return this.doc.getAuthorReference();
409    }
410   
411    /**
412    * Get fullName of the profile document of the author of the content modification of this document version. Example:
413    * XWiki.Admin.
414    *
415    * @return The fullName of the profile document of the author of the content modification in this document version.
416    */
 
417  428 toggle public String getContentAuthor()
418    {
419  428 return this.doc.getContentAuthor();
420    }
421   
422    /**
423    * @return the document content author reference
424    * @since 6.4RC1
425    */
 
426  6 toggle public DocumentReference getContentAuthorReference()
427    {
428  6 return this.doc.getContentAuthorReference();
429    }
430   
431    /**
432    * @return The date when this document version has been modified.
433    */
 
434  520 toggle public Date getDate()
435    {
436  520 return this.doc.getDate();
437    }
438   
439    /**
440    * Get the date when the content modification has been done on this document version. A content update excludes
441    * modifications to meta data fields or comments of the document.
442    *
443    * @return The date where the content modification has been done on this document version.
444    */
 
445  415 toggle public Date getContentUpdateDate()
446    {
447  415 return this.doc.getContentUpdateDate();
448    }
449   
450    /**
451    * @return the original creation date of the document.
452    */
 
453  868 toggle public Date getCreationDate()
454    {
455  868 return this.doc.getCreationDate();
456    }
457   
458    /**
459    * Get the name of the parent of this document.
460    *
461    * @return The name of the parent of this document.
462    */
 
463  7668 toggle public String getParent()
464    {
465  7667 return this.doc.getParent();
466    }
467   
468    /**
469    * @return the parent reference or null if the parent is not set
470    * @since 7.3M1
471    */
 
472  553 toggle public DocumentReference getParentReference()
473    {
474  553 return this.doc.getParentReference();
475    }
476   
477    /**
478    * Get fullName of the profile document of the document creator.
479    *
480    * @return The fullName of the profile document of the document creator.
481    */
 
482  833 toggle public String getCreator()
483    {
484  833 return this.doc.getCreator();
485    }
486   
487    /**
488    * @return the document creator reference
489    * @since 6.4RC1
490    */
 
491  84 toggle public DocumentReference getCreatorReference()
492    {
493  84 return this.doc.getCreatorReference();
494    }
495   
496    /**
497    * Get raw content of the document, i.e. the content that is visible through the wiki editor.
498    *
499    * @return The raw content of the document.
500    */
 
501  479 toggle public String getContent()
502    {
503  479 return this.doc.getContent();
504    }
505   
506    /**
507    * NOTE: This method caches the XDOM and returns a clone that can be safely modified.
508    *
509    * @return the XDOM corresponding to the document's string content
510    * @since 7.0RC1
511    */
 
512  0 toggle public XDOM getXDOM()
513    {
514  0 return this.doc.getXDOM();
515    }
516   
517    /**
518    * @return The syntax representing the syntax used for the document's content
519    * @since 2.3M1
520    */
 
521  4033 toggle public Syntax getSyntax()
522    {
523  4032 return this.doc.getSyntax();
524    }
525   
526    /**
527    * Get the Syntax id representing the syntax used for the document. For example "xwiki/1.0" represents the first
528    * version XWiki syntax while "xwiki/2.0" represents version 2.0 of the XWiki Syntax.
529    *
530    * @return The syntax id representing the syntax used for the document.
531    * @deprecated since 2.3M1 use {@link #getSyntax()} instead
532    */
 
533  3 toggle @Deprecated
534    public String getSyntaxId()
535    {
536  3 return this.doc.getSyntax().toIdString();
537    }
538   
539    /**
540    * Same as {@link #getLocale()} but as String.
541    *
542    * @return the locale of the document.
543    * @deprecated since 5.4M1 use {@link #getLocale()} instead
544    */
 
545  0 toggle @Deprecated
546    public String getLanguage()
547    {
548  0 return this.doc.getLanguage();
549    }
550   
551    /**
552    * Get the locale of the document. If the document is a translation it returns the locale set for it, otherwise, it
553    * returns the root locale.
554    *
555    * @return the locale of the document
556    * @since 5.4M1
557    */
 
558  720 toggle public Locale getLocale()
559    {
560  718 return this.doc.getLocale();
561    }
562   
563    /**
564    * TODO document this or mark it deprecated
565    */
 
566  0 toggle public String getTemplate()
567    {
568  0 String templateReferenceAsString = "";
569  0 DocumentReference templateDocumentReference = this.doc.getTemplateDocumentReference();
570  0 if (templateDocumentReference != null) {
571  0 templateReferenceAsString = getLocalEntityReferenceSerializer().serialize(templateDocumentReference);
572    }
573  0 return templateReferenceAsString;
574    }
575   
576    /**
577    * Same as {@link #getRealLocale()} but as String.
578    *
579    * @return the real locale
580    * @deprecated since 8.0M1, use {@link #getRealLocale()} instead
581    */
 
582  22 toggle @Deprecated
583    public String getRealLanguage() throws XWikiException
584    {
585  22 return this.doc.getRealLanguage(getXWikiContext());
586    }
587   
588    /**
589    * Gets the real locale of the document. The real locale is either the default locale field when the locale field is
590    * empty (when the document is the default document) or the locale field otherwise when the document is a
591    * translation document
592    *
593    * @return the actual locale of the document
594    * @since 8.0M1
595    */
 
596  772 toggle public Locale getRealLocale()
597    {
598  772 return this.doc.getRealLocale();
599    }
600   
601    /**
602    * Same as {@link #getDefaultLocale()} but as String.
603    *
604    * @return the locale of the default document
605    * @deprecated since 8.0M1, use {@link #getDefaultLocale()} instead
606    */
 
607  11 toggle @Deprecated
608    public String getDefaultLanguage()
609    {
610  11 return this.doc.getDefaultLanguage();
611    }
612   
613    /**
614    * @return the Locale of the default version of the document (usually {@link Locale#ROOT} or {@link Locale#ENGLISH})
615    * @since 8.0M1
616    */
 
617  0 toggle public Locale getDefaultLocale()
618    {
619  0 return this.doc.getDefaultLocale();
620    }
621   
622    /**
623    * TODO document this or mark it deprecated
624    */
 
625  0 toggle public String getDefaultTemplate()
626    {
627  0 return this.doc.getDefaultTemplate();
628    }
629   
630    /**
631    * @return the comment of of the document version
632    */
 
633  419 toggle public String getComment()
634    {
635  419 return this.doc.getComment();
636    }
637   
638    /**
639    * @return true if the this document version was a minor edit.
640    */
 
641  0 toggle public boolean isMinorEdit()
642    {
643  0 return this.doc.isMinorEdit();
644    }
645   
646    /**
647    * @return the list of existing translations for this document.
648    */
 
649  553 toggle public List<String> getTranslationList() throws XWikiException
650    {
651  553 return this.doc.getTranslationList(getXWikiContext());
652    }
653   
654    /**
655    * @return the translated document's content if the wiki is multilingual, the locale is first checked in the URL,
656    * the cookie, the user profile and finally the wiki configuration if not, the locale is the one on the wiki
657    * configuration.
658    */
 
659  158 toggle public String getTranslatedContent() throws XWikiException
660    {
661  158 return this.doc.getTranslatedContent(getXWikiContext());
662    }
663   
664    /**
665    * @return the translated content in the given locale
666    */
 
667  0 toggle public String getTranslatedContent(String locale) throws XWikiException
668    {
669  0 return this.doc.getTranslatedContent(locale, getXWikiContext());
670    }
671   
672    /**
673    * @return the translated document in the given locale
674    */
 
675  0 toggle public Document getTranslatedDocument(String locale) throws XWikiException
676    {
677  0 return this.doc.getTranslatedDocument(locale, getXWikiContext()).newDocument(getXWikiContext());
678    }
679   
680    /**
681    * @return the tranlated Document if the wiki is multilingual, the locale is first checked in the URL, the cookie,
682    * the user profile and finally the wiki configuration if not, the locale is the one on the wiki
683    * configuration.
684    */
 
685  14861 toggle public Document getTranslatedDocument() throws XWikiException
686    {
687  14861 return this.doc.getTranslatedDocument(getXWikiContext()).newDocument(getXWikiContext());
688    }
689   
690    /**
691    * @return the content of the document rendered.
692    */
 
693  592 toggle public String getRenderedContent() throws XWikiException
694    {
695  592 return this.doc.getRenderedContent(getXWikiContext());
696    }
697   
698    /**
699    * Execute and render the document in the current context.
700    * <p>
701    * The code is executed with right of this document content author.
702    *
703    * @param transformationContextIsolated see {@link DocumentDisplayerParameters#isTransformationContextIsolated()}
704    * @return the result
705    * @throws XWikiException when failing to display the document
706    * @since 8.4RC1
707    */
 
708  0 toggle public String getRenderedContent(boolean transformationContextIsolated) throws XWikiException
709    {
710  0 return this.doc.getRenderedContent(transformationContextIsolated, getXWikiContext());
711    }
712   
713    /**
714    * @param text the text to render
715    * @return the given text rendered in the context of this document
716    * @deprecated since 1.6M1 use {@link #getRenderedContent(String, String)}
717    */
 
718  0 toggle @Deprecated
719    public String getRenderedContent(String text) throws XWikiException
720    {
721  0 return getRenderedContent(text, Syntax.XWIKI_1_0.toIdString());
722    }
723   
724    /**
725    * @param text the text to render
726    * @param syntaxId the id of the Syntax used by the passed text (for example: "xwiki/1.0")
727    * @return the given text rendered in the context of this document using the passed Syntax
728    * @since 1.6M1
729    */
 
730  12 toggle public String getRenderedContent(String text, String syntaxId) throws XWikiException
731    {
732  12 return getRenderedContent(text, syntaxId, false);
733    }
734   
735    /**
736    * Render a text in a restricted mode, where script macros are completely disabled.
737    *
738    * @param text the text to render
739    * @param syntaxId the id of the Syntax used by the passed text (for example: "xwiki/1.0")
740    * @return the given text rendered in the context of this document using the passed Syntax
741    * @since 4.2M1
742    */
 
743  18 toggle public String getRenderedContentRestricted(String text, String syntaxId) throws XWikiException
744    {
745  18 return getRenderedContent(text, syntaxId, true);
746    }
747   
748    /**
749    * Render a text in a restricted mode, where script macros are completely disabled.
750    *
751    * @param text the text to render
752    * @param syntaxId the id of the Syntax used by the passed text (for example: "xwiki/1.0")
753    * @param restrictedTransformationContext see {@link DocumentDisplayerParameters#isTransformationContextRestricted}.
754    * @return the given text rendered in the context of this document using the passed Syntax
755    */
 
756  30 toggle private String getRenderedContent(String text, String syntaxId, boolean restricted) throws XWikiException
757    {
758    // Make sure we keep using current author as passed content author
759  30 return this.doc.getRenderedContent(text, syntaxId, restricted, getCallerDocument(getXWikiContext()),
760    getXWikiContext());
761    }
762   
763    /**
764    * @param text the text to render
765    * @param sourceSyntaxId the id of the Syntax used by the passed text (for example: "xwiki/1.0")
766    * @param targetSyntaxId the id of the syntax in which to render the document content
767    * @return the given text rendered in the context of this document using the passed Syntax
768    * @since 2.0M3
769    */
 
770  4 toggle public String getRenderedContent(String text, String sourceSyntaxId, String targetSyntaxId) throws XWikiException
771    {
772    // Make sure we keep using current author as passed content author
773  4 return this.doc.getRenderedContent(text, sourceSyntaxId, targetSyntaxId, false,
774    getCallerDocument(getXWikiContext()), getXWikiContext());
775    }
776   
 
777  34 toggle private XWikiDocument getCallerDocument(XWikiContext xcontext)
778    {
779  34 XWikiDocument sdoc = (XWikiDocument) xcontext.get("sdoc");
780  34 if (sdoc == null) {
781  7 sdoc = xcontext.getDoc();
782    }
783   
784  34 return sdoc;
785    }
786   
787    /**
788    * @param targetSyntax the syntax in which to render the document content
789    * @return the rendered content
790    * @throws XWikiException error when rendering content
791    */
 
792  5207 toggle public String getRenderedContent(Syntax targetSyntax) throws XWikiException
793    {
794  5207 return this.doc.getRenderedContent(targetSyntax, getXWikiContext());
795    }
796   
797    /**
798    * Get the document's content XML-escaped.
799    *
800    * @return an XML-escaped version of the content of this document.
801    */
 
802  0 toggle public String getEscapedContent() throws XWikiException
803    {
804  0 return this.doc.getEscapedContent(getXWikiContext());
805    }
806   
807    /**
808    * @return the archive of this document's history in string format
809    */
 
810  0 toggle public String getArchive() throws XWikiException
811    {
812  0 return this.doc.getDocumentArchive(getXWikiContext()).getArchive(getXWikiContext());
813    }
814   
815    /**
816    * Get the archive of this document's history. This function is accessible only if you have the programming rights.
817    *
818    * @return the archive of this document's history as an {@link XWikiDocumentArchive}.
819    */
 
820  0 toggle public XWikiDocumentArchive getDocumentArchive() throws XWikiException
821    {
822  0 if (hasProgrammingRights()) {
823  0 return this.doc.getDocumentArchive(getXWikiContext());
824    }
825  0 return null;
826    }
827   
828    /**
829    * @return true if the document is a new one (ie it has never been saved) or false otherwise
830    */
 
831  9189 toggle public boolean isNew()
832    {
833  9186 return this.doc.isNew();
834    }
835   
836    /**
837    * Return the relative URL of download for the the given attachment name.
838    *
839    * @param filename the name of the attachment
840    * @return A String with the URL or null if the file name is empty
841    */
 
842  10 toggle public String getAttachmentURL(String filename)
843    {
844  10 return this.doc.getAttachmentURL(filename, getXWikiContext());
845    }
846   
847    /**
848    * Get the relative URL of the given action for the the given attachment name.
849    *
850    * @param filename the name of the attachment.
851    * @param action what to do to the file for example "delattachment", "download" or "downloadrev".
852    * @return a string representation of a URL to do the given operation or null if the file name is empty
853    */
 
854  3 toggle public String getAttachmentURL(String filename, String action)
855    {
856  3 return this.doc.getAttachmentURL(filename, action, getXWikiContext());
857    }
858   
859    /**
860    * Get the relative URL of an action on an attachment. the given action for the the given attachment name with
861    * "queryString" parameters
862    *
863    * @param filename the name of the attachment.
864    * @param action what to do to the file for example "delattachment", "download" or "downloadrev"
865    * @param queryString parameters added to the URL, the "rev" parameter is used to specify a revision if using the
866    * "downloadrev" action. The query string must not begin with an ? character.
867    * @return a string representation of a URL to do the given operation or null if the file name is empty
868    */
 
869  24 toggle public String getAttachmentURL(String filename, String action, String queryString)
870    {
871  24 return this.doc.getAttachmentURL(filename, action, queryString, getXWikiContext());
872    }
873   
874    /**
875    * Get an old revision of an attachment.
876    *
877    * @param filename the name of the attachment.
878    * @param version a revision number such as "1.1" or "1.2".
879    * @return the URL for accessing to the archive of the attachment "filename" at the version "version" or null if the
880    * file name is empty
881    */
 
882  0 toggle public String getAttachmentRevisionURL(String filename, String version)
883    {
884  0 return this.doc.getAttachmentRevisionURL(filename, version, getXWikiContext());
885    }
886   
887    /**
888    * Get an old revision of an attachment.
889    *
890    * @param filename the name of the attachment.
891    * @param version a revision number such as "1.1" or "1.2".
892    * @param queryString additional query parameters to pass in the request.
893    * @return the URL for accessing to the archive of the attachment "filename" at the version "version" with the given
894    * queryString parameters or null if the file name is empty
895    */
 
896  0 toggle public String getAttachmentRevisionURL(String filename, String version, String queryString)
897    {
898  0 return this.doc.getAttachmentRevisionURL(filename, version, queryString, getXWikiContext());
899    }
900   
901    /**
902    * Get the URL of this document.
903    *
904    * @return the URL to view this document, this will be a relitive URL for example: /xwiki/bin/view/Main/WebHome
905    * @see #getExternalURL() for an absolute URL which can used outside of the site.
906    */
 
907  7226 toggle public String getURL()
908    {
909  7226 return this.doc.getURL("view", getXWikiContext());
910    }
911   
912    /**
913    * Get the URL to do a given action on this document.
914    *
915    * @param action what to do to the document for example "view", "edit" or "inline".
916    * @return the URL of this document with the given action.
917    * @see #getExternalURL(String) for an absolute URL which can used outside of the site.
918    */
 
919  21415 toggle public String getURL(String action)
920    {
921  21414 return this.doc.getURL(action, getXWikiContext());
922    }
923   
924    /**
925    * Get the URL to do a given action on this document.
926    *
927    * @param action what to do to the document for example "view", "edit" or "inline".
928    * @param queryString parameters to pass in the request eg: {@code paramA=value1&paramB=value2}
929    * @return the URL of this document with the given action and queryString as parameters.
930    * @see #getExternalURL(String, String) for an absolute URL which can used outside of the site.
931    */
 
932  13478 toggle public String getURL(String action, String queryString)
933    {
934  13477 return this.doc.getURL(action, queryString, getXWikiContext());
935    }
936   
937    /**
938    * Get the external URL to do a given action on this document.
939    *
940    * @return the full URL of the document, sutable for use at external websites for example:
941    * http://www.xwiki.org/xwiki/bin/view/Main/WebHome
942    * @see #getURL() for a reletive URL which can only be used inside of the site.
943    */
 
944  17 toggle public String getExternalURL()
945    {
946  17 return this.doc.getExternalURL("view", getXWikiContext());
947    }
948   
949    /**
950    * Get the external URL to do a given action on this document.
951    *
952    * @param action what to do to the document for example "view", "edit" or "inline".
953    * @return the URL of this document with the given action.
954    * @see #getURL() for a relative URL which can only be used inside of the site.
955    */
 
956  553 toggle public String getExternalURL(String action)
957    {
958  553 return this.doc.getExternalURL(action, getXWikiContext());
959    }
960   
961    /**
962    * Get the URL to do a given action on this document.
963    *
964    * @param action what to do to the document for example "view", "edit" or "inline".
965    * @param queryString parameters to pass in the request eg: {@code paramA=value1&paramB=value2}
966    * @return the URL of this document with the given action and queryString as parameters.
967    * @see #getURL() for a relative URL which can only be used inside of the site.
968    */
 
969  25 toggle public String getExternalURL(String action, String queryString)
970    {
971  25 return this.doc.getExternalURL(action, queryString, getXWikiContext());
972    }
973   
974    /**
975    * @return the relative URL of the parent document of this document
976    */
 
977  0 toggle public String getParentURL() throws XWikiException
978    {
979  0 return this.doc.getParentURL(getXWikiContext());
980    }
981   
982    /**
983    * @return the XClass associated to this document when the document represents an XWiki Class
984    */
 
985  585 toggle public Class getxWikiClass()
986    {
987  585 BaseClass bclass = this.getDoc().getXClass();
988  585 if (bclass == null) {
989  0 return null;
990    } else {
991  585 return new Class(bclass, getXWikiContext());
992    }
993    }
994   
995    /**
996    * @return the array of XClasses representing the objects of this document
997    */
 
998  44 toggle public Class[] getxWikiClasses()
999    {
1000  44 List<BaseClass> list = this.getDoc().getXClasses(getXWikiContext());
1001  44 if (list == null) {
1002  0 return null;
1003    }
1004  44 Class[] result = new Class[list.size()];
1005  112 for (int i = 0; i < list.size(); i++) {
1006  68 result[i] = new Class(list.get(i), getXWikiContext());
1007    }
1008  44 return result;
1009    }
1010   
1011    /**
1012    * Creates a New XWiki Object of the given classname
1013    *
1014    * @param classname the classname used
1015    * @return the number of the object created
1016    */
 
1017  80 toggle public int createNewObject(String classname) throws XWikiException
1018    {
1019  80 int index = getDoc().createNewObject(classname, getXWikiContext());
1020   
1021  80 updateAuthor();
1022   
1023  80 return index;
1024    }
1025   
1026    /**
1027    * Creates a New XWiki Object of the given classname
1028    *
1029    * @param classname the classname used
1030    * @return the object created
1031    */
 
1032  77 toggle public Object newObject(String classname) throws XWikiException
1033    {
1034  77 int nb = createNewObject(classname);
1035  77 return getObject(classname, nb);
1036    }
1037   
1038    /**
1039    * @return true of the document has been loaded from cache
1040    */
 
1041  0 toggle public boolean isFromCache()
1042    {
1043  0 return this.doc.isFromCache();
1044    }
1045   
1046    /**
1047    * @param classname the classname used
1048    * @return the number of objects available for a given classname
1049    */
 
1050  0 toggle public int getObjectNumbers(String classname)
1051    {
1052  0 return this.doc.getObjectNumbers(classname);
1053    }
1054   
1055    /**
1056    * Get the list of all objects available in this document organized in a Map by classname
1057    *
1058    * @return the map of objects
1059    */
 
1060  642 toggle public Map<String, Vector<Object>> getxWikiObjects()
1061    {
1062  642 Map<DocumentReference, List<BaseObject>> map = this.getDoc().getXObjects();
1063  642 Map<String, Vector<Object>> resultmap = new HashMap<String, Vector<Object>>();
1064  642 for (Map.Entry<DocumentReference, List<BaseObject>> entry : map.entrySet()) {
1065  308 List<BaseObject> objects = entry.getValue();
1066  308 if (objects != null) {
1067  308 resultmap.put(getLocalEntityReferenceSerializer().serialize(entry.getKey()), getXObjects(objects));
1068    }
1069    }
1070  642 return resultmap;
1071    }
1072   
 
1073  2513 toggle protected Vector<Object> getXObjects(List<BaseObject> objects)
1074    {
1075  2513 if (objects == null) {
1076  1522 return new Vector<Object>(0);
1077    }
1078  991 Vector<Object> result = new Vector<Object>(objects.size());
1079  991 for (BaseObject bobj : objects) {
1080  1220 if (bobj != null) {
1081  1200 result.add(newObjectApi(bobj, getXWikiContext()));
1082    }
1083    }
1084  991 return result;
1085    }
1086   
1087    /**
1088    * Get the list of objects for a given classname classname
1089    *
1090    * @return the vector of objects
1091    */
 
1092  1355 toggle public Vector<Object> getObjects(String className)
1093    {
1094  1355 List<BaseObject> objects = this.getDoc().getXObjects(this.doc.resolveClassReference(className));
1095  1355 return getXObjects(objects);
1096    }
1097   
1098    /**
1099    * Get the first object that contains the given fieldname
1100    *
1101    * @param fieldname name of the field to find in the object
1102    * @return the XWiki Object
1103    */
 
1104  3 toggle public Object getFirstObject(String fieldname)
1105    {
1106  3 try {
1107  3 BaseObject obj = this.getDoc().getFirstObject(fieldname, getXWikiContext());
1108  3 if (obj == null) {
1109  0 return null;
1110    } else {
1111  3 return newObjectApi(obj, getXWikiContext());
1112    }
1113    } catch (Exception e) {
1114  0 return null;
1115    }
1116    }
1117   
1118    /**
1119    * Get the first object of a given classname that has a field name matching the given value
1120    *
1121    * @param classname name of the class of the object to look for
1122    * @param key name of the field to find in the object
1123    * @param value value of the field to find in the object
1124    * @param failover true if the first object will be given when none found
1125    * @return the XWiki Object
1126    */
 
1127  1 toggle public Object getObject(String classname, String key, String value, boolean failover)
1128    {
1129  1 try {
1130  1 BaseObject obj = this.getDoc().getObject(classname, key, value, failover);
1131  1 if (obj == null) {
1132  0 return null;
1133    } else {
1134  1 return newObjectApi(obj, getXWikiContext());
1135    }
1136    } catch (Exception e) {
1137  0 return null;
1138    }
1139    }
1140   
1141    /**
1142    * Select a subset of objects from a given class, filtered on a "key = value" criteria.
1143    *
1144    * @param classname The type of objects to return.
1145    * @param key The name of the property used for filtering.
1146    * @param value The required value.
1147    * @return A Vector of {@link Object objects} matching the criteria. If no objects are found, or if the key is an
1148    * empty String, then an empty vector is returned.
1149    */
 
1150  15 toggle public Vector<Object> getObjects(String classname, String key, String value)
1151    {
1152  15 Vector<Object> result = new Vector<Object>();
1153  15 if (StringUtils.isBlank(key) || value == null) {
1154  0 return getObjects(classname);
1155    }
1156  15 try {
1157  15 Vector<BaseObject> allObjects = this.getDoc().getObjects(classname);
1158  15 if (allObjects == null || allObjects.size() == 0) {
1159  0 return result;
1160    } else {
1161  15 for (BaseObject obj : allObjects) {
1162  40 if (obj != null) {
1163  34 BaseProperty prop = (BaseProperty) obj.get(key);
1164  34 if (prop == null || prop.getValue() == null) {
1165  20 continue;
1166    }
1167  14 if (value.equals(prop.getValue().toString())) {
1168  9 result.add(newObjectApi(obj, getXWikiContext()));
1169    }
1170    }
1171    }
1172    }
1173    } catch (Exception e) {
1174    }
1175  15 return result;
1176    }
1177   
1178    /**
1179    * Get the first object of a given classname that has a field name matching the given value When none found this
1180    * method will return null
1181    *
1182    * @param classname name of the class of the object to look for
1183    * @param key name of the field to find in the object
1184    * @param value value of the field to find in the object
1185    * @return the XWiki Object
1186    */
 
1187  238 toggle public Object getObject(String classname, String key, String value)
1188    {
1189  238 try {
1190  238 BaseObject obj = this.getDoc().getObject(classname, key, value);
1191  238 if (obj == null) {
1192  64 return null;
1193    } else {
1194  174 return newObjectApi(obj, getXWikiContext());
1195    }
1196    } catch (Exception e) {
1197  0 return null;
1198    }
1199    }
1200   
1201    /**
1202    * Get the first object matching the given classname
1203    *
1204    * @param classname name of the class of the object to look for
1205    * @return the XWiki Object
1206    */
 
1207  7866 toggle public Object getObject(String classname)
1208    {
1209  7864 return getObject(classname, false);
1210    }
1211   
1212    /**
1213    * get the object of the given className. If there is no object of this className and the create parameter at true,
1214    * the object is created.
1215    *
1216    * @param classname name of the class of the object to look for
1217    * @param create true of the object should be created when it does not exist
1218    * @return the XWiki Object
1219    */
 
1220  7869 toggle public Object getObject(String classname, boolean create)
1221    {
1222  7870 try {
1223  7870 BaseObject obj = getDoc().getObject(classname, create, getXWikiContext());
1224   
1225  7870 if (obj == null) {
1226  6270 return null;
1227    } else {
1228  1600 return newObjectApi(obj, getXWikiContext());
1229    }
1230    } catch (Exception e) {
1231  0 return null;
1232    }
1233    }
1234   
1235    /**
1236    * Get the object matching the given classname and given object number
1237    *
1238    * @param classname name of the class of the object
1239    * @param nb number of the object
1240    * @return the XWiki Object
1241    */
 
1242  7982 toggle public Object getObject(String classname, int nb)
1243    {
1244  7982 try {
1245  7982 BaseObject obj = this.getDoc().getObject(classname, nb);
1246  7981 if (obj == null) {
1247  4474 return null;
1248    } else {
1249  3502 return newObjectApi(obj, getXWikiContext());
1250    }
1251    } catch (Exception e) {
1252  0 return null;
1253    }
1254    }
1255   
 
1256  6488 toggle private Object newObjectApi(BaseObject obj, XWikiContext context)
1257    {
1258  6488 return obj.newObjectApi(obj, context);
1259    }
1260   
 
1261  0 toggle public String getXMLContent() throws XWikiException
1262    {
1263  0 String xml = this.doc.getXMLContent(getXWikiContext());
1264  0 return getXWikiContext().getUtil().substitute("s/<email>.*?<\\/email>/<email>********<\\/email>/goi",
1265    getXWikiContext().getUtil().substitute("s/<password>.*?<\\/password>/<password>********<\\/password>/goi",
1266    xml));
1267    }
1268   
 
1269  0 toggle public String toXML() throws XWikiException
1270    {
1271  0 if (hasProgrammingRights()) {
1272  0 return this.doc.toXML(getXWikiContext());
1273    } else {
1274  0 return "";
1275    }
1276    }
1277   
 
1278  0 toggle public org.dom4j.Document toXMLDocument() throws XWikiException
1279    {
1280  0 if (hasProgrammingRights()) {
1281  0 return this.doc.toXMLDocument(getXWikiContext());
1282    } else {
1283  0 return null;
1284    }
1285    }
1286   
 
1287  0 toggle public Version[] getRevisions() throws XWikiException
1288    {
1289  0 return this.doc.getRevisions(getXWikiContext());
1290    }
1291   
 
1292  0 toggle public String[] getRecentRevisions() throws XWikiException
1293    {
1294  0 return this.doc.getRecentRevisions(5, getXWikiContext());
1295    }
1296   
 
1297  0 toggle public String[] getRecentRevisions(int nb) throws XWikiException
1298    {
1299  0 return this.doc.getRecentRevisions(nb, getXWikiContext());
1300    }
1301   
1302    /**
1303    * Get document versions matching criterias like author, minimum creation date, etc.
1304    *
1305    * @param criteria criteria used to match versions
1306    * @return a list of matching versions
1307    */
 
1308  14 toggle public List<String> getRevisions(RevisionCriteria criteria) throws XWikiException
1309    {
1310  14 return this.doc.getRevisions(criteria, this.context);
1311    }
1312   
1313    /**
1314    * Get information about a document version : author, date, etc.
1315    *
1316    * @param version the version you want to get information about
1317    * @return a new RevisionInfo object
1318    */
 
1319  11 toggle public RevisionInfo getRevisionInfo(String version) throws XWikiException
1320    {
1321  11 return new RevisionInfo(this.doc.getRevisionInfo(version, getXWikiContext()), getXWikiContext());
1322    }
1323   
 
1324  1685 toggle public List<Attachment> getAttachmentList()
1325    {
1326  1685 List<Attachment> apis = new ArrayList<Attachment>();
1327  1685 for (XWikiAttachment attachment : this.getDoc().getAttachmentList()) {
1328  190 apis.add(new Attachment(this, attachment, getXWikiContext()));
1329    }
1330  1685 return apis;
1331    }
1332   
 
1333  850 toggle public Vector<Object> getComments()
1334    {
1335  850 return getComments(true);
1336    }
1337   
 
1338  850 toggle public Vector<Object> getComments(boolean asc)
1339    {
1340  850 return getXObjects(this.getDoc().getComments(asc));
1341    }
1342   
1343    /**
1344    * Setting the current object to the given object. Following calls to display() will use this object as the
1345    * reference for finding properties.
1346    *
1347    * @param object Object to use as a reference for further display calls
1348    */
 
1349  145 toggle public void use(Object object)
1350    {
1351  145 this.currentObj = object;
1352    }
1353   
1354    /**
1355    * Setting the current object to the first object of the given class name. Following calls to display() will use
1356    * this object as the reference for finding properties.
1357    *
1358    * @param className class used to find the first object to use as the reference for display calls
1359    */
 
1360  311 toggle public void use(String className)
1361    {
1362  311 this.currentObj = getObject(className);
1363    }
1364   
1365    /**
1366    * Setting the current object to the object of the given class name and the given number. Following calls to
1367    * display() will use this object as the reference for finding properties.
1368    *
1369    * @param className class used to find the object to use as the reference for display calls
1370    * @param nb number of the object to use as the reference for display calls
1371    */
 
1372  0 toggle public void use(String className, int nb)
1373    {
1374  0 this.currentObj = getObject(className, nb);
1375    }
1376   
1377    /**
1378    * @return the className of the current active object use for display calls.
1379    */
 
1380  0 toggle public String getActiveClass()
1381    {
1382  0 if (this.currentObj == null) {
1383  0 return null;
1384    } else {
1385  0 return this.currentObj.getName();
1386    }
1387    }
1388   
1389    /**
1390    * Displays the pretty name of the given field. This function uses the active object or will find the first object
1391    * that has the given field.
1392    *
1393    * @param fieldname fieldname to display the pretty name of
1394    * @return the pretty name display of the field.
1395    */
 
1396  450 toggle public String displayPrettyName(String fieldname)
1397    {
1398  450 if (this.currentObj == null) {
1399  0 return this.doc.displayPrettyName(fieldname, getXWikiContext());
1400    } else {
1401  450 return this.doc.displayPrettyName(fieldname, this.currentObj.getBaseObject(), getXWikiContext());
1402    }
1403    }
1404   
1405    /**
1406    * Displays the pretty name of the given field of the given object.
1407    *
1408    * @param fieldname fieldname to display the pretty name of
1409    * @param obj Object to find the class to display the pretty name of
1410    * @return the pretty name display of the field.
1411    */
 
1412  4 toggle public String displayPrettyName(String fieldname, Object obj)
1413    {
1414  4 if (obj == null) {
1415  0 return "";
1416    }
1417  4 return this.doc.displayPrettyName(fieldname, obj.getBaseObject(), getXWikiContext());
1418    }
1419   
1420    /**
1421    * Displays the pretty name of the given field. This function uses the active object or will find the first object
1422    * that has the given field. with the optional addition of a mandatory field.
1423    *
1424    * @param fieldname fieldname to display the pretty name of
1425    * @param showMandatory true to display a mandatory sign
1426    * @return the pretty name display of the field.
1427    */
 
1428  0 toggle public String displayPrettyName(String fieldname, boolean showMandatory)
1429    {
1430  0 if (this.currentObj == null) {
1431  0 return this.doc.displayPrettyName(fieldname, showMandatory, getXWikiContext());
1432    } else {
1433  0 return this.doc.displayPrettyName(fieldname, showMandatory, this.currentObj.getBaseObject(),
1434    getXWikiContext());
1435    }
1436    }
1437   
1438    /**
1439    * Displays the pretty name of the given field of the given object. with the optional addition of a mandatory field.
1440    *
1441    * @param fieldname fieldname to display the pretty name of
1442    * @param obj Object to find the class to display the pretty name of
1443    * @param showMandatory true to display a mandatory sign
1444    * @return the pretty name display of the field.
1445    */
 
1446  0 toggle public String displayPrettyName(String fieldname, boolean showMandatory, Object obj)
1447    {
1448  0 if (obj == null) {
1449  0 return "";
1450    }
1451  0 return this.doc.displayPrettyName(fieldname, showMandatory, obj.getBaseObject(), getXWikiContext());
1452    }
1453   
1454    /**
1455    * Displays the pretty name of the given field. This function uses the active object or will find the first object
1456    * that has the given field. with the optional addition of a mandatory field before or after the field
1457    *
1458    * @param fieldname fieldname to display the pretty name of
1459    * @param showMandatory true to display a mandatory sign
1460    * @param before true if the mandatory sign should be before the field
1461    * @return the pretty name display of the field.
1462    */
 
1463  0 toggle public String displayPrettyName(String fieldname, boolean showMandatory, boolean before)
1464    {
1465  0 if (this.currentObj == null) {
1466  0 return this.doc.displayPrettyName(fieldname, showMandatory, before, getXWikiContext());
1467    } else {
1468  0 return this.doc.displayPrettyName(fieldname, showMandatory, before, this.currentObj.getBaseObject(),
1469    getXWikiContext());
1470    }
1471    }
1472   
1473    /**
1474    * Displays the pretty name of the given field of the given object. with the optional addition of a mandatory field
1475    * before or after the field
1476    *
1477    * @param fieldname fieldname to display the pretty name of
1478    * @param showMandatory true to display a mandatory sign
1479    * @param before true if the mandatory sign should be before the field
1480    * @param obj Object to find the class to display the pretty name of
1481    * @return the pretty name display of the field.
1482    */
 
1483  0 toggle public String displayPrettyName(String fieldname, boolean showMandatory, boolean before, Object obj)
1484    {
1485  0 if (obj == null) {
1486  0 return "";
1487    }
1488  0 return this.doc.displayPrettyName(fieldname, showMandatory, before, obj.getBaseObject(), getXWikiContext());
1489    }
1490   
1491    /**
1492    * Displays the tooltip of the given field. This function uses the active object or will find the first object that
1493    * has the given field.
1494    *
1495    * @param fieldname fieldname to display the tooltip of
1496    * @return the tooltip display of the field.
1497    */
 
1498  0 toggle public String displayTooltip(String fieldname)
1499    {
1500  0 if (this.currentObj == null) {
1501  0 return this.doc.displayTooltip(fieldname, getXWikiContext());
1502    } else {
1503  0 return this.doc.displayTooltip(fieldname, this.currentObj.getBaseObject(), getXWikiContext());
1504    }
1505    }
1506   
1507    /**
1508    * Displays the tooltip of the given field of the given object.
1509    *
1510    * @param fieldname fieldname to display the tooltip of
1511    * @param obj Object to find the class to display the tooltip of
1512    * @return the tooltip display of the field.
1513    */
 
1514  0 toggle public String displayTooltip(String fieldname, Object obj)
1515    {
1516  0 if (obj == null) {
1517  0 return "";
1518    }
1519  0 return this.doc.displayTooltip(fieldname, obj.getBaseObject(), getXWikiContext());
1520    }
1521   
1522    /**
1523    * Displays the given field. The display mode will be decided depending on page context (edit or inline context will
1524    * display in edit, view context in view) This function uses the active object or will find the first object that
1525    * has the given field. This function can return html inside and html macro
1526    *
1527    * @param fieldname fieldname to display
1528    * @return the display of the field.
1529    */
 
1530  585 toggle public String display(String fieldname)
1531    {
1532  585 if (this.currentObj == null) {
1533  39 return this.doc.display(fieldname, getXWikiContext());
1534    } else {
1535  546 return this.doc.display(fieldname, this.currentObj.getBaseObject(), getXWikiContext());
1536    }
1537    }
1538   
1539    /**
1540    * Displays the given field in the given mode. This function uses the active object or will find the first object
1541    * that has the given field. This function can return html inside and html macro
1542    *
1543    * @param fieldname fieldname to display
1544    * @param mode display mode to use (view, edit, hidden, search)
1545    * @return the display of the field.
1546    */
 
1547  131 toggle public String display(String fieldname, String mode)
1548    {
1549  131 if (this.currentObj == null) {
1550  0 return this.doc.display(fieldname, mode, getXWikiContext());
1551    } else {
1552  131 return this.doc.display(fieldname, mode, this.currentObj.getBaseObject(), getXWikiContext());
1553    }
1554    }
1555   
1556    /**
1557    * Displays the given field in the given mode. This function uses the active object or will find the first object
1558    * that has the given field. This function can return html inside and html macro A given prefix is added to the
1559    * field names when these are forms.
1560    *
1561    * @param fieldname fieldname to display
1562    * @param mode display mode to use (view, edit, hidden, search)
1563    * @param prefix prefix to use for the form names
1564    * @return the display of the field.
1565    */
 
1566  0 toggle public String display(String fieldname, String mode, String prefix)
1567    {
1568  0 if (this.currentObj == null) {
1569  0 return this.doc.display(fieldname, mode, prefix, getXWikiContext());
1570    } else {
1571  0 return this.doc.display(fieldname, mode, prefix, this.currentObj.getBaseObject(), getSyntaxId(),
1572    getXWikiContext());
1573    }
1574    }
1575   
1576    /**
1577    * Displays the given field of the given object The display mode will be decided depending on page context (edit or
1578    * inline context will display in edit, view context in view) This function can return html inside and html macro
1579    *
1580    * @param fieldname fieldname to display
1581    * @param obj object from which to take the field
1582    * @return the display of the field.
1583    */
 
1584  61 toggle public String display(String fieldname, Object obj)
1585    {
1586  61 if (obj == null) {
1587  0 return "";
1588    }
1589  61 return this.doc.display(fieldname, obj.getBaseObject(), getXWikiContext());
1590    }
1591   
1592    /**
1593    * Displays the given field of the given object using the given mode and syntax rendering The display mode will be
1594    * decided depending on page context (edit or inline context will display in edit, view context in view) This
1595    * function can return html inside and html macro
1596    *
1597    * @param fieldname the name of the field to display
1598    * @param type the type of the field to display
1599    * @param obj the object containing the field to display
1600    * @param wrappingSyntaxId the syntax of the content in which the result will be included. This to take care of some
1601    * escaping depending of the syntax.
1602    * @return the rendered field
1603    */
 
1604  0 toggle public String display(String fieldname, String type, Object obj, String wrappingSyntaxId)
1605    {
1606  0 if (obj == null) {
1607  0 return "";
1608    }
1609  0 return this.doc.display(fieldname, type, obj.getBaseObject(), wrappingSyntaxId, getXWikiContext());
1610    }
1611   
1612    /**
1613    * Displays the given field of the given object in the given mode. This function can return html inside and html
1614    * macro
1615    *
1616    * @param fieldname fieldname to display
1617    * @param mode display mode to use (view, edit, hidden, search)
1618    * @param obj the object containing the field to display
1619    * @return the display of the field.
1620    */
 
1621  839 toggle public String display(String fieldname, String mode, Object obj)
1622    {
1623  839 if (obj == null) {
1624  0 return "";
1625    }
1626  839 return this.doc.display(fieldname, mode, obj.getBaseObject(), getXWikiContext());
1627    }
1628   
1629    /**
1630    * Displays the given field of the given object in the given mode. This function can return html inside and html
1631    * macro A given prefix is added to the field names when these are forms.
1632    *
1633    * @param fieldname fieldname to display
1634    * @param mode display mode to use (view, edit, hidden, search)
1635    * @param prefix prefix to use for the form names
1636    * @param obj the object containing the field to display
1637    * @return the display of the field.
1638    */
 
1639  0 toggle public String display(String fieldname, String mode, String prefix, Object obj)
1640    {
1641  0 if (obj == null) {
1642  0 return "";
1643    }
1644  0 return this.doc.display(fieldname, mode, prefix, obj.getBaseObject(), getSyntaxId(), getXWikiContext());
1645    }
1646   
 
1647  0 toggle public String displayForm(String className, String header, String format)
1648    {
1649  0 return this.doc.displayForm(className, header, format, getXWikiContext());
1650    }
1651   
 
1652  0 toggle public String displayForm(String className, String header, String format, boolean linebreak)
1653    {
1654  0 return this.doc.displayForm(className, header, format, linebreak, getXWikiContext());
1655    }
1656   
 
1657  0 toggle public String displayForm(String className)
1658    {
1659  0 return this.doc.displayForm(className, getXWikiContext());
1660    }
1661   
 
1662  0 toggle public String displayRendered(com.xpn.xwiki.api.PropertyClass pclass, String prefix, Collection object)
1663    throws XWikiException
1664    {
1665  0 if ((pclass == null) || (object == null)) {
1666  0 return "";
1667    }
1668  0 return this.doc.displayRendered(pclass.getBasePropertyClass(), prefix, object.getCollection(),
1669    getXWikiContext());
1670    }
1671   
 
1672  326 toggle public String displayView(com.xpn.xwiki.api.PropertyClass pclass, String prefix, Collection object)
1673    {
1674  326 if ((pclass == null) || (object == null)) {
1675  0 return "";
1676    }
1677  326 return this.doc.displayView(pclass.getBasePropertyClass(), prefix, object.getCollection(), getXWikiContext());
1678    }
1679   
 
1680  2034 toggle public String displayEdit(com.xpn.xwiki.api.PropertyClass pclass, String prefix, Collection object)
1681    {
1682  2034 if ((pclass == null) || (object == null)) {
1683  0 return "";
1684    }
1685  2034 return this.doc.displayEdit(pclass.getBasePropertyClass(), prefix, object.getCollection(), getXWikiContext());
1686    }
1687   
 
1688  0 toggle public String displayHidden(com.xpn.xwiki.api.PropertyClass pclass, String prefix, Collection object)
1689    {
1690  0 if ((pclass == null) || (object == null)) {
1691  0 return "";
1692    }
1693  0 return this.doc.displayHidden(pclass.getBasePropertyClass(), prefix, object.getCollection(), getXWikiContext());
1694    }
1695   
 
1696  1 toggle public List<String> getIncludedPages()
1697    {
1698  1 return this.doc.getIncludedPages(getXWikiContext());
1699    }
1700   
 
1701  0 toggle public List<String> getIncludedMacros()
1702    {
1703  0 return this.doc.getIncludedMacros(getXWikiContext());
1704    }
1705   
 
1706  0 toggle public List<String> getLinkedPages()
1707    {
1708  0 return new ArrayList<String>(this.doc.getUniqueLinkedPages(getXWikiContext()));
1709    }
1710   
 
1711  4052 toggle public Attachment getAttachment(String filename)
1712    {
1713  4052 XWikiAttachment attach = this.getDoc().getAttachment(filename);
1714  4052 if (attach == null) {
1715  505 return null;
1716    } else {
1717  3547 return new Attachment(this, attach, getXWikiContext());
1718    }
1719    }
1720   
 
1721  1 toggle public List<Delta> getContentDiff(Document origdoc, Document newdoc)
1722    throws XWikiException, DifferentiationFailedException
1723    {
1724  1 try {
1725  1 if ((origdoc == null) && (newdoc == null)) {
1726  0 return Collections.emptyList();
1727    }
1728  1 if (origdoc == null) {
1729  0 return this.doc.getContentDiff(new XWikiDocument(newdoc.getDocumentReference()), newdoc.doc,
1730    getXWikiContext());
1731    }
1732  1 if (newdoc == null) {
1733  0 return this.doc.getContentDiff(origdoc.doc, new XWikiDocument(origdoc.getDocumentReference()),
1734    getXWikiContext());
1735    }
1736   
1737  1 return this.doc.getContentDiff(origdoc.doc, newdoc.doc, getXWikiContext());
1738    } catch (Exception e) {
1739  0 java.lang.Object[] args = { origdoc.getFullName(), origdoc.getVersion(), newdoc.getVersion() };
1740  0 List list = new ArrayList();
1741  0 XWikiException xe =
1742    new XWikiException(XWikiException.MODULE_XWIKI_DIFF, XWikiException.ERROR_XWIKI_DIFF_CONTENT_ERROR,
1743    "Error while making content diff of {0} between version {1} and version {2}", e, args);
1744  0 String errormsg = Util.getHTMLExceptionMessage(xe, getXWikiContext());
1745  0 list.add(errormsg);
1746  0 return list;
1747    }
1748    }
1749   
 
1750  0 toggle public List<Delta> getXMLDiff(Document origdoc, Document newdoc)
1751    throws XWikiException, DifferentiationFailedException
1752    {
1753  0 try {
1754  0 if ((origdoc == null) && (newdoc == null)) {
1755  0 return Collections.emptyList();
1756    }
1757  0 if (origdoc == null) {
1758  0 return this.doc.getXMLDiff(new XWikiDocument(newdoc.getDocumentReference()), newdoc.doc,
1759    getXWikiContext());
1760    }
1761  0 if (newdoc == null) {
1762  0 return this.doc.getXMLDiff(origdoc.doc, new XWikiDocument(origdoc.getDocumentReference()),
1763    getXWikiContext());
1764    }
1765   
1766  0 return this.doc.getXMLDiff(origdoc.doc, newdoc.doc, getXWikiContext());
1767    } catch (Exception e) {
1768  0 java.lang.Object[] args = { origdoc.getFullName(), origdoc.getVersion(), newdoc.getVersion() };
1769  0 List list = new ArrayList();
1770  0 XWikiException xe =
1771    new XWikiException(XWikiException.MODULE_XWIKI_DIFF, XWikiException.ERROR_XWIKI_DIFF_XML_ERROR,
1772    "Error while making xml diff of {0} between version {1} and version {2}", e, args);
1773  0 String errormsg = Util.getHTMLExceptionMessage(xe, getXWikiContext());
1774  0 list.add(errormsg);
1775  0 return list;
1776    }
1777    }
1778   
 
1779  0 toggle public List<Delta> getRenderedContentDiff(Document origdoc, Document newdoc)
1780    throws XWikiException, DifferentiationFailedException
1781    {
1782  0 try {
1783  0 if ((origdoc == null) && (newdoc == null)) {
1784  0 return Collections.emptyList();
1785    }
1786  0 if (origdoc == null) {
1787  0 return this.doc.getRenderedContentDiff(new XWikiDocument(newdoc.getDocumentReference()), newdoc.doc,
1788    getXWikiContext());
1789    }
1790  0 if (newdoc == null) {
1791  0 return this.doc.getRenderedContentDiff(origdoc.doc, new XWikiDocument(origdoc.getDocumentReference()),
1792    getXWikiContext());
1793    }
1794   
1795  0 return this.doc.getRenderedContentDiff(origdoc.doc, newdoc.doc, getXWikiContext());
1796    } catch (Exception e) {
1797  0 java.lang.Object[] args = { origdoc.getFullName(), origdoc.getVersion(), newdoc.getVersion() };
1798  0 List list = new ArrayList();
1799  0 XWikiException xe =
1800    new XWikiException(XWikiException.MODULE_XWIKI_DIFF, XWikiException.ERROR_XWIKI_DIFF_RENDERED_ERROR,
1801    "Error while making rendered diff of {0} between version {1} and version {2}", e, args);
1802  0 String errormsg = Util.getHTMLExceptionMessage(xe, getXWikiContext());
1803  0 list.add(errormsg);
1804  0 return list;
1805    }
1806    }
1807   
 
1808  3 toggle public List<MetaDataDiff> getMetaDataDiff(Document origdoc, Document newdoc) throws XWikiException
1809    {
1810  3 try {
1811  3 if ((origdoc == null) && (newdoc == null)) {
1812  0 return Collections.emptyList();
1813    }
1814  3 if (origdoc == null) {
1815  0 return this.doc.getMetaDataDiff(new XWikiDocument(newdoc.getDocumentReference()), newdoc.doc,
1816    getXWikiContext());
1817    }
1818  3 if (newdoc == null) {
1819  0 return this.doc.getMetaDataDiff(origdoc.doc, new XWikiDocument(origdoc.getDocumentReference()),
1820    getXWikiContext());
1821    }
1822   
1823  3 return this.doc.getMetaDataDiff(origdoc.doc, newdoc.doc, getXWikiContext());
1824    } catch (Exception e) {
1825  0 java.lang.Object[] args = { origdoc.getFullName(), origdoc.getVersion(), newdoc.getVersion() };
1826  0 List list = new ArrayList();
1827  0 XWikiException xe =
1828    new XWikiException(XWikiException.MODULE_XWIKI_DIFF, XWikiException.ERROR_XWIKI_DIFF_METADATA_ERROR,
1829    "Error while making meta data diff of {0} between version {1} and version {2}", e, args);
1830  0 String errormsg = Util.getHTMLExceptionMessage(xe, getXWikiContext());
1831  0 list.add(errormsg);
1832  0 return list;
1833    }
1834    }
1835   
 
1836  3 toggle public List<List<ObjectDiff>> getObjectDiff(Document origdoc, Document newdoc)
1837    {
1838  3 try {
1839  3 if ((origdoc == null) && (newdoc == null)) {
1840  0 return Collections.emptyList();
1841    }
1842  3 if (origdoc == null) {
1843  0 return this.doc.getObjectDiff(new XWikiDocument(newdoc.getDocumentReference()), newdoc.doc,
1844    getXWikiContext());
1845    }
1846  3 if (newdoc == null) {
1847  0 return this.doc.getObjectDiff(origdoc.doc, new XWikiDocument(origdoc.getDocumentReference()),
1848    getXWikiContext());
1849    }
1850   
1851  3 return this.doc.getObjectDiff(origdoc.doc, newdoc.doc, getXWikiContext());
1852    } catch (Exception e) {
1853  0 java.lang.Object[] args = { origdoc.getFullName(), origdoc.getVersion(), newdoc.getVersion() };
1854  0 List list = new ArrayList();
1855  0 XWikiException xe =
1856    new XWikiException(XWikiException.MODULE_XWIKI_DIFF, XWikiException.ERROR_XWIKI_DIFF_OBJECT_ERROR,
1857    "Error while making meta object diff of {0} between version {1} and version {2}", e, args);
1858  0 String errormsg = Util.getHTMLExceptionMessage(xe, getXWikiContext());
1859  0 list.add(errormsg);
1860  0 return list;
1861    }
1862    }
1863   
 
1864  3 toggle public List<List<ObjectDiff>> getClassDiff(Document origdoc, Document newdoc)
1865    {
1866  3 try {
1867  3 if ((origdoc == null) && (newdoc == null)) {
1868  0 return Collections.emptyList();
1869    }
1870  3 if (origdoc == null) {
1871  0 return this.doc.getClassDiff(new XWikiDocument(newdoc.getDocumentReference()), newdoc.doc,
1872    getXWikiContext());
1873    }
1874  3 if (newdoc == null) {
1875  0 return this.doc.getClassDiff(origdoc.doc, new XWikiDocument(origdoc.getDocumentReference()),
1876    getXWikiContext());
1877    }
1878   
1879  3 return this.doc.getClassDiff(origdoc.doc, newdoc.doc, getXWikiContext());
1880    } catch (Exception e) {
1881  0 java.lang.Object[] args = { origdoc.getFullName(), origdoc.getVersion(), newdoc.getVersion() };
1882  0 List list = new ArrayList();
1883  0 XWikiException xe =
1884    new XWikiException(XWikiException.MODULE_XWIKI_DIFF, XWikiException.ERROR_XWIKI_DIFF_CLASS_ERROR,
1885    "Error while making class diff of {0} between version {1} and version {2}", e, args);
1886  0 String errormsg = Util.getHTMLExceptionMessage(xe, getXWikiContext());
1887  0 list.add(errormsg);
1888  0 return list;
1889    }
1890    }
1891   
 
1892  3 toggle public List<AttachmentDiff> getAttachmentDiff(Document origdoc, Document newdoc)
1893    {
1894  3 try {
1895  3 if ((origdoc == null) && (newdoc == null)) {
1896  0 return Collections.emptyList();
1897    }
1898  3 if (origdoc == null) {
1899  0 return wrapAttachmentDiff(this.doc.getAttachmentDiff(new XWikiDocument(newdoc.getDocumentReference()),
1900    newdoc.doc, getXWikiContext()));
1901    }
1902  3 if (newdoc == null) {
1903  0 return wrapAttachmentDiff(this.doc.getAttachmentDiff(origdoc.doc,
1904    new XWikiDocument(origdoc.getDocumentReference()), getXWikiContext()));
1905    }
1906   
1907  3 return wrapAttachmentDiff(this.doc.getAttachmentDiff(origdoc.doc, newdoc.doc, getXWikiContext()));
1908    } catch (Exception e) {
1909  0 java.lang.Object[] args = { (origdoc != null) ? origdoc.getFullName() : null,
1910  0 (origdoc != null) ? origdoc.getVersion() : null, (newdoc != null) ? newdoc.getVersion() : null };
1911  0 List list = new ArrayList();
1912  0 XWikiException xe =
1913    new XWikiException(XWikiException.MODULE_XWIKI_DIFF, XWikiException.ERROR_XWIKI_DIFF_ATTACHMENT_ERROR,
1914    "Error while making attachment diff of {0} between version {1} and version {2}", e, args);
1915  0 String errormsg = Util.getHTMLExceptionMessage(xe, getXWikiContext());
1916  0 list.add(errormsg);
1917  0 return list;
1918    }
1919    }
1920   
 
1921  3 toggle private List<AttachmentDiff> wrapAttachmentDiff(List<com.xpn.xwiki.doc.AttachmentDiff> diffs)
1922    {
1923  3 List<AttachmentDiff> safeAttachmentDiffs = new ArrayList<>();
1924  3 for (com.xpn.xwiki.doc.AttachmentDiff diff : diffs) {
1925  0 safeAttachmentDiffs.add(new AttachmentDiff(diff, getXWikiContext()));
1926    }
1927  3 return safeAttachmentDiffs;
1928    }
1929   
 
1930  0 toggle public List<Delta> getLastChanges() throws XWikiException, DifferentiationFailedException
1931    {
1932  0 return this.doc.getLastChanges(getXWikiContext());
1933    }
1934   
1935    /**
1936    * Get statistics about the number of request for the current page during the current month.
1937    *
1938    * @param action the type of request for which to retrieve statistics: view, edit...
1939    * @return the statistics object holding information for this document and the current month
1940    */
 
1941  0 toggle public DocumentStats getCurrentMonthPageStats(String action)
1942    {
1943  0 Scope scope = ScopeFactory.createPageScope(this.getFullName());
1944  0 Range range = RangeFactory.ALL;
1945  0 Period period = PeriodFactory.getCurrentMonth();
1946  0 XWikiStatsService statisticsService = getXWikiContext().getWiki().getStatsService(getXWikiContext());
1947  0 List<DocumentStats> stats = statisticsService.getDocumentStatistics(action, scope, period, range, this.context);
1948  0 if (stats.size() > 0) {
1949  0 return stats.get(0);
1950    }
1951  0 return new DocumentStats();
1952    }
1953   
1954    /**
1955    * Get statistics about the number of request for the current space during the current month.
1956    *
1957    * @param action the type of request for which to retrieve statistics: view, edit...
1958    * @return the statistics object holding information for the document's space and the current month
1959    */
 
1960  0 toggle public DocumentStats getCurrentMonthSpaceStats(String action)
1961    {
1962  0 Scope scope = ScopeFactory.createSpaceScope(this.doc.getSpace(), false);
1963  0 Range range = RangeFactory.ALL;
1964  0 Period period = PeriodFactory.getCurrentMonth();
1965  0 XWikiStatsService statisticsService = getXWikiContext().getWiki().getStatsService(getXWikiContext());
1966  0 List<DocumentStats> stats = statisticsService.getDocumentStatistics(action, scope, period, range, this.context);
1967  0 if (stats.size() > 0) {
1968  0 return stats.get(0);
1969    }
1970  0 return new DocumentStats();
1971    }
1972   
1973    /**
1974    * Get referer statistics for the current document during the current month.
1975    *
1976    * @return a list of referer statistics for the document's space
1977    */
 
1978  0 toggle public List<RefererStats> getCurrentMonthRefStats()
1979    {
1980  0 Scope scope = ScopeFactory.createPageScope(this.getFullName());
1981  0 Range range = RangeFactory.ALL;
1982  0 Period period = PeriodFactory.getCurrentMonth();
1983  0 XWikiStatsService statisticsService = getXWikiContext().getWiki().getStatsService(getXWikiContext());
1984  0 List<RefererStats> stats = statisticsService.getRefererStatistics("", scope, period, range, this.context);
1985  0 return stats;
1986    }
1987   
 
1988  0 toggle public boolean checkAccess(String right)
1989    {
1990  0 try {
1991  0 return getXWikiContext().getWiki().checkAccess(right, this.doc, getXWikiContext());
1992    } catch (XWikiException e) {
1993  0 return false;
1994    }
1995    }
1996   
 
1997  369 toggle public boolean hasAccessLevel(String level)
1998    {
1999  369 try {
2000  369 return getXWikiContext().getWiki().getRightService().hasAccessLevel(level, getXWikiContext().getUser(),
2001    this.getPrefixedFullName(), getXWikiContext());
2002    } catch (Exception e) {
2003  0 return false;
2004    }
2005    }
2006   
 
2007  88 toggle @Override
2008    public boolean hasAccessLevel(String level, String user)
2009    {
2010  88 try {
2011  88 return getXWikiContext().getWiki().getRightService().hasAccessLevel(level, user, this.getPrefixedFullName(),
2012    getXWikiContext());
2013    } catch (Exception e) {
2014  0 return false;
2015    }
2016    }
2017   
 
2018  615 toggle public boolean getLocked()
2019    {
2020  615 try {
2021  615 XWikiLock lock = this.doc.getLock(getXWikiContext());
2022  615 if (lock != null && !getXWikiContext().getUser().equals(lock.getUserName())) {
2023  1 return true;
2024    } else {
2025  614 return false;
2026    }
2027    } catch (Exception e) {
2028  0 return false;
2029    }
2030    }
2031   
 
2032  1 toggle public String getLockingUser()
2033    {
2034  1 try {
2035  1 XWikiLock lock = this.doc.getLock(getXWikiContext());
2036  1 if (lock != null && !getXWikiContext().getUser().equals(lock.getUserName())) {
2037  1 return lock.getUserName();
2038    } else {
2039  0 return "";
2040    }
2041    } catch (XWikiException e) {
2042  0 return "";
2043    }
2044    }
2045   
 
2046  0 toggle public Date getLockingDate()
2047    {
2048  0 try {
2049  0 XWikiLock lock = this.doc.getLock(getXWikiContext());
2050  0 if (lock != null && !getXWikiContext().getUser().equals(lock.getUserName())) {
2051  0 return lock.getDate();
2052    } else {
2053  0 return null;
2054    }
2055    } catch (XWikiException e) {
2056  0 return null;
2057    }
2058    }
2059   
 
2060  6 toggle public java.lang.Object get(String classOrFieldName)
2061    {
2062  6 if (this.currentObj != null) {
2063  6 return this.doc.display(classOrFieldName, this.currentObj.getBaseObject(), getXWikiContext());
2064    }
2065  0 BaseObject object = this.doc.getFirstObject(classOrFieldName, getXWikiContext());
2066  0 if (object != null) {
2067  0 return this.doc.display(classOrFieldName, object, getXWikiContext());
2068    }
2069  0 return this.getDoc().getObject(classOrFieldName);
2070    }
2071   
 
2072  976 toggle public java.lang.Object getValue(String fieldName)
2073    {
2074  976 Object object;
2075  976 if (this.currentObj == null) {
2076  625 object = new Object(this.getDoc().getFirstObject(fieldName, getXWikiContext()), getXWikiContext());
2077    } else {
2078  351 object = this.currentObj;
2079    }
2080  976 return getValue(fieldName, object);
2081    }
2082   
 
2083  4344 toggle public java.lang.Object getValue(String fieldName, Object object)
2084    {
2085  4346 if (object != null) {
2086  4344 return object.getValue(fieldName);
2087    }
2088   
2089  0 return null;
2090    }
2091   
 
2092  0 toggle public String getTextArea()
2093    {
2094  0 return com.xpn.xwiki.XWiki.getTextArea(this.doc.getContent(), getXWikiContext());
2095    }
2096   
2097    /**
2098    * Returns data needed for a generation of Table of Content for this document.
2099    *
2100    * @param init an intial level where the TOC generation should start at
2101    * @param max maximum level TOC is generated for
2102    * @param numbered if should generate numbering for headings
2103    * @return a map where an heading (title) ID is the key and value is another map with two keys: text, level and
2104    * numbering
2105    */
 
2106  0 toggle public Map<String, Map<String, java.lang.Object>> getTOC(int init, int max, boolean numbered)
2107    {
2108  0 getXWikiContext().put("tocNumbered", new Boolean(numbered));
2109  0 return TOCGenerator.generateTOC(getContent(), init, max, numbered, getXWikiContext());
2110    }
2111   
 
2112  0 toggle public String getTags()
2113    {
2114  0 return this.doc.getTags(getXWikiContext());
2115    }
2116   
 
2117  343 toggle public List<String> getTagList()
2118    {
2119  343 return this.getDoc().getTagsList(getXWikiContext());
2120    }
2121   
 
2122  0 toggle public List<String> getTagsPossibleValues()
2123    {
2124  0 return this.doc.getTagsPossibleValues(getXWikiContext());
2125    }
2126   
 
2127  0 toggle public void insertText(String text, String marker) throws XWikiException
2128    {
2129  0 if (hasAccessLevel("edit")) {
2130  0 getDoc().insertText(text, marker, getXWikiContext());
2131   
2132  0 updateAuthor();
2133  0 updateContentAuthor();
2134    }
2135    }
2136   
 
2137  0 toggle @Override
2138    public boolean equals(java.lang.Object arg0)
2139    {
2140  0 if (!(arg0 instanceof Document)) {
2141  0 return false;
2142    }
2143  0 Document d = (Document) arg0;
2144  0 return d.getXWikiContext().equals(getXWikiContext()) && this.doc.equals(d.doc);
2145    }
2146   
2147    /**
2148    * Check if the passed one is the one wrapped by this {@link Document}.
2149    *
2150    * @param document the document to compare
2151    * @return true if passed document is the wrapped one
2152    * @since 8.3M1
2153    */
 
2154  366818 toggle public boolean same(XWikiDocument document)
2155    {
2156  366814 return document == this.doc || document == this.initialDoc;
2157    }
2158   
 
2159  13 toggle public List<String> getBacklinks() throws XWikiException
2160    {
2161  13 return this.doc.getBackLinkedPages(getXWikiContext());
2162    }
2163   
 
2164  0 toggle public List<XWikiLink> getLinks() throws XWikiException
2165    {
2166  0 return new ArrayList<XWikiLink>(this.doc.getUniqueWikiLinkedPages(getXWikiContext()));
2167    }
2168   
2169    /**
2170    * Get the top sections contained in the document.
2171    * <p>
2172    * The section are filtered by xwiki.section.depth property on the maximum depth of the sections to return. This
2173    * method is usually used to get "editable" sections.
2174    *
2175    * @return the sections in the current document
2176    */
 
2177  0 toggle public List<DocumentSection> getSections() throws XWikiException
2178    {
2179  0 return this.doc.getSections();
2180    }
2181   
2182    /**
2183    * Get document children. Children are documents with the current document as parent.
2184    *
2185    * @return The list of children for the current document.
2186    * @since 1.8 Milestone 2
2187    */
 
2188  553 toggle public List<String> getChildren() throws XWikiException
2189    {
2190  553 return this.doc.getChildren(getXWikiContext());
2191    }
2192   
2193    /**
2194    * Get document children. Children are documents with the current document as parent. Where a document has a large
2195    * number of children, one may desire to return a certain number of children (nb) and skip some number (start) of
2196    * the first results.
2197    *
2198    * @param nb The number of results to return.
2199    * @param start The number of results to skip before we begin returning results.
2200    * @return The list of children for the current document.
2201    */
 
2202  0 toggle public List<String> getChildren(int nb, int start) throws XWikiException
2203    {
2204  0 return this.doc.getChildren(nb, start, getXWikiContext());
2205    }
2206   
2207    /**
2208    * @return "inline" if the document should be edited in inline mode by default or "edit" otherwise.
2209    * @throws XWikiException if an error happens when computing the edit mode
2210    */
 
2211  799 toggle public String getDefaultEditMode() throws XWikiException
2212    {
2213  799 return this.doc.getDefaultEditMode(getXWikiContext());
2214    }
2215   
 
2216  0 toggle public String getDefaultEditURL() throws XWikiException
2217    {
2218  0 return this.doc.getDefaultEditURL(getXWikiContext());
2219    }
2220   
 
2221  0 toggle public String getEditURL(String action, String mode) throws XWikiException
2222    {
2223  0 return this.doc.getEditURL(action, mode, getXWikiContext());
2224    }
2225   
 
2226  0 toggle public String getEditURL(String action, String mode, String locale)
2227    {
2228  0 return this.doc.getEditURL(action, mode, locale, getXWikiContext());
2229    }
2230   
 
2231  0 toggle public boolean isCurrentUserCreator()
2232    {
2233  0 return this.doc.isCurrentUserCreator(getXWikiContext());
2234    }
2235   
 
2236  0 toggle public boolean isCurrentUserPage()
2237    {
2238  0 return this.doc.isCurrentUserPage(getXWikiContext());
2239    }
2240   
 
2241  0 toggle public boolean isCurrentLocalUserPage()
2242    {
2243  0 return this.doc.isCurrentLocalUserPage(getXWikiContext());
2244    }
2245   
 
2246  0 toggle public boolean isCreator(String username)
2247    {
2248  0 return this.doc.isCreator(username);
2249    }
2250   
 
2251  9 toggle public void set(String fieldname, java.lang.Object value)
2252    {
2253  9 Object obj;
2254  9 if (this.currentObj != null) {
2255  6 obj = this.currentObj;
2256    } else {
2257  3 obj = getFirstObject(fieldname);
2258    }
2259  9 set(fieldname, value, obj);
2260    }
2261   
 
2262  11 toggle public void set(String fieldname, java.lang.Object value, Object obj)
2263    {
2264  11 if (obj == null) {
2265  0 return;
2266    }
2267  11 obj.set(fieldname, value);
2268    }
2269   
 
2270  99 toggle public void setTitle(String title)
2271    {
2272  99 getDoc().setTitle(title);
2273   
2274  99 updateAuthor();
2275  99 updateContentAuthor();
2276    }
2277   
 
2278  0 toggle public void setCustomClass(String customClass)
2279    {
2280  0 getDoc().setCustomClass(customClass);
2281   
2282  0 updateAuthor();
2283    }
2284   
 
2285  34 toggle public void setParent(String parent)
2286    {
2287  34 getDoc().setParent(parent);
2288   
2289  34 updateAuthor();
2290    }
2291   
 
2292  134 toggle private void updateContentAuthor()
2293    {
2294    // Temporary set as content author of the document the current script author (until the document is saved)
2295  134 XWikiContext xcontext = getXWikiContext();
2296  134 getDoc().setContentAuthorReference(xcontext.getAuthorReference());
2297    }
2298   
 
2299  248 toggle private void updateAuthor()
2300    {
2301    // Temporary set as author of the document the current script author (until the document is saved)
2302  248 XWikiContext xcontext = getXWikiContext();
2303  248 getDoc().setAuthorReference(xcontext.getAuthorReference());
2304    }
2305   
 
2306  32 toggle public void setContent(String content)
2307    {
2308  32 getDoc().setContent(content);
2309   
2310  32 updateAuthor();
2311  32 updateContentAuthor();
2312    }
2313   
2314    /**
2315    * @param content the content as XDOM
2316    * @throws XWikiException when failing to convert the XDOM to String content
2317    * @since 7.0RC1
2318    */
 
2319  0 toggle public void setContent(XDOM content) throws XWikiException
2320    {
2321  0 getDoc().setContent(content);
2322   
2323  0 updateAuthor();
2324  0 updateContentAuthor();
2325    }
2326   
2327    /**
2328    * @param syntax the Syntax representing the syntax used for the current document's content.
2329    * @since 2.3M1
2330    */
 
2331  0 toggle public void setSyntax(Syntax syntax)
2332    {
2333  0 getDoc().setSyntax(syntax);
2334   
2335  0 updateAuthor();
2336  0 updateContentAuthor();
2337    }
2338   
2339    /**
2340    * @param syntaxId the Syntax id representing the syntax used for the current document. For example "xwiki/1.0"
2341    * represents the first version XWiki syntax while "xwiki/2.0" represents version 2.0 of the XWiki
2342    * Syntax.
2343    */
 
2344  3 toggle public void setSyntaxId(String syntaxId)
2345    {
2346  3 getDoc().setSyntaxId(syntaxId);
2347   
2348  3 updateAuthor();
2349  3 updateContentAuthor();
2350    }
2351   
 
2352  0 toggle public void setDefaultTemplate(String dtemplate)
2353    {
2354  0 getDoc().setDefaultTemplate(dtemplate);
2355   
2356  0 updateAuthor();
2357    }
2358   
 
2359  0 toggle public void setComment(String comment)
2360    {
2361  0 getDoc().setComment(comment);
2362    }
2363   
 
2364  0 toggle public void setMinorEdit(boolean isMinor)
2365    {
2366  0 getDoc().setMinorEdit(isMinor);
2367    }
2368   
 
2369  58 toggle public void save() throws XWikiException
2370    {
2371  58 save("", false);
2372    }
2373   
 
2374  189 toggle public void save(String comment) throws XWikiException
2375    {
2376  189 save(comment, false);
2377    }
2378   
 
2379  254 toggle public void save(String comment, boolean minorEdit) throws XWikiException
2380    {
2381  254 if (hasAccessLevel("edit")) {
2382  253 saveDocument(comment, minorEdit);
2383    } else {
2384  1 java.lang.Object[] args = { getDefaultEntityReferenceSerializer().serialize(getDocumentReference()) };
2385  1 throw new XWikiException(XWikiException.MODULE_XWIKI_ACCESS, XWikiException.ERROR_XWIKI_ACCESS_DENIED,
2386    "Access denied in edit mode on document {0}", null, args);
2387    }
2388    }
2389   
 
2390  0 toggle public void saveWithProgrammingRights() throws XWikiException
2391    {
2392  0 saveWithProgrammingRights("", false);
2393    }
2394   
 
2395  0 toggle public void saveWithProgrammingRights(String comment) throws XWikiException
2396    {
2397  0 saveWithProgrammingRights(comment, false);
2398    }
2399   
 
2400  0 toggle public void saveWithProgrammingRights(String comment, boolean minorEdit) throws XWikiException
2401    {
2402  0 if (hasProgrammingRights()) {
2403    // The rights check above is generic, but the current method is a save operation, thus it should not be
2404    // performed if the document's wiki is in read only mode.
2405  0 XWikiContext context = getXWikiContext();
2406  0 String currentWikiId = context.getWikiId();
2407  0 try {
2408    // Make sure we check the current document's wiki and not the current context's wiki.
2409  0 context.setWikiId(getWiki());
2410   
2411  0 if (!context.getWiki().isReadOnly()) {
2412  0 saveDocument(comment, minorEdit);
2413    } else {
2414  0 java.lang.Object[] args =
2415    { getDefaultEntityReferenceSerializer().serialize(getDocumentReference()), getWiki() };
2416  0 throw new XWikiException(XWikiException.MODULE_XWIKI_ACCESS,
2417    XWikiException.ERROR_XWIKI_ACCESS_DENIED,
2418    "Access denied in edit mode on document [{0}]. The wiki [{1}] is in read only mode.", null,
2419    args);
2420    }
2421    } finally {
2422    // Restore the context wiki.
2423  0 context.setWikiId(currentWikiId);
2424    }
2425    } else {
2426  0 java.lang.Object[] args = { this.getFullName() };
2427  0 throw new XWikiException(XWikiException.MODULE_XWIKI_ACCESS, XWikiException.ERROR_XWIKI_ACCESS_DENIED,
2428    "Access denied with no programming rights document {0}", null, args);
2429    }
2430    }
2431   
2432    /**
2433    * Save the document if the {@link #getContentAuthor content author} of the script calling this method has
2434    * permission to do so. The author of this document is also set to the said content author.
2435    *
2436    * @throws XWikiException if script author is not allowed to save the document or if save operation fails.
2437    * @since 2.3M2
2438    */
 
2439  2 toggle public void saveAsAuthor() throws XWikiException
2440    {
2441  2 saveAsAuthor("", false);
2442    }
2443   
2444    /**
2445    * Save the document if the {@link #getContentAuthor content author} of the script calling this method has
2446    * permission to do so. The author of this document is also set to the said content author.
2447    *
2448    * @param comment The comment to display in document history (what did you change in the document)
2449    * @throws XWikiException if script author is not allowed to save the document or if save operation fails.
2450    * @since 2.3M2
2451    */
 
2452  0 toggle public void saveAsAuthor(String comment) throws XWikiException
2453    {
2454  0 saveAsAuthor(comment, false);
2455    }
2456   
2457    /**
2458    * Save the document if the {@link #getContentAuthor content author} of the script calling this method has
2459    * permission to do so. The author of this document is also set to the said content author.
2460    *
2461    * @param comment The comment to display in document history (what did you change in the document)
2462    * @param minorEdit Set true to advance the document version number by 0.1 or false to advance version to the next
2463    * integer + 0.1 eg: 25.1
2464    * @throws XWikiException if script author is not allowed to save the document or if save operation fails.
2465    * @since 2.3M2
2466    */
 
2467  5 toggle public void saveAsAuthor(String comment, boolean minorEdit) throws XWikiException
2468    {
2469  5 String author = this.getEffectiveScriptAuthorName();
2470  5 if (hasAccessLevel("edit", author)) {
2471  4 String viewer = getXWikiContext().getUser();
2472  4 try {
2473  4 getXWikiContext().setUser(author);
2474  4 saveDocument(comment, minorEdit);
2475    } finally {
2476  4 getXWikiContext().setUser(viewer);
2477    }
2478    } else {
2479  1 java.lang.Object[] args = { author, getXWikiContext().getDoc(), this.getFullName() };
2480  1 throw new XWikiException(XWikiException.MODULE_XWIKI_ACCESS, XWikiException.ERROR_XWIKI_ACCESS_DENIED,
2481    "Access denied; user {0}, acting through script in document {1} cannot save document {2}", null, args);
2482    }
2483    }
2484   
 
2485  257 toggle protected void saveDocument(String comment, boolean minorEdit) throws XWikiException
2486    {
2487  257 XWikiDocument doc = getDoc();
2488   
2489  257 DocumentReference currentUserReference = this.context.getUserReference();
2490   
2491  257 doc.setAuthorReference(currentUserReference);
2492   
2493  257 if (doc.isNew()) {
2494  121 doc.setCreatorReference(currentUserReference);
2495    }
2496  257 getXWikiContext().getWiki().saveDocument(doc, comment, minorEdit, getXWikiContext());
2497  257 this.initialDoc = this.doc;
2498    }
2499   
 
2500  0 toggle public com.xpn.xwiki.api.Object addObjectFromRequest() throws XWikiException
2501    {
2502    // Call to getDoc() ensures that we are working on a clone()
2503  0 com.xpn.xwiki.api.Object obj =
2504    new com.xpn.xwiki.api.Object(getDoc().addXObjectFromRequest(getXWikiContext()), getXWikiContext());
2505   
2506  0 updateAuthor();
2507   
2508  0 return obj;
2509    }
2510   
 
2511  0 toggle public com.xpn.xwiki.api.Object addObjectFromRequest(String className) throws XWikiException
2512    {
2513  0 com.xpn.xwiki.api.Object obj = new com.xpn.xwiki.api.Object(
2514    getDoc().addObjectFromRequest(className, getXWikiContext()), getXWikiContext());
2515   
2516  0 updateAuthor();
2517   
2518  0 return obj;
2519    }
2520   
 
2521  0 toggle public List<Object> addObjectsFromRequest(String className) throws XWikiException
2522    {
2523  0 return addObjectsFromRequest(className, "");
2524    }
2525   
 
2526  0 toggle public com.xpn.xwiki.api.Object addObjectFromRequest(String className, String prefix) throws XWikiException
2527    {
2528  0 com.xpn.xwiki.api.Object obj = new com.xpn.xwiki.api.Object(
2529    getDoc().addObjectFromRequest(className, prefix, getXWikiContext()), getXWikiContext());
2530   
2531  0 updateAuthor();
2532   
2533  0 return obj;
2534    }
2535   
 
2536  0 toggle public List<Object> addObjectsFromRequest(String className, String prefix) throws XWikiException
2537    {
2538  0 List<BaseObject> objs = getDoc().addObjectsFromRequest(className, prefix, getXWikiContext());
2539  0 List<Object> wrapped = new ArrayList<Object>();
2540  0 for (BaseObject object : objs) {
2541  0 wrapped.add(new com.xpn.xwiki.api.Object(object, getXWikiContext()));
2542    }
2543   
2544  0 updateAuthor();
2545   
2546  0 return wrapped;
2547    }
2548   
 
2549  0 toggle public com.xpn.xwiki.api.Object updateObjectFromRequest(String className) throws XWikiException
2550    {
2551  0 com.xpn.xwiki.api.Object obj = new com.xpn.xwiki.api.Object(
2552    getDoc().updateObjectFromRequest(className, getXWikiContext()), getXWikiContext());
2553   
2554  0 updateAuthor();
2555   
2556  0 return obj;
2557    }
2558   
 
2559  0 toggle public List<Object> updateObjectsFromRequest(String className) throws XWikiException
2560    {
2561  0 return updateObjectsFromRequest(className, "");
2562    }
2563   
 
2564  0 toggle public com.xpn.xwiki.api.Object updateObjectFromRequest(String className, String prefix) throws XWikiException
2565    {
2566  0 com.xpn.xwiki.api.Object obj = new com.xpn.xwiki.api.Object(
2567    getDoc().updateObjectFromRequest(className, prefix, getXWikiContext()), getXWikiContext());
2568   
2569  0 updateAuthor();
2570   
2571  0 return obj;
2572    }
2573   
 
2574  0 toggle public List<Object> updateObjectsFromRequest(String className, String prefix) throws XWikiException
2575    {
2576  0 List<BaseObject> objs = getDoc().updateObjectsFromRequest(className, prefix, getXWikiContext());
2577  0 List<Object> wrapped = new ArrayList<Object>();
2578  0 for (BaseObject object : objs) {
2579  0 wrapped.add(new com.xpn.xwiki.api.Object(object, getXWikiContext()));
2580    }
2581   
2582  0 updateAuthor();
2583   
2584  0 return wrapped;
2585    }
2586   
 
2587  0 toggle public boolean isAdvancedContent()
2588    {
2589  0 return this.doc.isAdvancedContent();
2590    }
2591   
 
2592  0 toggle public boolean isProgrammaticContent()
2593    {
2594  0 return this.doc.isProgrammaticContent();
2595    }
2596   
2597    /**
2598    * Remove an XObject from the document. The changes are not persisted until the document is saved.
2599    *
2600    * @param object the object to remove
2601    * @return {@code true} if the object was successfully removed, {@code false} if the object was not found in the
2602    * current document.
2603    */
 
2604  5 toggle public boolean removeObject(Object object)
2605    {
2606  5 return getDoc().removeObject(object.getBaseObject());
2607    }
2608   
2609    /**
2610    * Remove all the objects of a given type (XClass) from the document. The object counter is left unchanged, so that
2611    * future objects will have new (different) numbers. However, on some storage engines the counter will be reset if
2612    * the document is removed from the cache and reloaded from the persistent storage.
2613    *
2614    * @param className The class name of the objects to be removed.
2615    * @return {@code true} if the objects were successfully removed, {@code false} if no object from the target class
2616    * was in the current document.
2617    */
 
2618  1 toggle public boolean removeObjects(String className)
2619    {
2620  1 return getDoc().removeObjects(className);
2621    }
2622   
2623    /**
2624    * Remove document from the wiki. Reinit <code>cloned</code>.
2625    *
2626    * @throws XWikiException
2627    */
 
2628  49 toggle protected void deleteDocument() throws XWikiException
2629    {
2630  49 getXWikiContext().getWiki().deleteDocument(this.doc, getXWikiContext());
2631  49 this.initialDoc = this.doc;
2632    }
2633   
 
2634  50 toggle public void delete() throws XWikiException
2635    {
2636  50 if (hasAccessLevel("delete")) {
2637  49 deleteDocument();
2638    } else {
2639  1 java.lang.Object[] args = { this.getFullName() };
2640  1 throw new XWikiException(XWikiException.MODULE_XWIKI_ACCESS, XWikiException.ERROR_XWIKI_ACCESS_DENIED,
2641    "Access denied in edit mode on document {0}", null, args);
2642    }
2643    }
2644   
2645    /**
2646    * Delete the document if the {@link #getContentAuthor content author} of the script calling this method has
2647    * permission to do so. The deleter is also set to the said content author.
2648    *
2649    * @throws XWikiException if script author is not allowed to delete the document or if save operation fails.
2650    * @since 2.3M2
2651    */
 
2652  0 toggle public void deleteAsAuthor() throws XWikiException
2653    {
2654  0 String author = this.getEffectiveScriptAuthorName();
2655  0 if (hasAccessLevel("delete", author)) {
2656  0 String viewer = getXWikiContext().getUser();
2657  0 try {
2658  0 getXWikiContext().setUser(author);
2659  0 deleteDocument();
2660    } finally {
2661  0 getXWikiContext().setUser(viewer);
2662    }
2663    } else {
2664  0 java.lang.Object[] args = { author, getXWikiContext().getDoc(), this.getFullName() };
2665  0 throw new XWikiException(XWikiException.MODULE_XWIKI_ACCESS, XWikiException.ERROR_XWIKI_ACCESS_DENIED,
2666    "Access denied; user {0}, acting through script in document {1} cannot delete document {2}", null,
2667    args);
2668    }
2669    }
2670   
 
2671  0 toggle public void deleteWithProgrammingRights() throws XWikiException
2672    {
2673  0 if (hasProgrammingRights()) {
2674  0 deleteDocument();
2675    } else {
2676  0 java.lang.Object[] args = { this.getFullName() };
2677  0 throw new XWikiException(XWikiException.MODULE_XWIKI_ACCESS, XWikiException.ERROR_XWIKI_ACCESS_DENIED,
2678    "Access denied with no programming rights document {0}", null, args);
2679    }
2680    }
2681   
 
2682  0 toggle public String getVersionHashCode()
2683    {
2684  0 return this.doc.getVersionHashCode(getXWikiContext());
2685    }
2686   
 
2687  0 toggle public int addAttachments() throws XWikiException
2688    {
2689  0 return addAttachments(null);
2690    }
2691   
 
2692  0 toggle public int addAttachments(String fieldName) throws XWikiException
2693    {
2694  0 if (!hasAccessLevel("edit")) {
2695  0 java.lang.Object[] args = { this.getFullName() };
2696  0 throw new XWikiException(XWikiException.MODULE_XWIKI_ACCESS, XWikiException.ERROR_XWIKI_ACCESS_DENIED,
2697    "Access denied in edit mode on document {0}", null, args);
2698    }
2699  0 XWiki xwiki = getXWikiContext().getWiki();
2700  0 FileUploadPlugin fileupload = (FileUploadPlugin) xwiki.getPlugin("fileupload", getXWikiContext());
2701  0 List<FileItem> fileuploadlist = fileupload.getFileItems(getXWikiContext());
2702  0 List<XWikiAttachment> attachments = new ArrayList<XWikiAttachment>();
2703    // adding attachment list to context so we find the names
2704  0 this.context.put("addedAttachments", attachments);
2705  0 int nb = 0;
2706   
2707  0 if (fileuploadlist == null) {
2708  0 return 0;
2709    }
2710   
2711  0 for (FileItem item : fileuploadlist) {
2712  0 String name = item.getFieldName();
2713  0 if (fieldName != null && !fieldName.equals(name)) {
2714  0 continue;
2715    }
2716  0 if (item.isFormField()) {
2717  0 continue;
2718    }
2719  0 byte[] data = fileupload.getFileItemData(name, getXWikiContext());
2720  0 String filename;
2721  0 String fname = fileupload.getFileName(name, getXWikiContext());
2722  0 int i = fname.lastIndexOf("\\");
2723  0 if (i == -1) {
2724  0 i = fname.lastIndexOf("/");
2725    }
2726  0 filename = fname.substring(i + 1);
2727  0 filename = filename.replaceAll("\\+", " ");
2728   
2729  0 if ((data != null) && (data.length > 0)) {
2730  0 XWikiAttachment attachment = this.getDoc().addAttachment(filename, data, getXWikiContext());
2731  0 getDoc().saveAttachmentContent(attachment, getXWikiContext());
2732    // commenting because this was already done by addAttachment
2733    // getDoc().getAttachmentList().add(attachment);
2734  0 attachments.add(attachment);
2735  0 nb++;
2736    }
2737    }
2738   
2739  0 if (nb > 0) {
2740  0 getXWikiContext().getWiki().saveDocument(getDoc(), getXWikiContext());
2741  0 this.initialDoc = this.doc;
2742    }
2743   
2744  0 return nb;
2745    }
2746   
 
2747  0 toggle public Attachment addAttachment(String fileName, InputStream iStream)
2748    {
2749  0 try {
2750  0 return new Attachment(this, this.getDoc().addAttachment(fileName, iStream, getXWikiContext()),
2751    getXWikiContext());
2752    } catch (XWikiException e) {
2753    // TODO Log the error and let the user know about it
2754    } catch (IOException e) {
2755    // TODO Log the error and let the user know about it
2756    } finally {
2757  0 updateAuthor();
2758    }
2759   
2760  0 return null;
2761    }
2762   
 
2763  0 toggle public Attachment addAttachment(String fileName, byte[] data)
2764    {
2765  0 try {
2766  0 return new Attachment(this, this.getDoc().addAttachment(fileName, data, getXWikiContext()),
2767    getXWikiContext());
2768    } catch (XWikiException e) {
2769    // TODO Log the error and let the user know about it
2770    } finally {
2771  0 updateAuthor();
2772    }
2773   
2774  0 return null;
2775    }
2776   
 
2777  0 toggle public boolean validate() throws XWikiException
2778    {
2779  0 return this.doc.validate(getXWikiContext());
2780    }
2781   
 
2782  0 toggle public boolean validate(String[] classNames) throws XWikiException
2783    {
2784  0 return this.doc.validate(classNames, getXWikiContext());
2785    }
2786   
2787    /**
2788    * Retrieves the validation script associated with this document, a Velocity script that is executed when validating
2789    * the document data.
2790    *
2791    * @return A <code>String</code> representation of the validation script, or an empty string if there is no such
2792    * script.
2793    */
 
2794  0 toggle public String getValidationScript()
2795    {
2796  0 return getDoc().getValidationScript();
2797    }
2798   
2799    /**
2800    * Sets a new validation script for this document, a Velocity script that is executed when validating the document
2801    * data.
2802    *
2803    * @param validationScript The new validation script, which can be an empty string or <code>null</code> if the
2804    * script should be removed.
2805    */
 
2806  0 toggle public void setValidationScript(String validationScript)
2807    {
2808  0 getDoc().setValidationScript(validationScript);
2809   
2810  0 updateAuthor();
2811    }
2812   
2813    /**
2814    * Rename the current document and all the backlinks leading to it. Will also change parent field in all documents
2815    * which list the document we are renaming as their parent. See
2816    * {@link #rename(String, java.util.List, java.util.List)} for more details.
2817    *
2818    * @param newDocumentName the new document name. If the space is not specified then defaults to the current space.
2819    * @throws XWikiException in case of an error
2820    */
 
2821  2 toggle public void rename(String newDocumentName) throws XWikiException
2822    {
2823  2 rename(getCurrentMixedDocumentReferenceResolver().resolve(newDocumentName));
2824    }
2825   
2826    /**
2827    * Rename the current document and all the backlinks leading to it. Will also change parent field in all documents
2828    * which list the document we are renaming as their parent. See
2829    * {@link #rename(String, java.util.List, java.util.List)} for more details.
2830    *
2831    * @param newReference the reference to the new document
2832    * @throws XWikiException in case of an error
2833    * @since 2.3M2
2834    */
 
2835  2 toggle public void rename(DocumentReference newReference) throws XWikiException
2836    {
2837  2 if (hasAccessLevel("delete") && this.context.getWiki().checkAccess("edit",
2838    this.context.getWiki().getDocument(newReference, this.context), this.context)) {
2839  2 this.getDoc().rename(newReference, getXWikiContext());
2840    }
2841    }
2842   
2843    /**
2844    * Rename the current document and all the links pointing to it in the list of passed backlink documents. The
2845    * renaming algorithm takes into account the fact that there are several ways to write a link to a given page and
2846    * all those forms need to be renamed. For example the following links all point to the same page:
2847    * <ul>
2848    * <li>[Page]</li>
2849    * <li>[Page?param=1]</li>
2850    * <li>[currentwiki:Page]</li>
2851    * <li>[currentwiki:CurrentSpace.Page]</li>
2852    * </ul>
2853    * <p>
2854    * Note: links without a space are renamed with the space added and all documents which have the document being
2855    * renamed as parent have their parent field set to "currentwiki:CurrentSpace.Page".
2856    * </p>
2857    *
2858    * @param newDocumentName the new document name. If the space is not specified then defaults to the current space.
2859    * @param backlinkDocumentNames the list of documents to parse and for which links will be modified to point to the
2860    * new renamed document.
2861    * @throws XWikiException in case of an error
2862    */
 
2863  0 toggle public void rename(String newDocumentName, List<String> backlinkDocumentNames) throws XWikiException
2864    {
2865  0 if (hasAccessLevel("delete") && this.context.getWiki().checkAccess("edit",
2866    this.context.getWiki().getDocument(newDocumentName, this.context), this.context)) {
2867  0 this.getDoc().rename(newDocumentName, backlinkDocumentNames, getXWikiContext());
2868    }
2869    }
2870   
2871    /**
2872    * Same as {@link #rename(String, List)} but the list of documents having the current document as their parent is
2873    * passed in parameter.
2874    *
2875    * @param newDocumentName the new document name. If the space is not specified then defaults to the current space.
2876    * @param backlinkDocumentNames the list of documents to parse and for which links will be modified to point to the
2877    * new renamed document.
2878    * @param childDocumentNames the list of documents whose parent field will be set to the new document name.
2879    * @throws XWikiException in case of an error
2880    */
 
2881  0 toggle public void rename(String newDocumentName, List<String> backlinkDocumentNames, List<String> childDocumentNames)
2882    throws XWikiException
2883    {
2884  0 List<DocumentReference> backlinkDocumentReferences = new ArrayList<DocumentReference>();
2885  0 for (String backlinkDocumentName : backlinkDocumentNames) {
2886  0 backlinkDocumentReferences.add(getCurrentMixedDocumentReferenceResolver().resolve(backlinkDocumentName));
2887    }
2888   
2889  0 List<DocumentReference> childDocumentReferences = new ArrayList<DocumentReference>();
2890  0 for (String childDocumentName : childDocumentNames) {
2891  0 childDocumentReferences.add(getCurrentMixedDocumentReferenceResolver().resolve(childDocumentName));
2892    }
2893   
2894  0 rename(getCurrentMixedDocumentReferenceResolver().resolve(newDocumentName), backlinkDocumentReferences,
2895    childDocumentReferences);
2896    }
2897   
2898    /**
2899    * Same as {@link #rename(String, List)} but the list of documents having the current document as their parent is
2900    * passed in parameter.
2901    *
2902    * @param newReference the reference to the new document
2903    * @param backlinkDocumentNames the list of reference to documents to parse and for which links will be modified to
2904    * point to the new renamed document
2905    * @param childDocumentNames the list of references to documents whose parent field will be set to the new document
2906    * reference
2907    * @throws XWikiException in case of an error
2908    * @since 2.3M2
2909    */
 
2910  0 toggle public void rename(DocumentReference newReference, List<DocumentReference> backlinkDocumentNames,
2911    List<DocumentReference> childDocumentNames) throws XWikiException
2912    {
2913  0 if (hasAccessLevel("delete") && this.context.getWiki().checkAccess("edit",
2914    this.context.getWiki().getDocument(newReference, this.context), this.context)) {
2915   
2916    // Every page given in childDocumentNames has it's parent changed whether it needs it or not.
2917    // Let's make sure the user has edit permission on any page given which is not actually a child.
2918    // Otherwise it would be embarrassing if a user called:
2919    // $doc.rename("mynewpage",$doc.getBacklinks(),$xwiki.searchDocuments("true"))
2920  0 int counter = childDocumentNames.size();
2921  0 List<String> actuallyChildren = getChildren();
2922  0 while (counter > 0) {
2923  0 counter--;
2924  0 if (!actuallyChildren.contains(childDocumentNames.get(counter))
2925    && !this.context.getWiki().checkAccess("edit",
2926    this.context.getWiki().getDocument(childDocumentNames.get(counter), this.context),
2927    this.context)) {
2928  0 return;
2929    }
2930    }
2931   
2932  0 this.getDoc().rename(newReference, backlinkDocumentNames, childDocumentNames, getXWikiContext());
2933    }
2934    }
2935   
2936    /**
2937    * Allow to easily access any revision of a document
2938    *
2939    * @param revision the version to access
2940    * @return the document coresponding to the requested revision or {@code null} if the revision does not exist.
2941    */
 
2942  21 toggle public Document getDocumentRevision(String revision)
2943    {
2944  21 try {
2945  21 XWikiDocument documentRevision = this.context.getWiki().getDocument(this.doc, revision, this.context);
2946  21 Document result = new Document(documentRevision, this.context);
2947   
2948  21 return result;
2949    } catch (Exception e) {
2950  0 return null;
2951    }
2952    }
2953   
2954    /**
2955    * Allow to easily access the previous revision of a document
2956    *
2957    * @return Document
2958    * @throws XWikiException
2959    */
 
2960  0 toggle public Document getPreviousDocument() throws XWikiException
2961    {
2962  0 return getDocumentRevision(getPreviousVersion());
2963    }
2964   
2965    /**
2966    * @return is document most recent. false if and only if there are older versions of this document.
2967    */
 
2968  0 toggle public boolean isMostRecent()
2969    {
2970  0 return this.doc.isMostRecent();
2971    }
2972   
 
2973  20666 toggle @Override
2974    public String toString()
2975    {
2976  20664 return this.doc.toString();
2977    }
2978   
2979    /**
2980    * Convert the current document content from its current syntax to the new syntax passed as parameter.
2981    *
2982    * @param targetSyntaxId the syntax to convert to (eg "xwiki/2.0", "xhtml/1.0", etc)
2983    * @throws XWikiException if an exception occurred during the conversion process
2984    */
 
2985  0 toggle public boolean convertSyntax(String targetSyntaxId) throws XWikiException
2986    {
2987  0 try {
2988  0 getDoc().convertSyntax(targetSyntaxId, this.context);
2989    } catch (Exception ex) {
2990  0 LOGGER.error(
2991    "Failed to convert document [" + getPrefixedFullName() + "] to syntax [" + targetSyntaxId + "]", ex);
2992   
2993  0 return false;
2994    } finally {
2995  0 updateAuthor();
2996  0 updateContentAuthor();
2997    }
2998   
2999  0 return true;
3000    }
3001   
3002    /**
3003    * Indicates whether the document is 'hidden' or not, meaning that it should not be returned in public search
3004    * results or appear in the User Interface in general.
3005    *
3006    * @return <code>true</code> if the document is hidden, <code>false</code> otherwise.
3007    */
 
3008  416 toggle public boolean isHidden()
3009    {
3010  416 return this.doc.isHidden();
3011    }
3012   
3013    /**
3014    * Indicates whether the document should be 'hidden' or not, meaning that it should not be returned in public search
3015    * results or appear in the User Interface in general.
3016    *
3017    * @param hidden <code>true</code> if the document should be 'hidden', <code>false</code> otherwise.
3018    */
 
3019  201 toggle public void setHidden(boolean hidden)
3020    {
3021  201 this.doc.setHidden(hidden);
3022    }
3023   
3024    /**
3025    * Drop permissions for the remainder of the rendering cycle. After this is called:
3026    * <ul>
3027    * <li>1. {@link com.xpn.xwiki.api.Api#hasProgrammingRights()} will always return false.</li>
3028    * <li>2. {@link com.xpn.xwiki.api.XWiki#getDocumentAsAuthor(org.xwiki.model.reference.DocumentReference)},
3029    * {@link com.xpn.xwiki.api.XWiki#getDocumentAsAuthor(String)}, {@link com.xpn.xwiki.api.Document#saveAsAuthor()},
3030    * {@link com.xpn.xwiki.api.Document#saveAsAuthor(String)},
3031    * {@link com.xpn.xwiki.api.Document#saveAsAuthor(String, boolean)}, and
3032    * {@link com.xpn.xwiki.api.Document#deleteAsAuthor()} will perform all of their actions as if the document's
3033    * content author was the guest user (XWiki.XWikiGuest).</li>
3034    * </ul>
3035    * <p>
3036    * This sandboxing will expire at the end of the rendering cycle and can be suspended by beginning a new rendering
3037    * cycle. A rendering cycle can be begin by calling {@link #getRenderedContent(String)}, {@link #display(String)}
3038    * (or variations thereof) or by invoking the include macro or using
3039    * {@link com.xpn.xwiki.api.XWiki#includeTopic(String)}
3040    * <p>
3041    * NOTE: Even if you include the same document, permissions will be regained. What this does is sandbox the
3042    * remainder of the code on the page because although it can temporarily suspend the permissions drop, it cannot get
3043    * itself to be executed with permissions because if it calls itself, it will hit the drop function first.
3044    * <p>
3045    * If you are interested in a more secure sandboxing method where code is guaranteed not to have permissions for the
3046    * remainder of the request, you should consider {@link com.xpn.xwiki.api.Context#dropPermissions()}.
3047    * <p>
3048    *
3049    * @since 3.2M2
3050    */
 
3051  24 toggle public void dropPermissions()
3052    {
3053    // Set the droppedPermissions key to the context so if the context is cloned and
3054    // pushed, it will return false until it is popped again.
3055  24 final ExecutionContext context = Utils.getComponent(Execution.class).getContext();
3056  24 context.setProperty(XWikiConstant.DROPPED_PERMISSIONS, System.identityHashCode(context));
3057    }
3058   
3059    /**
3060    * @return true if this document is a translation of the main document (i.e. returned by
3061    * {@link #getTranslatedDocument(String)}); false if this is actually the main document (i.e. returned by
3062    * {@link com.xpn.xwiki.api.XWiki#getDocument(DocumentReference)}.
3063    * @since 6.2M2
3064    */
 
3065  0 toggle public boolean isTranslation()
3066    {
3067  0 return 1 == this.getDoc().getTranslation();
3068    }
3069   
 
3070  0 toggle private ContextualAuthorizationManager getAuthorizationManager()
3071    {
3072  0 if (this.authorizationManager == null) {
3073  0 this.authorizationManager = Utils.getComponent(ContextualAuthorizationManager.class);
3074    }
3075   
3076  0 return this.authorizationManager;
3077    }
3078    }