001/* 002 * (C) Copyright 2010 Nuxeo SA (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 * Olivier Grisel 018 */ 019package org.nuxeo.ecm.platform.categorization.listener; 020 021import java.util.ArrayList; 022import java.util.Arrays; 023import java.util.HashSet; 024import java.util.LinkedHashSet; 025import java.util.List; 026import java.util.Set; 027 028import org.apache.commons.logging.Log; 029import org.apache.commons.logging.LogFactory; 030import org.nuxeo.common.collections.ScopeType; 031import org.nuxeo.common.collections.ScopedMap; 032import org.nuxeo.ecm.core.api.CoreSession; 033import org.nuxeo.ecm.core.api.DocumentModel; 034import org.nuxeo.ecm.core.api.event.DocumentEventTypes; 035import org.nuxeo.ecm.core.event.Event; 036import org.nuxeo.ecm.core.event.EventBundle; 037import org.nuxeo.ecm.core.event.EventContext; 038import org.nuxeo.ecm.core.event.PostCommitEventListener; 039import org.nuxeo.ecm.core.event.impl.DocumentEventContext; 040import org.nuxeo.ecm.platform.categorization.service.DocumentCategorizationService; 041import org.nuxeo.runtime.api.Framework; 042 043/** 044 * Base default implementation of an asynchronous event listener that runs the document categorization service. 045 * 046 * @author ogrisel@nuxeo.com 047 */ 048public class DocumentCategorizationAsyncListener implements PostCommitEventListener { 049 050 protected static final Log log = LogFactory.getLog(DocumentCategorizationAsyncListener.class); 051 052 protected static final String ALLREADY_CATEGORIZED_FLAG = DocumentCategorizationAsyncListener.class.getName(); 053 054 // to be overridden in derived classes 055 protected Set<String> eventNames = new HashSet<String>(Arrays.asList(DocumentEventTypes.DOCUMENT_CREATED, 056 DocumentEventTypes.DOCUMENT_UPDATED)); 057 058 protected DocumentCategorizationService service; 059 060 public void handleEvent(EventBundle events) { 061 // collect ids of documents to analyze while filtering duplicated doc 062 // ids 063 Set<DocumentModel> collectedDocuments = new LinkedHashSet<DocumentModel>(events.size()); 064 for (Event event : events) { 065 if (!eventNames.contains(event.getName())) { 066 continue; 067 } 068 EventContext ctx = event.getContext(); 069 if (ctx.hasProperty(ALLREADY_CATEGORIZED_FLAG)) { 070 // avoid infinite loops with event listeners triggering them 071 // selves on the same documents 072 continue; 073 } 074 if (ctx instanceof DocumentEventContext) { 075 DocumentEventContext docCtx = (DocumentEventContext) ctx; 076 DocumentModel doc = docCtx.getSourceDocument(); 077 if (doc != null) { 078 ScopedMap contextData = doc.getContextData(); 079 contextData.putScopedValue(ScopeType.REQUEST, ALLREADY_CATEGORIZED_FLAG, Boolean.TRUE); 080 collectedDocuments.add(doc); 081 } 082 } 083 } 084 if (!collectedDocuments.isEmpty()) { 085 // assume all document stem from the same repo, with the 086 // save session 087 CoreSession session = collectedDocuments.iterator().next().getCoreSession(); 088 DocumentCategorizationService categorizationService = Framework.getService( 089 DocumentCategorizationService.class); 090 List<DocumentModel> documents = categorizationService.updateCategories( 091 new ArrayList<DocumentModel>(collectedDocuments)); 092 if (!documents.isEmpty()) { 093 session.saveDocuments(documents.toArray(new DocumentModel[documents.size()])); 094 session.save(); 095 } 096 } 097 } 098 099}