/*
* (C) Copyright 2006-2007 Nuxeo SAS (http://nuxeo.com/) and contributors.
*
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the GNU Lesser General Public License
* (LGPL) version 2.1 which accompanies this distribution, and is available at
* http://www.gnu.org/licenses/lgpl.html
*
* This library 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.
*
* Contributors:
* Nuxeo - initial API and implementation
*
* $Id$
*/
package org.nuxeo.ecm.webapp.clipboard;
import static org.jboss.seam.ScopeType.EVENT;
import static org.jboss.seam.ScopeType.SESSION;
import java.io.File;
import java.io.IOException;
import java.io.Serializable;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.HashMap;
import java.util.HashSet;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;
import java.util.Set;
import javax.faces.context.FacesContext;
import javax.servlet.http.HttpServletRequest;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.jboss.seam.annotations.Factory;
import org.jboss.seam.annotations.In;
import org.jboss.seam.annotations.Name;
import org.jboss.seam.annotations.Scope;
import org.jboss.seam.annotations.remoting.WebRemote;
import org.jboss.seam.annotations.web.RequestParameter;
import org.jboss.seam.core.Events;
import org.jboss.seam.international.LocaleSelector;
import org.jboss.seam.international.StatusMessage;
import org.nuxeo.ecm.core.api.ClientException;
import org.nuxeo.ecm.core.api.CoreSession;
import org.nuxeo.ecm.core.api.DocumentModel;
import org.nuxeo.ecm.core.api.DocumentModelList;
import org.nuxeo.ecm.core.api.DocumentRef;
import org.nuxeo.ecm.core.api.IdRef;
import org.nuxeo.ecm.core.api.LifeCycleConstants;
import org.nuxeo.ecm.core.api.security.SecurityConstants;
import org.nuxeo.ecm.core.schema.FacetNames;
import org.nuxeo.ecm.core.schema.SchemaManager;
import org.nuxeo.ecm.platform.actions.Action;
import org.nuxeo.ecm.platform.ui.web.api.WebActions;
import org.nuxeo.ecm.platform.ui.web.auth.NXAuthConstants;
import org.nuxeo.ecm.platform.ui.web.cache.SeamCacheHelper;
import org.nuxeo.ecm.platform.ui.web.tag.fn.Functions;
import org.nuxeo.ecm.platform.ui.web.util.BaseURL;
import org.nuxeo.ecm.platform.ui.web.util.ComponentUtils;
import org.nuxeo.ecm.webapp.base.InputController;
import org.nuxeo.ecm.webapp.documentsLists.DocumentsListDescriptor;
import org.nuxeo.ecm.webapp.documentsLists.DocumentsListsManager;
import org.nuxeo.ecm.webapp.helpers.EventManager;
import org.nuxeo.ecm.webapp.helpers.EventNames;
import org.nuxeo.runtime.api.Framework;
/**
* This is the action listener behind the copy/paste template that knows how to
* copy/paste the selected user data to the target action listener, and also
* create/remove the corresponding objects into the backend.
*
* @author <a href="mailto:rcaraghin@nuxeo.com">Razvan Caraghin</a>
*/
@Name("clipboardActions")
@Scope(SESSION)
public class ClipboardActionsBean extends InputController implements
ClipboardActions, Serializable {
private static final long serialVersionUID = -2407222456116573225L;
private static final Log log = LogFactory.getLog(ClipboardActionsBean.class);
private static final String PASTE_OUTCOME = "after_paste";
/**
* @deprecated use {@link LifeCycleConstants#DELETED_STATE}
*/
@Deprecated
public static final String DELETED_LIFECYCLE_STATE = "deleted";
@In(create = true, required = false)
protected transient CoreSession documentManager;
@In(create = true)
protected transient DocumentsListsManager documentsListsManager;
@In(create = true)
protected transient WebActions webActions; // it is serializable
@In(create = true)
protected transient LocaleSelector localeSelector;
@RequestParameter()
protected String workListDocId;
private String currentSelectedList;
private String previouslySelectedList;
private transient List<String> availableLists;
private transient List<DocumentsListDescriptor> descriptorsForAvailableLists;
private Boolean canEditSelectedDocs;
private transient Map<String, List<Action>> actionCache;
public void releaseClipboardableDocuments() {
}
public boolean isInitialized() {
return documentManager != null;
}
public void putSelectionInWorkList(Boolean forceAppend) {
canEditSelectedDocs = null;
if (!documentsListsManager.isWorkingListEmpty(DocumentsListsManager.CURRENT_DOCUMENT_SELECTION)) {
putSelectionInWorkList(
documentsListsManager.getWorkingList(DocumentsListsManager.CURRENT_DOCUMENT_SELECTION),
forceAppend);
autoSelectCurrentList(DocumentsListsManager.DEFAULT_WORKING_LIST);
} else {
log.debug("No selectable Documents in context to process copy on...");
}
log.debug("add to worklist processed...");
}
public void putSelectionInWorkList() {
putSelectionInWorkList(false);
}
public void putSelectionInDefaultWorkList() {
canEditSelectedDocs = null;
if (!documentsListsManager.isWorkingListEmpty(DocumentsListsManager.CURRENT_DOCUMENT_SELECTION)) {
List<DocumentModel> docsList = documentsListsManager.getWorkingList(DocumentsListsManager.CURRENT_DOCUMENT_SELECTION);
Object[] params = { docsList.size() };
facesMessages.add(StatusMessage.Severity.INFO, "#0 "
+ resourcesAccessor.getMessages().get("n_copied_docs"),
params);
documentsListsManager.addToWorkingList(
DocumentsListsManager.DEFAULT_WORKING_LIST, docsList);
// auto select clipboard
autoSelectCurrentList(DocumentsListsManager.DEFAULT_WORKING_LIST);
} else {
log.debug("No selectable Documents in context to process copy on...");
}
log.debug("add to worklist processed...");
}
@WebRemote
public void putInClipboard(String docId) throws ClientException {
DocumentModel doc = documentManager.getDocument(new IdRef(docId));
documentsListsManager.addToWorkingList(DocumentsListsManager.CLIPBOARD,
doc);
Object[] params = { 1 };
facesMessages.add(StatusMessage.Severity.INFO, "#0 "
+ resourcesAccessor.getMessages().get("n_copied_docs"), params);
autoSelectCurrentList(DocumentsListsManager.CLIPBOARD);
}
public void putSelectionInClipboard() {
canEditSelectedDocs = null;
if (!documentsListsManager.isWorkingListEmpty(DocumentsListsManager.CURRENT_DOCUMENT_SELECTION)) {
List<DocumentModel> docsList = documentsListsManager.getWorkingList(DocumentsListsManager.CURRENT_DOCUMENT_SELECTION);
Object[] params = { docsList.size() };
facesMessages.add(StatusMessage.Severity.INFO, "#0 "
+ resourcesAccessor.getMessages().get("n_copied_docs"),
params);
documentsListsManager.addToWorkingList(
DocumentsListsManager.CLIPBOARD, docsList);
// auto select clipboard
autoSelectCurrentList(DocumentsListsManager.CLIPBOARD);
} else {
log.debug("No selectable Documents in context to process copy on...");
}
log.debug("add to worklist processed...");
}
public void putSelectionInWorkList(List<DocumentModel> docsList) {
putSelectionInWorkList(docsList, false);
}
public void putSelectionInWorkList(List<DocumentModel> docsList,
Boolean forceAppend) {
canEditSelectedDocs = null;
if (null != docsList) {
Object[] params = { docsList.size() };
facesMessages.add(
StatusMessage.Severity.INFO,
"#0 "
+ resourcesAccessor.getMessages().get(
"n_added_to_worklist_docs"), params);
// Add to the default working list
documentsListsManager.addToWorkingList(
getCurrentSelectedListName(), docsList, forceAppend);
log.debug("Elements copied to clipboard...");
} else {
log.debug("No copiedDocs to process copy on...");
}
log.debug("add to worklist processed...");
}
@Deprecated
public void copySelection(List<DocumentModel> copiedDocs) {
if (null != copiedDocs) {
Object[] params = { copiedDocs.size() };
facesMessages.add(StatusMessage.Severity.INFO, "#0 "
+ resourcesAccessor.getMessages().get("n_copied_docs"),
params);
// clipboard.copy(copiedDocs);
// Reset + Add to clipboard list
documentsListsManager.resetWorkingList(DocumentsListsManager.CLIPBOARD);
documentsListsManager.addToWorkingList(
DocumentsListsManager.CLIPBOARD, copiedDocs);
// Add to the default working list
documentsListsManager.addToWorkingList(copiedDocs);
log.debug("Elements copied to clipboard...");
} else {
log.debug("No copiedDocs to process copy on...");
}
log.debug("Copy processed...");
}
public String removeWorkListItem(DocumentRef ref) throws ClientException {
DocumentModel doc = documentManager.getDocument(ref);
documentsListsManager.removeFromWorkingList(
getCurrentSelectedListName(), doc);
return null;
}
public String clearWorkingList() {
documentsListsManager.resetWorkingList(getCurrentSelectedListName());
return null;
}
public String pasteDocumentList(String listName) throws ClientException {
return pasteDocumentList(documentsListsManager.getWorkingList(listName));
}
public String pasteDocumentListInside(String listName, String docId)
throws ClientException {
return pasteDocumentListInside(
documentsListsManager.getWorkingList(listName), docId);
}
public String pasteDocumentList(List<DocumentModel> docPaste)
throws ClientException {
DocumentModel currentDocument = navigationContext.getCurrentDocument();
if (null != docPaste) {
List<DocumentModel> newDocs = recreateDocumentsWithNewParent(
getParent(currentDocument), docPaste);
Object[] params = { newDocs.size() };
facesMessages.add(StatusMessage.Severity.INFO, "#0 "
+ resourcesAccessor.getMessages().get("n_pasted_docs"),
params);
EventManager.raiseEventsOnDocumentSelected(currentDocument);
Events.instance().raiseEvent(EventNames.DOCUMENT_CHILDREN_CHANGED,
currentDocument);
log.debug("Elements pasted and created into the backend...");
} else {
log.debug("No docPaste to process paste on...");
}
return computeOutcome(PASTE_OUTCOME);
}
public String pasteDocumentListInside(List<DocumentModel> docPaste,
String docId) throws ClientException {
DocumentModel targetDoc = documentManager.getDocument(new IdRef(docId));
if (null != docPaste) {
List<DocumentModel> newDocs = recreateDocumentsWithNewParent(
targetDoc, docPaste);
Object[] params = { newDocs.size() };
facesMessages.add(StatusMessage.Severity.INFO, "#0 "
+ resourcesAccessor.getMessages().get("n_pasted_docs"),
params);
EventManager.raiseEventsOnDocumentSelected(targetDoc);
Events.instance().raiseEvent(EventNames.DOCUMENT_CHILDREN_CHANGED,
targetDoc);
log.debug("Elements pasted and created into the backend...");
} else {
log.debug("No docPaste to process paste on...");
}
return null;
}
public List<DocumentModel> moveDocumentsToNewParent(
DocumentModel destFolder, List<DocumentModel> docs)
throws ClientException {
DocumentRef destFolderRef = destFolder.getRef();
boolean destinationIsDeleted = LifeCycleConstants.DELETED_STATE.equals(destFolder.getCurrentLifeCycleState());
List<DocumentModel> newDocs = new ArrayList<DocumentModel>();
StringBuilder sb = new StringBuilder();
for (DocumentModel docModel : docs) {
DocumentRef sourceFolderRef = docModel.getParentRef();
String sourceType = docModel.getType();
boolean canRemoveDoc = documentManager.hasPermission(
sourceFolderRef, SecurityConstants.REMOVE_CHILDREN);
boolean canPasteInCurrentFolder = typeManager.isAllowedSubType(
sourceType, destFolder.getType(),
navigationContext.getCurrentDocument());
boolean sameFolder = sourceFolderRef.equals(destFolderRef);
if (canRemoveDoc && canPasteInCurrentFolder && !sameFolder) {
if (destinationIsDeleted) {
if (checkDeletedState(docModel)) {
DocumentModel newDoc = documentManager.move(
docModel.getRef(), destFolderRef, null);
setDeleteState(newDoc);
newDocs.add(newDoc);
} else {
addWarnMessage(sb, docModel);
}
} else {
DocumentModel newDoc = documentManager.move(
docModel.getRef(), destFolderRef, null);
newDocs.add(newDoc);
}
}
}
documentManager.save();
if (sb.length() > 0) {
facesMessages.add(StatusMessage.Severity.WARN, sb.toString(), null);
}
return newDocs;
}
public String moveDocumentList(String listName, String docId)
throws ClientException {
List<DocumentModel> docs = documentsListsManager.getWorkingList(listName);
DocumentModel targetDoc = documentManager.getDocument(new IdRef(docId));
// Get all parent folders
Set<DocumentRef> parentRefs = new HashSet<DocumentRef>();
for (DocumentModel doc : docs) {
parentRefs.add(doc.getParentRef());
}
List<DocumentModel> newDocs = moveDocumentsToNewParent(targetDoc, docs);
documentsListsManager.resetWorkingList(listName);
Object[] params = { newDocs.size() };
facesMessages.add(StatusMessage.Severity.INFO, "#0 "
+ resourcesAccessor.getMessages().get("n_moved_docs"), params);
EventManager.raiseEventsOnDocumentSelected(targetDoc);
Events.instance().raiseEvent(EventNames.DOCUMENT_CHILDREN_CHANGED,
targetDoc);
// Send event to all initial parents
for (DocumentRef docRef : parentRefs) {
Events.instance().raiseEvent(EventNames.DOCUMENT_CHILDREN_CHANGED,
documentManager.getDocument(docRef));
}
log.debug("Elements moved and created into the backend...");
return null;
}
public String moveDocumentList(String listName) throws ClientException {
DocumentModel currentDocument = navigationContext.getCurrentDocument();
return moveDocumentList(listName, currentDocument.getId());
}
public String moveWorkingList() {
try {
moveDocumentList(getCurrentSelectedListName());
} catch (ClientException e) {
log.info("moveWorkingList failed" + e.getMessage(), e);
facesMessages.add(StatusMessage.Severity.WARN,
resourcesAccessor.getMessages().get("invalid_operation"),
null);
}
return null;
}
public String pasteWorkingList() {
try {
pasteDocumentList(getCurrentSelectedList());
} catch (ClientException e) {
log.info("pasteWorkingList failed" + e.getMessage(), e);
facesMessages.add(StatusMessage.Severity.WARN,
resourcesAccessor.getMessages().get("invalid_operation"),
null);
}
return null;
}
public String pasteClipboard() {
try {
pasteDocumentList(DocumentsListsManager.CLIPBOARD);
returnToPreviouslySelectedList();
} catch (ClientException e) {
log.info("pasteClipboard failed" + e.getMessage(), e);
facesMessages.add(StatusMessage.Severity.WARN,
resourcesAccessor.getMessages().get("invalid_operation"),
null);
}
return null;
}
@WebRemote
public String pasteClipboardInside(String docId) throws ClientException {
pasteDocumentListInside(DocumentsListsManager.CLIPBOARD, docId);
return null;
}
@WebRemote
public String moveClipboardInside(String docId) throws ClientException {
moveDocumentList(DocumentsListsManager.CLIPBOARD, docId);
return null;
}
/**
* Creates the documents in the backend under the target parent.
*/
protected List<DocumentModel> recreateDocumentsWithNewParent(
DocumentModel parent, List<DocumentModel> documents)
throws ClientException {
List<DocumentModel> newDocuments = new ArrayList<DocumentModel>();
if (null == parent || null == documents) {
log.error("Null params received, returning...");
return newDocuments;
}
List<DocumentModel> documentsToPast = new LinkedList<DocumentModel>();
// filter list on content type
for (DocumentModel doc : documents) {
if (typeManager.isAllowedSubType(doc.getType(), parent.getType(),
navigationContext.getCurrentDocument())) {
documentsToPast.add(doc);
}
}
// copying proxy or document
boolean isPublishSpace = isPublishSpace(parent);
boolean destinationIsDeleted = LifeCycleConstants.DELETED_STATE.equals(parent.getCurrentLifeCycleState());
List<DocumentRef> docRefs = new ArrayList<DocumentRef>();
List<DocumentRef> proxyRefs = new ArrayList<DocumentRef>();
StringBuilder sb = new StringBuilder();
for (DocumentModel doc : documentsToPast) {
if (destinationIsDeleted && !checkDeletedState(doc)) {
addWarnMessage(sb, doc);
} else if (doc.isProxy() && !isPublishSpace) {
// in a non-publish space, we want to expand proxies into
// normal docs
proxyRefs.add(doc.getRef());
} else {
// copy as is
docRefs.add(doc.getRef());
}
}
if (!proxyRefs.isEmpty()) {
newDocuments.addAll(documentManager.copyProxyAsDocument(proxyRefs,
parent.getRef(),true));
}
if (!docRefs.isEmpty()) {
newDocuments.addAll(documentManager.copy(docRefs, parent.getRef(),true));
}
if (destinationIsDeleted) {
for (DocumentModel d : newDocuments) {
setDeleteState(d);
}
}
documentManager.save();
if (sb.length() > 0) {
facesMessages.add(StatusMessage.Severity.WARN, sb.toString(), null);
}
return newDocuments;
}
protected boolean checkDeletedState(DocumentModel doc)
throws ClientException {
if (LifeCycleConstants.DELETED_STATE.equals(doc.getCurrentLifeCycleState())) {
return true;
}
if (doc.getAllowedStateTransitions().contains(
LifeCycleConstants.DELETE_TRANSITION)) {
return true;
}
return false;
}
protected void setDeleteState(DocumentModel doc) throws ClientException {
if (doc.getAllowedStateTransitions().contains(
LifeCycleConstants.DELETE_TRANSITION)) {
doc.followTransition(LifeCycleConstants.DELETE_TRANSITION);
}
}
protected void addWarnMessage(StringBuilder sb, DocumentModel doc)
throws ClientException {
if (sb.length() == 0) {
sb.append(resourcesAccessor.getMessages().get(
"document_no_deleted_state"));
sb.append("'").append(doc.getTitle()).append("'");
} else {
sb.append(", '").append(doc.getTitle()).append("'");
}
}
/**
* Check if the container is a publish space. If this is not the case, a
* proxy copied to it will be recreated as a new document.
*/
protected boolean isPublishSpace(DocumentModel container)
throws ClientException {
SchemaManager schemaManager;
try {
schemaManager = Framework.getService(SchemaManager.class);
} catch (Exception e) {
throw new ClientException(e);
}
Set<String> publishSpaces = null;
if (schemaManager != null) {
publishSpaces = schemaManager.getDocumentTypeNamesForFacet(FacetNames.PUBLISH_SPACE);
}
if (publishSpaces == null || publishSpaces.isEmpty()) {
publishSpaces = new HashSet<String>();
}
return publishSpaces.contains(container.getType());
}
/**
* Gets the parent document under the paste should be performed.
* <p>
* Rules:
* <p>
* In general the currentDocument is the parent. Exceptions to this rule:
* when the currentDocument is a domain or null. If Domain then content root
* is the parent. If null is passed, then the JCR root is taken as parent.
*/
protected DocumentModel getParent(DocumentModel currentDocument)
throws ClientException {
if (currentDocument.isFolder()) {
return currentDocument;
}
DocumentModelList parents = navigationContext.getCurrentPath();
for (int i = parents.size() - 1; i >= 0; i--) {
DocumentModel parent = parents.get(i);
if (parent.isFolder()) {
return parent;
}
}
return null;
}
@Factory(value = "isCurrentWorkListEmpty", scope = EVENT)
public boolean factoryForIsCurrentWorkListEmpty() {
return isWorkListEmpty();
}
public boolean isWorkListEmpty() {
return documentsListsManager.isWorkingListEmpty(getCurrentSelectedListName());
}
public String exportWorklistAsZip() throws ClientException {
return exportWorklistAsZip(documentsListsManager.getWorkingList(getCurrentSelectedListName()));
}
public String exportAllBlobsFromWorkingListAsZip() throws ClientException {
return exportWorklistAsZip();
}
public String exportMainBlobFromWorkingListAsZip() throws ClientException {
return exportWorklistAsZip();
}
public String exportWorklistAsZip(List<DocumentModel> documents)
throws ClientException {
return exportWorklistAsZip(documents, true);
}
public String exportWorklistAsZip(DocumentModel document)
throws ClientException {
return exportWorklistAsZip(
Arrays.asList(new DocumentModel[] { document }), true);
}
/**
* Checks if copy action is available in the context of the current
* Document.
* <p>
* Condition: the list of selected documents is not empty.
*/
public boolean getCanCopy() {
if (navigationContext.getCurrentDocument() == null) {
return false;
}
return !documentsListsManager.isWorkingListEmpty(DocumentsListsManager.CURRENT_DOCUMENT_SELECTION);
}
/**
* Checks if the Paste action is available in the context of the current
* Document. Conditions:
* <p>
* <ul>
* <li>list is not empty
* <li>user has the needed permissions on the current document
* <li>the content of the list can be added as children of the current
* document
* </ul>
*/
public boolean getCanPaste(String listName) throws ClientException {
DocumentModel currentDocument = navigationContext.getCurrentDocument();
if (documentsListsManager.isWorkingListEmpty(listName)
|| currentDocument == null) {
return false;
}
DocumentModel pasteTarget = getParent(navigationContext.getCurrentDocument());
if (pasteTarget == null) {
// parent may be unreachable (right inheritance blocked)
return false;
}
if (!documentManager.hasPermission(pasteTarget.getRef(),
SecurityConstants.ADD_CHILDREN)) {
return false;
} else {
// filter on allowed content types
// see if at least one doc can be pasted
// String pasteTypeName = clipboard.getClipboardDocumentType();
List<String> pasteTypesName = documentsListsManager.getWorkingListTypes(listName);
for (String pasteTypeName : pasteTypesName) {
if (typeManager.isAllowedSubType(pasteTypeName,
pasteTarget.getType(),
navigationContext.getCurrentDocument())) {
return true;
}
}
return false;
}
}
public boolean getCanPasteInside(String listName, DocumentModel document)
throws ClientException {
if (documentsListsManager.isWorkingListEmpty(listName)
|| document == null) {
return false;
}
if (!documentManager.hasPermission(document.getRef(),
SecurityConstants.ADD_CHILDREN)) {
return false;
} else {
// filter on allowed content types
// see if at least one doc can be pasted
// String pasteTypeName = clipboard.getClipboardDocumentType();
List<String> pasteTypesName = documentsListsManager.getWorkingListTypes(listName);
for (String pasteTypeName : pasteTypesName) {
if (typeManager.isAllowedSubType(pasteTypeName,
document.getType(),
navigationContext.getCurrentDocument())) {
return true;
}
}
return false;
}
}
/**
* Checks if the Move action is available in the context of the document
* document. Conditions:
* <p>
* <ul>
* <li>list is not empty
* <li>user has the needed permissions on the document
* <li>an element in the list can be removed from its folder and added as
* child of the current document
* </ul>
*/
public boolean getCanMoveInside(String listName, DocumentModel document)
throws ClientException {
if (documentsListsManager.isWorkingListEmpty(listName)
|| document == null) {
return false;
}
DocumentRef destFolderRef = document.getRef();
DocumentModel destFolder = document;
if (!documentManager.hasPermission(destFolderRef,
SecurityConstants.ADD_CHILDREN)) {
return false;
} else {
// filter on allowed content types
// see if at least one doc can be removed and pasted
for (DocumentModel docModel : documentsListsManager.getWorkingList(listName)) {
DocumentRef sourceFolderRef = docModel.getParentRef();
String sourceType = docModel.getType();
boolean canRemoveDoc = documentManager.hasPermission(
sourceFolderRef, SecurityConstants.REMOVE_CHILDREN);
boolean canPasteInCurrentFolder = typeManager.isAllowedSubType(
sourceType, destFolder.getType(),
navigationContext.getCurrentDocument());
boolean sameFolder = sourceFolderRef.equals(destFolderRef);
if (canRemoveDoc && canPasteInCurrentFolder && !sameFolder) {
return true;
}
}
return false;
}
}
/**
* Checks if the Move action is available in the context of the current
* Document. Conditions:
* <p>
* <ul>
* <li>list is not empty
* <li>user has the needed permissions on the current document
* <li>an element in the list can be removed from its folder and added as
* child of the current document
* </ul>
*/
public boolean getCanMove(String listName) throws ClientException {
DocumentModel currentDocument = navigationContext.getCurrentDocument();
return getCanMoveInside(listName, currentDocument);
}
public boolean getCanPasteWorkList() throws ClientException {
return getCanPaste(getCurrentSelectedListName());
}
public boolean getCanMoveWorkingList() throws ClientException {
return getCanMove(getCurrentSelectedListName());
}
public boolean getCanPasteFromClipboard() throws ClientException {
return getCanPaste(DocumentsListsManager.CLIPBOARD);
}
public boolean getCanPasteFromClipboardInside(DocumentModel document)
throws ClientException {
return getCanPasteInside(DocumentsListsManager.CLIPBOARD, document);
}
public boolean getCanMoveFromClipboardInside(DocumentModel document)
throws ClientException {
return getCanMoveInside(DocumentsListsManager.CLIPBOARD, document);
}
public void setCurrentSelectedList(String listId) {
if (listId != null && !listId.equals(currentSelectedList)) {
currentSelectedList = listId;
canEditSelectedDocs = null;
}
}
@RequestParameter()
String listIdToSelect;
public void selectList() {
if (listIdToSelect != null) {
setCurrentSelectedList(listIdToSelect);
}
}
public List<DocumentModel> getCurrentSelectedList() {
return documentsListsManager.getWorkingList(getCurrentSelectedListName());
}
public String getCurrentSelectedListName() {
if (currentSelectedList == null) {
if (!getAvailableLists().isEmpty()) {
setCurrentSelectedList(availableLists.get(0));
}
}
return currentSelectedList;
}
public String getCurrentSelectedListTitle() {
String title = null;
String listName = getCurrentSelectedListName();
if (listName != null) {
DocumentsListDescriptor desc = documentsListsManager.getWorkingListDescriptor(listName);
if (desc != null) {
title = desc.getTitle();
}
}
return title;
}
public List<String> getAvailableLists() {
if (availableLists == null) {
availableLists = documentsListsManager.getWorkingListNamesForCategory("CLIPBOARD");
}
return availableLists;
}
public List<DocumentsListDescriptor> getDescriptorsForAvailableLists() {
if (descriptorsForAvailableLists == null) {
List<String> availableLists = getAvailableLists();
descriptorsForAvailableLists = new ArrayList<DocumentsListDescriptor>();
for (String lName : availableLists) {
descriptorsForAvailableLists.add(documentsListsManager.getWorkingListDescriptor(lName));
}
}
return descriptorsForAvailableLists;
}
public List<Action> getActionsForCurrentList() {
String lstName = getCurrentSelectedListName();
if (isWorkListEmpty()) {
// we use cache here since this is a very common case ...
if (actionCache == null) {
actionCache = new HashMap<String, List<Action>>();
}
if (!actionCache.containsKey(lstName)) {
actionCache.put(lstName,
webActions.getActionsList(lstName + "_LIST"));
}
return actionCache.get(lstName);
} else {
return webActions.getActionsList(lstName + "_LIST");
}
}
public List<Action> getActionsForSelection() {
return webActions.getUnfiltredActionsList(DocumentsListsManager.CURRENT_DOCUMENT_SELECTION
+ "_LIST");
}
private void autoSelectCurrentList(String listName) {
previouslySelectedList = getCurrentSelectedListName();
setCurrentSelectedList(listName);
}
private void returnToPreviouslySelectedList() {
setCurrentSelectedList(previouslySelectedList);
}
public boolean getCanEditSelectedDocs() throws ClientException {
if (canEditSelectedDocs == null) {
if (getCurrentSelectedList().isEmpty()) {
canEditSelectedDocs = false;
} else {
final List<DocumentModel> selectedDocs = getCurrentSelectedList();
// check selected docs
canEditSelectedDocs = checkWritePerm(selectedDocs);
}
}
return canEditSelectedDocs;
}
@Deprecated
// no longer used by the user_clipboard.xhtml template
public boolean getCanEditListDocs(String listName) throws ClientException {
final List<DocumentModel> docs = documentsListsManager.getWorkingList(listName);
final boolean canEdit;
if (docs.isEmpty()) {
canEdit = false;
} else {
// check selected docs
canEdit = checkWritePerm(docs);
}
return canEdit;
}
private boolean checkWritePerm(List<DocumentModel> selectedDocs)
throws ClientException {
for (DocumentModel documentModel : selectedDocs) {
boolean canWrite = documentManager.hasPermission(
documentModel.getRef(), SecurityConstants.WRITE_PROPERTIES);
if (!canWrite) {
return false;
}
}
return true;
}
public boolean isCacheEnabled() {
if (!SeamCacheHelper.canUseSeamCache()) {
return false;
}
return isWorkListEmpty();
}
public String getCacheKey() {
return getCurrentSelectedListName() + "::"
+ localeSelector.getLocaleString();
}
public boolean isCacheEnabledForSelection() {
if (!SeamCacheHelper.canUseSeamCache()) {
return false;
}
return documentsListsManager.isWorkingListEmpty(DocumentsListsManager.CURRENT_DOCUMENT_SELECTION);
}
@Override
public String exportWorklistAsZip(List<DocumentModel> documents,
boolean exportAllBlobs) throws ClientException {
try {
FacesContext context = FacesContext.getCurrentInstance();
DocumentListZipExporter zipExporter = new DocumentListZipExporter();
File tmpFile = zipExporter.exportWorklistAsZip(documents,
documentManager, exportAllBlobs);
if (tmpFile == null) {
// empty zip file, do nothing
setFacesMessage("label.clipboard.emptyDocuments");
return null;
} else {
if (tmpFile.length() > Functions.getBigFileSizeLimit()) {
HttpServletRequest request = (HttpServletRequest) context.getExternalContext().getRequest();
request.setAttribute(
NXAuthConstants.DISABLE_REDIRECT_REQUEST_KEY, true);
String zipDownloadURL = BaseURL.getBaseURL(request);
zipDownloadURL += "nxbigzipfile" + "/";
zipDownloadURL += tmpFile.getName();
try {
context.getExternalContext().redirect(zipDownloadURL);
} catch (IOException e) {
log.error(
"Error while redirecting for big file downloader",
e);
}
} else {
ComponentUtils.downloadFile(context, "clipboard.zip",
tmpFile);
}
return "";
}
} catch (IOException io) {
throw ClientException.wrap(io);
}
}
}