001/* 002 * (C) Copyright 2018 Nuxeo (http://nuxeo.com/) and others. 003 * 004 * Licensed under the Apache License, Version 2.0 (the "License"); 005 * you may not use this file except in compliance with the License. 006 * You may obtain a copy of the License at 007 * 008 * http://www.apache.org/licenses/LICENSE-2.0 009 * 010 * Unless required by applicable law or agreed to in writing, software 011 * distributed under the License is distributed on an "AS IS" BASIS, 012 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 013 * See the License for the specific language governing permissions and 014 * limitations under the License. 015 * 016 * Contributors: 017 * Kevin Leturc <kleturc@nuxeo.com> 018 */ 019package org.nuxeo.ecm.core.trash; 020 021import static org.nuxeo.ecm.core.trash.TrashService.DOCUMENT_TRASHED; 022import static org.nuxeo.ecm.core.trash.TrashService.DOCUMENT_UNTRASHED; 023import static org.nuxeo.ecm.core.trash.TrashService.DISABLE_TRASH_RENAMING; 024 025import java.util.function.Consumer; 026 027import org.apache.commons.logging.Log; 028import org.apache.commons.logging.LogFactory; 029import org.nuxeo.ecm.core.api.CoreSession; 030import org.nuxeo.ecm.core.api.DocumentModel; 031import org.nuxeo.ecm.core.api.DocumentModelList; 032import org.nuxeo.ecm.core.event.Event; 033import org.nuxeo.ecm.core.event.EventBundle; 034import org.nuxeo.ecm.core.event.EventContext; 035import org.nuxeo.ecm.core.event.PostCommitFilteringEventListener; 036import org.nuxeo.ecm.core.event.impl.DocumentEventContext; 037import org.nuxeo.runtime.api.Framework; 038 039/** 040 * Listener for trashed state change events. 041 * <p> 042 * If event occurs on a folder, it will recurse on children to perform the same change if possible. 043 * 044 * @since 10.1 045 */ 046public class BulkTrashedStateChangeListener implements PostCommitFilteringEventListener { 047 048 public static final String SKIP_CHILDREN_PROCESSING_KEY = "skipChildrenForTrashedStageChange"; 049 050 private static final Log log = LogFactory.getLog(BulkTrashedStateChangeListener.class); 051 052 @Override 053 public boolean acceptEvent(Event event) { 054 EventContext ctx = event.getContext(); 055 return ctx instanceof DocumentEventContext && ((DocumentEventContext) ctx).getSourceDocument().isFolder() 056 && !Boolean.parseBoolean(String.valueOf(ctx.getProperty(SKIP_CHILDREN_PROCESSING_KEY))); 057 } 058 059 @Override 060 public void handleEvent(EventBundle events) { 061 if (events.containsEventName(DOCUMENT_TRASHED) || events.containsEventName(DOCUMENT_UNTRASHED)) { 062 for (Event event : events) { 063 if (DOCUMENT_TRASHED.equals(event.getName()) || DOCUMENT_UNTRASHED.equals(event.getName())) { 064 handleEvent(event); 065 } 066 } 067 } 068 } 069 070 protected void handleEvent(Event event) { 071 log.debug("Processing trashed state change in async listener"); 072 DocumentEventContext ctx = (DocumentEventContext) event.getContext(); 073 DocumentModel doc = ctx.getSourceDocument(); 074 CoreSession session = ctx.getCoreSession(); 075 if (session == null) { 076 log.error("Can not process trashed state change since session is null"); 077 return; 078 } 079 DocumentModelList children = session.getChildren(doc.getRef()); 080 TrashService trashService = Framework.getService(TrashService.class); 081 // TODO review the way we disable renaming when bulk operation will be done 082 Consumer<DocumentModel> trashOperation = DOCUMENT_TRASHED.equals(event.getName()) ? trashService::trashDocument 083 : trashService::untrashDocument; 084 for (DocumentModel child : children) { 085 // skip renaming 086 child.putContextData(DISABLE_TRASH_RENAMING, Boolean.TRUE); 087 trashOperation.accept(child); 088 089 } 090 } 091 092}