/*
* See the NOTICE file distributed with this work for additional
* information regarding copyright ownership.
*
* This is free software; you can redistribute it and/or modify it
* under the terms of the GNU Lesser General Public License as
* published by the Free Software Foundation; either version 2.1 of
* the License, or (at your option) any later version.
*
* This software is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this software; if not, write to the Free
* Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
* 02110-1301 USA, or see the FSF site: http://www.fsf.org.
*/
package com.xpn.xwiki.doc;
import java.util.Date;
import java.util.List;
import java.util.Locale;
import java.util.Map;
import org.dom4j.Document;
import org.suigeneris.jrcs.rcs.Version;
import org.xwiki.context.Execution;
import org.xwiki.model.reference.DocumentReference;
import org.xwiki.model.reference.EntityReference;
import org.xwiki.rendering.block.XDOM;
import org.xwiki.rendering.syntax.Syntax;
import com.xpn.xwiki.XWikiContext;
import com.xpn.xwiki.XWikiException;
import com.xpn.xwiki.objects.BaseObject;
import com.xpn.xwiki.objects.classes.BaseClass;
import com.xpn.xwiki.store.XWikiStoreInterface;
import com.xpn.xwiki.web.Utils;
/**
* Read only lazy loading document.
* <p>
* The following informations are taken into account:
* <ul>
* <li>document reference: the absolute reference of the document</li>
* <li>document language: if provided the proper language version of the document is loaded. If not the default one is
* loaded.</li>
* <li>document version: if provided the proper version of the document is loaded. Also make extra sure to bypass cache
* storage for remote observation use case.</li>
* </ul>
* <p>
* originalDocument remain the property of {@link LazyXWikiDocument} object and is not taken from the lazy loaded
* document since it depends on how this {@link XWikiDocument} object is used (its technical meaning is its state in the
* database before any modification but in the case of observation it's used as the previous version of the document).
* TODO: we should probably think about a separation of theses two notions in something more clear, something for the
* new model.
*
* @version $Id: e215d894834917f828fdedad1e54c9872379f377 $
* @since 2.0M4
*/
public class LazyXWikiDocument extends XWikiDocument
{
/**
* The real document.
*/
private XWikiDocument document;
/**
* @deprecated use {@link #LazyXWikiDocument(DocumentReference)} instead
*/
@Deprecated
public LazyXWikiDocument()
{
}
public LazyXWikiDocument(DocumentReference documentReference)
{
super(documentReference);
}
/**
* Load and return the document in the database.
*
* @return the real document
*/
private XWikiDocument getDocument()
{
if (this.document == null) {
// get context
XWikiContext context =
(XWikiContext) Utils.getComponent(Execution.class).getContext().getProperty("xwikicontext");
XWikiDocument doc = new XWikiDocument(getDocumentReference(), getLocale());
String currentWiki = context.getWikiId();
try {
// Put context in document wiki
context.setWikiId(getDocumentReference().getWikiReference().getName());
if (this.version == null) {
this.document = context.getWiki().getDocument(doc, context);
} else {
// Force bypassing the cache to make extra sure we get the last version of the document. This is
// safer for example when LazyXWikiDocument is used in the context of remote events. This is for
// properly emulate events, XWikiCacheStore is taking care itself of invalidating itself.
doc = context.getWiki().getNotCacheStore().loadXWikiDoc(doc, context);
if (doc.getRCSVersion().equals(this.version)) {
// It's the last version of the document
this.document = doc;
} else {
// It's not the last version of the document, ask versioning store.
try {
this.document =
context.getWiki().getVersioningStore()
.loadXWikiDoc(doc, this.version.toString(), context);
} catch (XWikiException e) {
// If the proper can't be found, return the last version of the document
this.document = doc;
}
}
}
} catch (XWikiException e) {
throw new RuntimeException("Failed to get document [" + this + "]", e);
} finally {
context.setWikiId(currentWiki);
}
}
return this.document;
}
@Override
public Version getRCSVersion()
{
if (this.version == null) {
return getDocument().getRCSVersion();
} else {
return this.version;
}
}
@Override
public String getContent()
{
return getDocument().getContent();
}
@Override
public Map<DocumentReference, List<BaseObject>> getXObjects()
{
return getDocument().getXObjects();
}
@Override
public BaseClass getXClass()
{
return getDocument().getXClass();
}
@Override
public String getXClassXML()
{
return getDocument().getXClassXML();
}
@Override
public DocumentReference getAuthorReference()
{
return getDocument().getAuthorReference();
}
@Override
public DocumentReference getContentAuthorReference()
{
return getDocument().getContentAuthorReference();
}
@Override
public DocumentReference getCreatorReference()
{
return super.getCreatorReference();
}
@Override
public Date getDate()
{
return getDocument().getDate();
}
@Override
public Date getCreationDate()
{
return getDocument().getCreationDate();
}
@Override
public Date getContentUpdateDate()
{
return getDocument().getContentUpdateDate();
}
@Override
public String getMeta()
{
return getDocument().getMeta();
}
@Override
public String getTitle()
{
return getDocument().getTitle();
}
@Override
public String getFormat()
{
return getDocument().getFormat();
}
@Override
public Locale getDefaultLocale()
{
return getDocument().getDefaultLocale();
}
@Override
public int getTranslation()
{
return getDocument().getTranslation();
}
@Override
public String getCustomClass()
{
return getDocument().getCustomClass();
}
@Override
public EntityReference getRelativeParentReference()
{
return getDocument().getRelativeParentReference();
}
@Override
public DocumentReference getParentReference()
{
return getDocument().getParentReference();
}
@Override
public int getElements()
{
return getDocument().getElements();
}
@Override
public String getDefaultTemplate()
{
return getDocument().getDefaultTemplate();
}
@Override
public String getValidationScript()
{
return getDocument().getValidationScript();
}
@Override
public String getComment()
{
return getDocument().getComment();
}
@Override
public Syntax getSyntax()
{
return getDocument().getSyntax();
}
@Override
public Boolean isHidden()
{
return getDocument().isHidden();
}
@Override
public XWikiDocumentArchive getDocumentArchive()
{
return getDocument().getDocumentArchive();
}
@Override
public void loadArchive(XWikiContext context) throws XWikiException
{
getDocument().loadArchive(context);
}
@Override
public XWikiDocumentArchive getDocumentArchive(XWikiContext context) throws XWikiException
{
return getDocument().getDocumentArchive(context);
}
@Override
public XWikiStoreInterface getStore()
{
return getDocument().getStore();
}
@Override
public long getId()
{
return getDocument().getId();
}
@Override
public XWikiStoreInterface getStore(XWikiContext context)
{
return getDocument().getStore(context);
}
@Override
public XDOM getXDOM()
{
return getDocument().getXDOM();
}
@Override
public String getTags(XWikiContext context)
{
return getDocument().getTags(context);
}
@Override
public List<String> getTagsPossibleValues(XWikiContext context)
{
return getDocument().getTagsPossibleValues(context);
}
@Override
public boolean isFromCache()
{
return getDocument().isFromCache();
}
@Override
public boolean isMostRecent()
{
return getDocument().isMostRecent();
}
@Override
public Document toXMLDocument(boolean bWithObjects, boolean bWithRendering, boolean bWithAttachmentContent,
boolean bWithVersions, XWikiContext context) throws XWikiException
{
return getDocument()
.toXMLDocument(bWithObjects, bWithRendering, bWithAttachmentContent, bWithVersions, context);
}
@Override
public Object getWikiNode()
{
return getDocument().getWikiNode();
}
}