/*
* (C) Copyright 2006-2012 Nuxeo SA (http://nuxeo.com/) and others.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
* Contributors:
* Razvan Caraghin
* Florent Guillaume
* Thierry Martins
* Antoine Taillefer
*/
package org.nuxeo.ecm.webapp.versioning;
import static org.jboss.seam.ScopeType.CONVERSATION;
import static org.jboss.seam.ScopeType.EVENT;
import static org.jboss.seam.annotations.Install.FRAMEWORK;
import static org.nuxeo.ecm.webapp.helpers.EventNames.DOCUMENT_CHANGED;
import static org.nuxeo.ecm.webapp.helpers.EventNames.DOCUMENT_PUBLISHED;
import static org.nuxeo.ecm.webapp.helpers.EventNames.DOCUMENT_SELECTION_CHANGED;
import static org.nuxeo.ecm.webapp.helpers.EventNames.DOCUMENT_SUBMITED_FOR_PUBLICATION;
import java.io.Serializable;
import java.util.ArrayList;
import java.util.List;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.jboss.seam.annotations.Create;
import org.jboss.seam.annotations.Factory;
import org.jboss.seam.annotations.In;
import org.jboss.seam.annotations.Install;
import org.jboss.seam.annotations.Name;
import org.jboss.seam.annotations.Observer;
import org.jboss.seam.annotations.Scope;
import org.jboss.seam.annotations.intercept.BypassInterceptors;
import org.jboss.seam.contexts.Context;
import org.jboss.seam.faces.FacesMessages;
import org.jboss.seam.international.StatusMessage;
import org.nuxeo.ecm.core.api.CoreSession;
import org.nuxeo.ecm.core.api.DocumentModel;
import org.nuxeo.ecm.core.api.DocumentRef;
import org.nuxeo.ecm.core.api.IdRef;
import org.nuxeo.ecm.core.api.VersionModel;
import org.nuxeo.ecm.core.api.impl.VersionModelImpl;
import org.nuxeo.ecm.core.api.security.SecurityConstants;
import org.nuxeo.ecm.platform.query.api.PageSelection;
import org.nuxeo.ecm.platform.query.api.PageSelections;
import org.nuxeo.ecm.platform.ui.web.api.NavigationContext;
import org.nuxeo.ecm.platform.ui.web.api.UserAction;
import org.nuxeo.ecm.webapp.documentsLists.DocumentsListsManager;
import org.nuxeo.ecm.webapp.helpers.EventManager;
import org.nuxeo.ecm.webapp.helpers.ResourcesAccessor;
/**
* Deals with versioning actions.
*
* @author Razvan Caraghin
* @author Florent Guillaume
* @author Thierry Martins
*/
@Name("versionedActions")
@Scope(CONVERSATION)
@Install(precedence = FRAMEWORK)
public class VersionedActionsBean implements VersionedActions, Serializable {
private static final long serialVersionUID = 4472648747609642493L;
private static final Log log = LogFactory.getLog(VersionedActionsBean.class);
@In(create = true)
protected transient NavigationContext navigationContext;
/** @since 5.6 */
@In(create = true, required = false)
protected transient DocumentsListsManager documentsListsManager;
@In(create = true, required = false)
protected transient CoreSession documentManager;
@In(create = true, required = false)
protected transient FacesMessages facesMessages;
@In(create = true, required = false)
protected transient ResourcesAccessor resourcesAccessor;
@In
protected transient Context sessionContext;
@In(create = true)
protected transient DocumentVersioning documentVersioning;
protected transient PageSelections<VersionModel> versionModelList;
protected String selectedVersionId;
protected String checkedOut;
@Create
@Override
public void initialize() {
}
@Observer(value = { DOCUMENT_SELECTION_CHANGED, DOCUMENT_CHANGED, DOCUMENT_SUBMITED_FOR_PUBLICATION,
DOCUMENT_PUBLISHED }, create = false)
@BypassInterceptors
@Override
public void resetVersions() {
versionModelList = null;
}
@Override
@Factory(value = "versionList", scope = EVENT)
public PageSelections<VersionModel> getVersionList() {
if (versionModelList == null || versionModelList.getEntries() == null
|| versionModelList.getEntries().isEmpty()) {
retrieveVersions();
}
return versionModelList;
}
@Override
public void retrieveVersions() {
/**
* in case the document is a proxy,meaning is the result of a publishing,to have the history of the document
* from which this proxy was created,first we have to get to the version that was created when the document was
* publish,and to which the proxy document indicates,and then from that version we have to get to the root
* document.
*/
DocumentModel currentDocument = navigationContext.getCurrentDocument();
DocumentModel doc;
if (currentDocument.isProxy()) {
DocumentRef ref = currentDocument.getRef();
DocumentModel version = documentManager.getSourceDocument(ref);
doc = documentManager.getSourceDocument(version.getRef());
} else {
doc = currentDocument;
}
List<PageSelection<VersionModel>> versionModelSelections = new ArrayList<PageSelection<VersionModel>>();
for (VersionModel versionModel : documentVersioning.getItemVersioningHistory(doc)) {
versionModelSelections.add(new PageSelection<VersionModel>(versionModel, isVersionSelected(versionModel)));
}
versionModelList = new PageSelections<VersionModel>(versionModelSelections);
}
/**
* Checks if the {@code versionModel} is selected.
*
* @param versionModel the version model
* @return true, if the {@versionModel} is selected
*/
protected boolean isVersionSelected(VersionModel versionModel) {
List<DocumentModel> currentVersionSelection = documentsListsManager.getWorkingList(DocumentsListsManager.CURRENT_VERSION_SELECTION);
if (currentVersionSelection != null) {
DocumentModel currentDocument = navigationContext.getCurrentDocument();
if (currentDocument != null) {
DocumentModel version = documentManager.getDocumentWithVersion(currentDocument.getRef(), versionModel);
if (version != null) {
return currentVersionSelection.contains(version);
}
}
}
return false;
}
/**
* Restores the document to the selected version. If there is no selected version it does nothing.
*
* @return the page that needs to be displayed next
*/
@Override
public String restoreToVersion(VersionModel selectedVersion) {
DocumentModel restoredDocument = documentManager.restoreToVersion(
navigationContext.getCurrentDocument().getRef(), new IdRef(selectedVersion.getId()), true, true);
documentManager.save();
// same as edit basically
// XXX AT: do edit events need to be sent?
EventManager.raiseEventsOnDocumentChange(restoredDocument);
return navigationContext.navigateToDocument(restoredDocument, "after-edit");
}
@Override
public String restoreToVersion() {
if (getSelectedVersionId() != null) {
VersionModel selectedVersion = new VersionModelImpl();
selectedVersion.setId(getSelectedVersionId());
return restoreToVersion(selectedVersion);
}
return null;
}
@Override
public String viewArchivedVersion(VersionModel selectedVersion) {
return navigationContext.navigateToDocument(navigationContext.getCurrentDocument(), selectedVersion);
}
@Override
public String viewArchivedVersion() {
if (getSelectedVersionId() != null) {
VersionModel selectedVersion = new VersionModelImpl();
selectedVersion.setId(getSelectedVersionId());
return viewArchivedVersion(selectedVersion);
}
return null;
}
@Override
public boolean getCanRestore() {
// TODO: should check for a specific RESTORE permission instead
return documentManager.hasPermission(navigationContext.getCurrentDocument().getRef(),
SecurityConstants.WRITE_VERSION);
}
/**
* Tells if the current selected document is checked out or not.
*/
@Override
public String getCheckedOut() {
if (documentManager.isCheckedOut(navigationContext.getCurrentDocument().getRef())) {
checkedOut = "Checked-out";
} else {
checkedOut = "Checked-in";
}
return checkedOut;
}
@Override
public void setCheckedOut(String checkedOut) {
this.checkedOut = checkedOut;
}
/**
* Checks the document out.
*
* @return the next page
*/
@Override
public String checkOut() {
documentManager.checkOut(navigationContext.getCurrentDocument().getRef());
return null;
}
/**
* Checks the selected document in, with the selected version.
*/
@Override
public String checkIn() {
DocumentModel currentDocument = navigationContext.getCurrentDocument();
documentManager.checkIn(currentDocument.getRef(), null, null);
retrieveVersions();
return navigationContext.getActionResult(currentDocument, UserAction.AFTER_EDIT);
}
@Override
public DocumentModel getSourceDocument() {
return getSourceDocument(navigationContext.getCurrentDocument());
}
/**
* @since 5.4
*/
@Override
public DocumentModel getSourceDocument(DocumentModel document) {
return documentManager.getSourceDocument(document.getRef());
}
@Override
public boolean canRemoveArchivedVersion(VersionModel selectedVersion) {
DocumentRef docRef = navigationContext.getCurrentDocument().getRef();
DocumentModel docVersion = documentManager.getDocumentWithVersion(docRef, selectedVersion);
if (docVersion == null) {
// it doesn't exist? don't remove. Still it is a problem
log.warn("Unexpectedly couldn't find the version " + selectedVersion.getLabel());
return false;
}
return documentManager.canRemoveDocument(docVersion.getRef());
}
/**
* @since 5.6
*/
@Override
public boolean getCanRemoveSelectedArchivedVersions() {
List<DocumentModel> currentVersionSelection = documentsListsManager.getWorkingList(DocumentsListsManager.CURRENT_VERSION_SELECTION);
if (currentVersionSelection != null && currentVersionSelection.size() > 0) {
for (DocumentModel version : currentVersionSelection) {
if (!documentManager.canRemoveDocument(version.getRef())) {
return false;
}
}
return true;
}
return false;
}
@Override
public String removeArchivedVersion(VersionModel selectedVersion) {
DocumentRef docRef = navigationContext.getCurrentDocument().getRef();
DocumentModel docVersion = documentManager.getDocumentWithVersion(docRef, selectedVersion);
if (docVersion == null) {
// it doesn't exist? consider removed
log.warn("Unexpectedly couldn't find the version " + selectedVersion.getLabel());
return null;
}
documentManager.removeDocument(docVersion.getRef());
documentManager.save();
resetVersions();
facesMessages.add(StatusMessage.Severity.INFO,
resourcesAccessor.getMessages().get("feedback.versioning.versionRemoved"));
return null;
}
/**
* @since 5.6
*/
@Override
public String removeSelectedArchivedVersions() {
List<DocumentModel> currentVersionSelection = documentsListsManager.getWorkingList(DocumentsListsManager.CURRENT_VERSION_SELECTION);
if (currentVersionSelection == null || currentVersionSelection.isEmpty()) {
log.warn("Currently selected version list is null or empty, cannot remove any version.");
return null;
}
for (DocumentModel version : currentVersionSelection) {
if (version != null) {
documentManager.removeDocument(version.getRef());
}
}
documentManager.save();
resetVersions();
// remove from all lists
documentsListsManager.removeFromAllLists(new ArrayList<DocumentModel>(currentVersionSelection));
facesMessages.add(StatusMessage.Severity.INFO,
resourcesAccessor.getMessages().get("feedback.versioning.versionsRemoved"));
return null;
}
@Override
public String getSelectedVersionId() {
return selectedVersionId;
}
@Override
public void setSelectedVersionId(String selectedVersionId) {
this.selectedVersionId = selectedVersionId;
}
}