/*
* 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.celements.cells.cmd;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.xwiki.context.Execution;
import org.xwiki.model.EntityType;
import org.xwiki.model.reference.DocumentReference;
import org.xwiki.model.reference.EntityReferenceSerializer;
import org.xwiki.model.reference.EntityReferenceValueProvider;
import org.xwiki.model.reference.SpaceReference;
import org.xwiki.model.reference.WikiReference;
import com.celements.cells.ICellsClassConfig;
import com.celements.inheritor.InheritorFactory;
import com.celements.web.plugin.cmd.PageLayoutCommand;
import com.celements.web.service.IWebUtilsService;
import com.xpn.xwiki.XWikiContext;
import com.xpn.xwiki.XWikiException;
import com.xpn.xwiki.doc.XWikiDocument;
import com.xpn.xwiki.objects.BaseObject;
import com.xpn.xwiki.web.Utils;
public class PageDependentDocumentReferenceCommand {
public static final String PDC_DEFAULT_CONTENT_NAME = "PDC-Default_Content";
public static final String PDC_WIKIDEFAULT_SPACE_NAME = "PDC-WikiDefault";
/**
* @deprecated instead use ICellsClassConfig.CELEMENTS_CELL_CLASS_SPACE
*/
@Deprecated
public static final String PAGE_DEP_CELL_CONFIG_CLASS_SPACE = ICellsClassConfig.CELEMENTS_CELL_CLASS_SPACE;
/**
* @deprecated instead use ICellsClassConfig.PAGE_DEP_CELL_CONFIG_CLASS_DOC
*/
@Deprecated
public static final String PAGE_DEP_CELL_CONFIG_CLASS_DOC = ICellsClassConfig.PAGE_DEP_CELL_CONFIG_CLASS_DOC;
public static final String PROPNAME_SPACE_NAME = "space_name";
public static final String PROPNAME_IS_INHERITABLE = "is_inheritable";
private static Logger LOGGER = LoggerFactory.getLogger(
PageDependentDocumentReferenceCommand.class);
PageLayoutCommand pageLayoutCmd;
private SpaceReference currentLayoutRef;
IWebUtilsService inject_WebUtilsService;
/**
* @deprecated since 2.29.0 instead use getDocumentReference(DocumentReference,
* DocumentReference)
*/
@Deprecated
public DocumentReference getDocumentReference(XWikiDocument document,
DocumentReference cellDocRef, XWikiContext context) {
return getDocumentReference(document.getDocumentReference(), cellDocRef);
}
public DocumentReference getDocumentReference(DocumentReference docRef,
DocumentReference cellDocRef) {
LOGGER.debug("getDocumentReference: document [" + docRef + "] cellDocRef [" + cellDocRef
+ "] context language [" + getContext().getLanguage() + "].");
if (!isCurrentDocument(cellDocRef)) {
return getDependentDocumentReference(docRef, cellDocRef);
}
LOGGER.info("getDocumentReference: isCurrentDoc returning " + docRef);
return docRef;
}
/**
* @deprecated since 2.29.0 instead use getDocumentReference(DocumentReference,
* DocumentReference, boolean)
*/
@Deprecated
public DocumentReference getDocumentReference(XWikiDocument document,
DocumentReference cellDocRef, boolean isInheritable, XWikiContext context) {
return getDocumentReference(document.getDocumentReference(), cellDocRef, isInheritable);
}
public DocumentReference getDocumentReference(DocumentReference docRef,
DocumentReference cellDocRef, boolean isInheritable) {
LOGGER.debug("getDocumentReference: document [" + docRef + "] cellDocRef [" + cellDocRef
+ "] isInheritable [" + isInheritable + "] context language [" + getContext().getLanguage()
+ "].");
if (!isCurrentDocument(cellDocRef)) {
return getDependentDocumentReference(docRef, cellDocRef, isInheritable);
}
LOGGER.info("getDocumentReference: isCurrentDoc returning " + docRef);
return docRef;
}
/**
* @deprecated since 2.29.0 instead use getDocument(XWikiDocument, DocumentReference)
*/
@Deprecated
public XWikiDocument getDocument(XWikiDocument document, DocumentReference cellDocRef,
XWikiContext context) throws XWikiException {
return getDocument(document, cellDocRef);
}
public XWikiDocument getDocument(XWikiDocument document, DocumentReference cellDocRef)
throws XWikiException {
LOGGER.debug("getDocument: document [" + document.getDocumentReference() + "] cellDocRef ["
+ cellDocRef + "] context language [" + getContext().getLanguage() + "].");
if (!isCurrentDocument(cellDocRef)) {
DocumentReference dependentDocRef = getDependentDocumentReference(
document.getDocumentReference(), cellDocRef);
return getContext().getWiki().getDocument(dependentDocRef, getContext());
}
return document;
}
List<String> getDependentDocList(DocumentReference docRef, String depDocSpace) {
List<DocumentReference> docParentList = getWebUtilsService().getDocumentParentsList(docRef,
true);
List<String> depDocList = new ArrayList<String>(docParentList.size());
for (DocumentReference parentRef : docParentList) {
depDocList.add(depDocSpace + "." + parentRef.getName());
}
return depDocList;
}
/**
* @deprecated since 2.29.0 instead use getTranslatedDocument(XWikiDocument,
* DocumentReference)
*/
@Deprecated
public XWikiDocument getTranslatedDocument(XWikiDocument document, DocumentReference cellDocRef,
XWikiContext context) throws XWikiException {
return getTranslatedDocument(document, cellDocRef);
}
public XWikiDocument getTranslatedDocument(XWikiDocument document, DocumentReference cellDocRef)
throws XWikiException {
LOGGER.debug("getTranslatedDocument: document [" + document.getDocumentReference()
+ "] cellDocRef [" + cellDocRef + "] context language [" + getContext().getLanguage()
+ "].");
if (!isCurrentDocument(cellDocRef)) {
XWikiDocument tdoc = getDocument(document, cellDocRef).getTranslatedDocument(
getContext().getLanguage(), getContext());
LOGGER.trace("getTranslatedDocument returning tdoc [" + tdoc.getDocumentReference()
+ "] lang [" + tdoc.getLanguage() + "," + tdoc.getDefaultLanguage() + "].");
return tdoc;
}
return document;
}
DocumentReference getDependentDocumentReference(DocumentReference docRef,
DocumentReference cellDocRef) {
return getDependentDocumentReference(docRef, cellDocRef, isInheritable(cellDocRef));
}
DocumentReference getDependentDocumentReference(DocumentReference docRef,
DocumentReference cellDocRef, boolean isInheritable) {
SpaceReference depDocSpaceRef = getDependentDocumentSpaceRef(docRef, cellDocRef);
LOGGER.debug("getDependentDocumentReference: docRef [" + docRef + "] cellDocRef [" + cellDocRef
+ "] isInheritable [" + isInheritable + "] depDocSpaceRef [" + depDocSpaceRef + "].");
if (isInheritable) {
List<String> depDocList = getDependentDocList(docRef, depDocSpaceRef.getName());
if (LOGGER.isDebugEnabled()) {
LOGGER.debug("getDependentDocumentReference: inheritable for [" + docRef + "]"
+ " depDocList [" + Arrays.deepToString(depDocList.toArray(new String[0])) + "]. ");
} else {
LOGGER.info("getDependentDocumentReference: inheritable for [" + docRef + "]. ");
}
XWikiDocument pageDepDoc = new InheritorFactory().getContentInheritor(depDocList,
getContext()).getDocument();
if (pageDepDoc != null) {
return pageDepDoc.getDocumentReference();
} else {
LOGGER.debug("getDependentDocumentReference: inheritable result was null."
+ " Fallback to [" + depDocSpaceRef + "." + PDC_DEFAULT_CONTENT_NAME + "]");
return getDependentDefaultDocumentReference(docRef, cellDocRef);
}
} else {
return new DocumentReference(docRef.getName(), depDocSpaceRef);
}
}
public DocumentReference getDependentDefaultDocumentReference(DocumentReference docRef,
DocumentReference cellDocRef) {
DocumentReference spaceDefault = getSpaceDefaultDocRef(docRef, cellDocRef);
List<String> depDefaultDocList = new ArrayList<String>();
depDefaultDocList.add(getRefSerializer().serialize(spaceDefault));
depDefaultDocList.add(getRefSerializer().serialize(getWikiDefaultDocRef(docRef, cellDocRef)));
if (getCurrentLayoutRef() != null) {
DocumentReference layoutDefault = getLayoutDefaultDocRef(getCurrentLayoutRef(), cellDocRef);
LOGGER.trace("getDependentDefaultDocumentReference: layout default docRef '{}'",
layoutDefault);
if (layoutDefault != null) {
depDefaultDocList.add(getRefSerializer().serialize(layoutDefault));
}
} else {
LOGGER.trace("getDependentDefaultDocumentReference: no current layout reference found.");
}
XWikiDocument pageDepDoc = new InheritorFactory().getContentInheritor(depDefaultDocList,
getContext()).getDocument();
if (pageDepDoc != null) {
LOGGER.debug("getDependentDefaultDocumentReference: docList '{}', pageDepDoc '{}'",
depDefaultDocList, pageDepDoc.getDocumentReference());
return pageDepDoc.getDocumentReference();
} else {
LOGGER.debug("getDependentDefaultDocumentReference: docList '{}', no default doc found!"
+ " Using spaceDefault", depDefaultDocList);
// XXX What should be the default?
// For now using spaceDefault for backwards compatibility
return spaceDefault;
}
}
public void setCurrentLayoutRef(SpaceReference currentLayoutRef) {
LOGGER.info("setCurrentLayoutRef: '{}'", currentLayoutRef);
this.currentLayoutRef = currentLayoutRef;
}
SpaceReference getCurrentLayoutRef() {
if (currentLayoutRef == null) {
currentLayoutRef = getPageLayoutCmd().getPageLayoutForCurrentDoc();
LOGGER.info("getCurrentLayoutRef: '{}'", currentLayoutRef);
}
return currentLayoutRef;
}
public DocumentReference getLayoutDefaultDocRef(SpaceReference currLayoutRef,
DocumentReference cellDocRef) {
String depCellSpace = null;
try {
depCellSpace = getDepCellSpace(cellDocRef);
} catch (XWikiException exp) {
LOGGER.warn("Failed to get layoutDefault because unable to get depCellSpace for ["
+ cellDocRef + "] omitting layout default.", exp);
}
return getLayoutDefaultDocRef(currLayoutRef, depCellSpace);
}
public DocumentReference getLayoutDefaultDocRef(SpaceReference currLayoutRef,
String depCellSpace) {
if ((depCellSpace != null) && (!"".equals(depCellSpace))) {
return new DocumentReference(depCellSpace + "-"
+ PageDependentDocumentReferenceCommand.PDC_DEFAULT_CONTENT_NAME, currLayoutRef);
}
return null;
}
public DocumentReference getWikiDefaultDocRef(String depCellSpaceSuffix) {
return getSpaceDefaultDocRef(getDependentWikiSpaceRef(depCellSpaceSuffix));
}
public DocumentReference getWikiDefaultDocRef(DocumentReference docRef,
DocumentReference cellDocRef) {
return getSpaceDefaultDocRef(getDependentWikiSpaceRef(docRef, cellDocRef));
}
public DocumentReference getSpaceDefaultDocRef(DocumentReference docRef,
DocumentReference cellDocRef) {
return getSpaceDefaultDocRef(getDependentDocumentSpaceRef(docRef, cellDocRef));
}
public DocumentReference getSpaceDefaultDocRef(SpaceReference depDocumentSpaceRef) {
return new DocumentReference(PDC_DEFAULT_CONTENT_NAME, depDocumentSpaceRef);
}
/**
* @deprecated since 2.29.0 instead use getDependentDocumentSpace(DocumentReference,
* DocumentReference)
*/
@Deprecated
public String getDependentDocumentSpace(XWikiDocument document, DocumentReference cellDocRef,
XWikiContext context) {
DocumentReference docRef = document.getDocumentReference();
return getDependentDocumentSpaceRef(docRef, cellDocRef).getName();
}
public SpaceReference getDependentDocumentSpaceRef(DocumentReference docRef,
DocumentReference cellDocRef) {
SpaceReference spaceRef;
try {
if (!"".equals(getDepCellSpace(cellDocRef))) {
SpaceReference curSpaceRef = getCurrentDocumentSpaceRef(docRef);
/*
* IMPORTANT: do not use .clone() on any reference it will not be available on
* unstable branch
*/
spaceRef = new SpaceReference(curSpaceRef.getName() + "_" + getDepCellSpace(cellDocRef),
(WikiReference) curSpaceRef.getParent());
} else {
LOGGER.warn("getDependentDocumentSpace: fallback to currentDocument. Please"
+ " check with isCurrentDocument method before calling"
+ " getDependentDocumentSpace!");
spaceRef = getCurrentDocumentSpaceRef(docRef);
}
} catch (XWikiException exp) {
spaceRef = getCurrentDocumentSpaceRef(docRef);
LOGGER.error("getDependentDocumentSpace: Failed to get getDepCellSpace from [" + cellDocRef
+ "] assuming" + " [" + spaceRef + "] for document space.", exp);
}
return spaceRef;
}
public SpaceReference getDependentWikiSpaceRef(DocumentReference docRef,
DocumentReference cellDocRef) {
SpaceReference spaceRef;
try {
String depCellSpace = getDepCellSpace(cellDocRef);
spaceRef = getDependentWikiSpaceRef(depCellSpace);
if (spaceRef == null) {
LOGGER.warn("getDependentDocumentSpace: fallback to currentDocument. Please"
+ " check with isCurrentDocument method before calling"
+ " getDependentDocumentSpace!");
spaceRef = getCurrentDocumentSpaceRef(docRef);
}
} catch (XWikiException exp) {
spaceRef = getCurrentDocumentSpaceRef(docRef);
LOGGER.error("getDependentDocumentSpace: Failed to get getDepCellSpace from [" + cellDocRef
+ "] assuming" + " [" + spaceRef + "] for document space.", exp);
}
return spaceRef;
}
private SpaceReference getDependentWikiSpaceRef(String depCellSpaceSuffix) {
SpaceReference spaceRef = null;
if ((depCellSpaceSuffix != null) && !"".equals(depCellSpaceSuffix)) {
String spaceName = PDC_WIKIDEFAULT_SPACE_NAME + "_" + depCellSpaceSuffix;
spaceRef = new SpaceReference(spaceName, new WikiReference(getContext().getDatabase()));
}
return spaceRef;
}
SpaceReference getCurrentDocumentSpaceRef(DocumentReference docRef) {
LOGGER.info("getCurrentDocumentSpaceRef for document [" + docRef + "].");
SpaceReference spaceRef;
List<SpaceReference> currentSpaces = docRef.getSpaceReferences();
if (currentSpaces.size() > 0) {
spaceRef = currentSpaces.get(0);
} else {
spaceRef = new SpaceReference(getConfigProvider().getDefaultValue(EntityType.SPACE),
new WikiReference(getContext().getDatabase()));
LOGGER.warn("getCurrentDocumentSpaceRef: no space reference for current Document" + " ["
+ docRef + "] found. Fallback to default [" + spaceRef + "].");
}
return spaceRef;
}
boolean isCurrentDocument(DocumentReference cellDocRef) {
try {
return "".equals(getDepCellSpace(cellDocRef));
} catch (XWikiException exp) {
LOGGER.error("Failed to get PageDepCellConfigClass object from [" + cellDocRef + "].", exp);
// return true, because without config we are unable to determine the document
return true;
}
}
public String getDepCellSpace(DocumentReference cellDocRef) throws XWikiException {
BaseObject cellConfObj = getDepCellXObject(cellDocRef);
if (cellConfObj != null) {
String spaceName = cellConfObj.getStringValue(PROPNAME_SPACE_NAME);
LOGGER.debug("getDepCellSpace: spaceName [" + spaceName + "] for [" + cellDocRef + "]");
if (spaceName != null) {
return spaceName;
}
} else {
LOGGER.debug("getDepCellSpace: no cellConfObj found for [" + cellDocRef + "]");
}
return "";
}
/**
* @deprecated since 2.29.0 instead use isInheritable(DocumentReference)
*/
@Deprecated
public boolean isInheritable(DocumentReference cellDocRef, XWikiContext context) {
return isInheritable(cellDocRef);
}
public boolean isInheritable(DocumentReference cellDocRef) {
try {
BaseObject cellConfObj = getDepCellXObject(cellDocRef);
if (cellConfObj != null) {
return (cellConfObj.getIntValue(PROPNAME_IS_INHERITABLE, 0) != 0);
}
} catch (XWikiException exp) {
LOGGER.error("Faild to check if isInheritable for [" + cellDocRef.getLastSpaceReference()
+ "." + cellDocRef.getName() + "].", exp);
}
return false;
}
private BaseObject getDepCellXObject(DocumentReference cellDocRef) throws XWikiException {
BaseObject cellConfObj = getContext().getWiki().getDocument(cellDocRef,
getContext()).getXObject(getCellsClassConfig().getPageDepCellConfigClassRef(
cellDocRef.getWikiReference().getName()));
return cellConfObj;
}
/**
* @deprecated since 2.29.0 instead use getPageDepCellConfigClassDocRef()
*/
@Deprecated
public DocumentReference getPageDepCellConfigClassDocRef(XWikiContext context) {
return getPageDepCellConfigClassDocRef();
}
/**
* @deprecated since 2.81 instead use
* {@link ICellsClassConfig#getPageDepCellConfigClassRef(String)}
*/
@Deprecated
public DocumentReference getPageDepCellConfigClassDocRef() {
DocumentReference pageDepConfigClassRef = new DocumentReference(getContext().getDatabase(),
PAGE_DEP_CELL_CONFIG_CLASS_SPACE, PAGE_DEP_CELL_CONFIG_CLASS_DOC);
return pageDepConfigClassRef;
}
private ICellsClassConfig getCellsClassConfig() {
return Utils.getComponent(ICellsClassConfig.class);
}
private IWebUtilsService getWebUtilsService() {
if (inject_WebUtilsService != null) {
return inject_WebUtilsService;
}
return Utils.getComponent(IWebUtilsService.class);
}
private XWikiContext getContext() {
return (XWikiContext) Utils.getComponent(Execution.class).getContext().getProperty(
XWikiContext.EXECUTIONCONTEXT_KEY);
}
private EntityReferenceValueProvider getConfigProvider() {
return Utils.getComponent(EntityReferenceValueProvider.class);
}
PageLayoutCommand getPageLayoutCmd() {
if (this.pageLayoutCmd == null) {
this.pageLayoutCmd = new PageLayoutCommand();
}
return this.pageLayoutCmd;
}
private EntityReferenceSerializer<String> getRefSerializer() {
return getWebUtilsService().getRefDefaultSerializer();
}
}