001/* 002 * (C) Copyright 2010 Nuxeo SAS (http://nuxeo.com/) and contributors. 003 * 004 * All rights reserved. This program and the accompanying materials 005 * are made available under the terms of the GNU Lesser General Public License 006 * (LGPL) version 2.1 which accompanies this distribution, and is available at 007 * http://www.gnu.org/licenses/lgpl.html 008 * 009 * This library is distributed in the hope that it will be useful, 010 * but WITHOUT ANY WARRANTY; without even the implied warranty of 011 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 012 * Lesser General Public License for more details. 013 * 014 * Contributors: 015 * Olivier Grisel 016 */ 017package org.nuxeo.ecm.platform.categorization.listener; 018 019import java.util.ArrayList; 020import java.util.Arrays; 021import java.util.HashSet; 022import java.util.LinkedHashSet; 023import java.util.List; 024import java.util.Set; 025 026import org.apache.commons.logging.Log; 027import org.apache.commons.logging.LogFactory; 028import org.nuxeo.common.collections.ScopeType; 029import org.nuxeo.common.collections.ScopedMap; 030import org.nuxeo.ecm.core.api.CoreSession; 031import org.nuxeo.ecm.core.api.DocumentModel; 032import org.nuxeo.ecm.core.api.event.DocumentEventTypes; 033import org.nuxeo.ecm.core.event.Event; 034import org.nuxeo.ecm.core.event.EventBundle; 035import org.nuxeo.ecm.core.event.EventContext; 036import org.nuxeo.ecm.core.event.PostCommitEventListener; 037import org.nuxeo.ecm.core.event.impl.DocumentEventContext; 038import org.nuxeo.ecm.platform.categorization.service.DocumentCategorizationService; 039import org.nuxeo.runtime.api.Framework; 040 041/** 042 * Base default implementation of an asynchronous event listener that runs the document categorization service. 043 * 044 * @author ogrisel@nuxeo.com 045 */ 046public class DocumentCategorizationAsyncListener implements PostCommitEventListener { 047 048 protected static final Log log = LogFactory.getLog(DocumentCategorizationAsyncListener.class); 049 050 protected static final String ALLREADY_CATEGORIZED_FLAG = DocumentCategorizationAsyncListener.class.getName(); 051 052 // to be overridden in derived classes 053 protected Set<String> eventNames = new HashSet<String>(Arrays.asList(DocumentEventTypes.DOCUMENT_CREATED, 054 DocumentEventTypes.DOCUMENT_UPDATED)); 055 056 protected DocumentCategorizationService service; 057 058 public void handleEvent(EventBundle events) { 059 // collect ids of documents to analyze while filtering duplicated doc 060 // ids 061 Set<DocumentModel> collectedDocuments = new LinkedHashSet<DocumentModel>(events.size()); 062 for (Event event : events) { 063 if (!eventNames.contains(event.getName())) { 064 continue; 065 } 066 EventContext ctx = event.getContext(); 067 if (ctx.hasProperty(ALLREADY_CATEGORIZED_FLAG)) { 068 // avoid infinite loops with event listeners triggering them 069 // selves on the same documents 070 continue; 071 } 072 if (ctx instanceof DocumentEventContext) { 073 DocumentEventContext docCtx = (DocumentEventContext) ctx; 074 DocumentModel doc = docCtx.getSourceDocument(); 075 if (doc != null) { 076 ScopedMap contextData = doc.getContextData(); 077 contextData.putScopedValue(ScopeType.REQUEST, ALLREADY_CATEGORIZED_FLAG, Boolean.TRUE); 078 collectedDocuments.add(doc); 079 } 080 } 081 } 082 if (!collectedDocuments.isEmpty()) { 083 // assume all document stem from the same repo, with the 084 // save session 085 CoreSession session = collectedDocuments.iterator().next().getCoreSession(); 086 DocumentCategorizationService categorizationService = Framework.getService( 087 DocumentCategorizationService.class); 088 List<DocumentModel> documents = categorizationService.updateCategories( 089 new ArrayList<DocumentModel>(collectedDocuments)); 090 if (!documents.isEmpty()) { 091 session.saveDocuments(documents.toArray(new DocumentModel[documents.size()])); 092 session.save(); 093 } 094 } 095 } 096 097}