/* * (C) Copyright 2012 Nuxeo SA (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: * Anahide Tchertchian * Antoine Taillefer */ package org.nuxeo.ecm.webapp.contentbrowser; import static org.jboss.seam.ScopeType.CONVERSATION; import static org.jboss.seam.ScopeType.EVENT; import java.io.Serializable; import java.util.ArrayList; import java.util.Arrays; import java.util.Collections; import java.util.List; 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.Observer; import org.jboss.seam.annotations.Scope; import org.jboss.seam.annotations.intercept.BypassInterceptors; 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.DocumentRef; import org.nuxeo.ecm.core.api.IdRef; import org.nuxeo.ecm.core.api.VersionModel; import org.nuxeo.ecm.platform.contentview.jsf.ContentView; import org.nuxeo.ecm.platform.contentview.seam.ContentViewActions; import org.nuxeo.ecm.platform.forms.layout.api.BuiltinModes; import org.nuxeo.ecm.platform.query.api.PageProvider; import org.nuxeo.ecm.platform.query.api.PageSelection; import org.nuxeo.ecm.platform.types.adapter.TypeInfo; import org.nuxeo.ecm.platform.ui.web.api.NavigationContext; import org.nuxeo.ecm.platform.ui.web.cache.LRUCachingMap; import org.nuxeo.ecm.webapp.documentsLists.DocumentsListsManager; import org.nuxeo.ecm.webapp.helpers.EventNames; /** * Manages document listings rendering. * * @author Anahide Tchertchian */ @Name("documentListingActions") @Scope(CONVERSATION) public class DocumentListingActionsBean implements Serializable { private static final long serialVersionUID = 1L; private static final Log log = LogFactory.getLog(DocumentListingActionsBean.class); public static String DEFAULT_LISTING_LAYOUT = "document_listing"; @In(create = true) protected transient NavigationContext navigationContext; /** @since 5.6 */ @In(create = true, required = false) protected transient CoreSession documentManager; @In(create = true) protected transient ContentViewActions contentViewActions; @In(required = false, create = true) protected transient DocumentsListsManager documentsListsManager; // only store 20 entries that cache chosen layout for a given document protected LRUCachingMap<String, String> docTolistings = new LRUCachingMap<String, String>( 20); protected String currentListingLayoutName = null; protected List<String> currentAvailableListingLayoutNames = null; // API for current layout in listing mode /** * @deprecated this information is now held by content views */ @Deprecated public String getLayoutForDocument(DocumentModel doc) { if (doc != null) { String id = doc.getId(); if (docTolistings.containsKey(id)) { return docTolistings.get(id); } List<String> availableLayouts = getAvailableLayoutsForDocument(doc); if (availableLayouts != null && !availableLayouts.isEmpty()) { return availableLayouts.get(0); } } return DEFAULT_LISTING_LAYOUT; } /** * @deprecated this information is now held by content views */ @Deprecated public void setLayoutForDocument(DocumentModel doc, String layoutName) { if (doc == null) { log.error("Cannot set listing layout for null document"); return; } String id = doc.getId(); docTolistings.put(id, layoutName); } /** * @deprecated this information is now held by content views */ @Deprecated @Factory(value = "currentListingLayoutName", scope = EVENT) public String getLayoutForCurrentDocument() { if (currentListingLayoutName == null) { DocumentModel currentDocument = navigationContext.getCurrentDocument(); currentListingLayoutName = getLayoutForDocument(currentDocument); } return currentListingLayoutName; } /** * @deprecated this information is now held by content views */ @Deprecated public void setLayoutForCurrentDocument(String layoutName) { DocumentModel currentDocument = navigationContext.getCurrentDocument(); setLayoutForDocument(currentDocument, layoutName); currentListingLayoutName = layoutName; } /** * @deprecated this information is now held by content views */ @Deprecated public List<String> getAvailableLayoutsForDocument(DocumentModel doc) { if (doc == null) { return Collections.emptyList(); } TypeInfo typeInfo = doc.getAdapter(TypeInfo.class); String[] layoutNames = typeInfo.getLayouts(BuiltinModes.LISTING, null); List<String> res = new ArrayList<String>(); if (layoutNames != null && layoutNames.length > 0) { res.addAll(Arrays.asList(layoutNames)); } else { res.add(DEFAULT_LISTING_LAYOUT); } return res; } /** * @deprecated this information is now held by content views */ @Deprecated @Factory(value = "currentAvailableListingLayoutNames", scope = EVENT) public List<String> getAvailableLayoutsForCurrentDocument() { if (currentAvailableListingLayoutNames == null) { DocumentModel currentDocument = navigationContext.getCurrentDocument(); currentAvailableListingLayoutNames = getAvailableLayoutsForDocument(currentDocument); } return currentAvailableListingLayoutNames; } /** * @deprecated this information is now held by content views */ @Observer(value = { EventNames.USER_ALL_DOCUMENT_TYPES_SELECTION_CHANGED }, create = false) @BypassInterceptors @Deprecated public void documentChanged() { currentListingLayoutName = null; currentAvailableListingLayoutNames = null; } // API for AJAX selection in listings of content views @SuppressWarnings("unchecked") protected List<DocumentModel> getCurrentPageDocuments(String contentViewName) throws ClientException { List<DocumentModel> documents = null; ContentView cView = contentViewActions.getContentView(contentViewName); if (cView != null) { PageProvider<?> cProvider = cView.getCurrentPageProvider(); if (cProvider != null) { List<?> items = cProvider.getCurrentPage(); try { documents = (List<DocumentModel>) items; } catch (Exception e) { throw new ClientException(e); } } } return documents; } public void processSelectPage(String contentViewName, String listName, Boolean selection) throws ClientException { List<DocumentModel> documents = getCurrentPageDocuments(contentViewName); if (documents != null) { String lName = (listName == null) ? DocumentsListsManager.CURRENT_DOCUMENT_SELECTION : listName; if (Boolean.TRUE.equals(selection)) { documentsListsManager.addToWorkingList(lName, documents); } else { documentsListsManager.removeFromWorkingList(lName, documents); } } } /** * Handle complete table selection event after having ensured that the * navigation context stills points to currentDocumentRef to protect against * browsers' back button errors * * @throws ClientException if currentDocRef is not a valid document */ public void checkCurrentDocAndProcessSelectPage(String contentViewName, String listName, Boolean selection, String currentDocRef) throws ClientException { DocumentRef currentDocumentRef = new IdRef(currentDocRef); if (!currentDocumentRef.equals(navigationContext.getCurrentDocument().getRef())) { navigationContext.navigateToRef(currentDocumentRef); } processSelectPage(contentViewName, listName, selection); } public void processSelectRow(String docRef, String contentViewName, String listName, Boolean selection) throws ClientException { List<DocumentModel> documents = getCurrentPageDocuments(contentViewName); DocumentModel doc = null; if (documents != null) { for (DocumentModel pagedDoc : documents) { if (pagedDoc.getRef().toString().equals(docRef)) { doc = pagedDoc; break; } } } if (doc == null) { log.error(String.format( "could not find doc '%s' in the current page of " + "content view page provider '%s'", docRef, contentViewName)); return; } String lName = (listName == null) ? DocumentsListsManager.CURRENT_DOCUMENT_SELECTION : listName; if (Boolean.TRUE.equals(selection)) { documentsListsManager.addToWorkingList(lName, doc); } else { documentsListsManager.removeFromWorkingList(lName, doc); } } /** * Handle row selection event after having ensured that the navigation * context stills points to currentDocumentRef to protect against browsers' * back button errors * * @throws ClientException if currentDocRef is not a valid document */ public void checkCurrentDocAndProcessSelectRow(String docRef, String providerName, String listName, Boolean selection, String requestedCurrentDocRef) throws ClientException { DocumentRef requestedCurrentDocumentRef = new IdRef( requestedCurrentDocRef); DocumentRef currentDocumentRef = null; DocumentModel currentDocument = navigationContext.getCurrentDocument(); if (currentDocument != null) { currentDocumentRef = currentDocument.getRef(); } if (!requestedCurrentDocumentRef.equals(currentDocumentRef)) { navigationContext.navigateToRef(requestedCurrentDocumentRef); } processSelectRow(docRef, providerName, listName, selection); } /** * Handle version row selection event after having ensured that the * navigation context stills points to currentDocumentRef to protect against * browsers' back button errors. * * @param versionModelSelection the version model selection * @param requestedCurrentDocRef the requested current doc ref * @throws ClientException if currentDocRef is not a valid document * * @since 5.6 */ public void checkCurrentDocAndProcessVersionSelectRow( PageSelection<VersionModel> versionModelSelection, String requestedCurrentDocRef) throws ClientException { DocumentRef requestedCurrentDocumentRef = new IdRef( requestedCurrentDocRef); DocumentRef currentDocumentRef = null; DocumentModel currentDocument = navigationContext.getCurrentDocument(); if (currentDocument != null) { currentDocumentRef = currentDocument.getRef(); } if (!requestedCurrentDocumentRef.equals(currentDocumentRef)) { navigationContext.navigateToRef(requestedCurrentDocumentRef); } processVersionSelectRow(versionModelSelection); } /** * Processes the version selection row. * * @param versionModelSelection the version model selection * @throws ClientException the client exception */ protected final void processVersionSelectRow( PageSelection<VersionModel> versionModelSelection) throws ClientException { DocumentModel currentDocument = navigationContext.getCurrentDocument(); if (currentDocument == null) { throw new ClientException( "Cannot process version select row since current document is null."); } DocumentModel version = documentManager.getDocumentWithVersion( currentDocument.getRef(), versionModelSelection.getData()); if (version == null) { throw new ClientException( "Cannot process version select row since selected version document is null."); } if (Boolean.TRUE.equals(versionModelSelection.isSelected())) { documentsListsManager.addToWorkingList( DocumentsListsManager.CURRENT_VERSION_SELECTION, version); } else { documentsListsManager.removeFromWorkingList( DocumentsListsManager.CURRENT_VERSION_SELECTION, version); } } }