/* * BrowseConsumer.java * * Version: $Revision: 3736 $ * * Date: $Date: 2009-04-24 04:16:22 +0000 (Fri, 24 Apr 2009) $ * * Copyright (c) 2002-2009, The DSpace Foundation. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are * met: * * - Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * - Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * - Neither the name of the DSpace Foundation nor the names of its * contributors may be used to endorse or promote products derived from * this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR * TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE * USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH * DAMAGE. */ package org.dspace.browse; import java.util.HashSet; import java.util.Set; import org.apache.log4j.Logger; import org.dspace.content.DSpaceObject; import org.dspace.content.Item; import org.dspace.core.Constants; import org.dspace.core.Context; import org.dspace.event.Consumer; import org.dspace.event.Event; /** * Class for updating browse system from content events. * Prototype: only Item events recognized. * * XXX FIXME NOTE: The Browse Consumer is INCOMPLETE because the * deletion of an Item CANNOT be implemented as an event consumer: * When an Item is deleted, the browse tables must be updated * immediately, within the same transaction, to maintain referential * consistency. It cannot be handled in an Event consumer since by * definition that runs after the transaction is committed. * Perhaps this can be addressed if the Browse system is replaced. * * To handle create/modify events: accumulate Sets of Items to be added * and updated out of the event stream. Process them in endEvents() * filter out update requests for Items that were just created. * * Recommended filter: Item+Create|Modify|Modify_Metadata:Collection+Add|Remove * * @version $Revision: 3736 $ */ public class BrowseConsumer implements Consumer { /** log4j logger */ private static Logger log = Logger.getLogger(BrowseConsumer.class); // items to be updated in browse index private Set<Item> toUpdate = null; public void initialize() throws Exception { } public void consume(Context ctx, Event event) throws Exception { if(toUpdate == null) { toUpdate = new HashSet<Item>(); } log.debug("consume() evaluating event: " + event.toString()); int st = event.getSubjectType(); int et = event.getEventType(); switch (st) { // If an Item is created or its metadata is modified.. case Constants.ITEM: if(et == Event.MODIFY_METADATA || et == Event.CREATE) { DSpaceObject subj = event.getSubject(ctx); if (subj != null) { log.debug("consume() adding event to update queue: " + event.toString()); toUpdate.add((Item)subj); } } break; // track ADD and REMOVE from collections, that changes browse index. case Constants.COLLECTION: if (event.getObjectType() == Constants.ITEM && (et == Event.ADD || et == Event.REMOVE)) { Item obj = (Item)event.getObject(ctx); if (obj != null) { log.debug("consume() adding event to update queue: " + event.toString()); toUpdate.add(obj); } } break; default: log.debug("consume() ingnoring event: " + event.toString()); } } public void end(Context ctx) throws Exception { if (toUpdate != null) { // Update/Add items for (Item i : toUpdate) { // FIXME: there is an exception handling problem here try { // Update browse indices ctx.turnOffAuthorisationSystem(); IndexBrowse ib = new IndexBrowse(ctx); ib.indexItem(i); ctx.restoreAuthSystemState(); } catch (BrowseException e) { log.error("caught exception: ", e); //throw new SQLException(e.getMessage()); } if (log.isDebugEnabled()) log.debug("Updated browse indices for Item id=" + String.valueOf(i.getID()) + ", hdl=" + i.getHandle()); } // NOTE: Removed items are necessarily handled inline (ugh). // browse updates wrote to the DB, so we have to commit. ctx.getDBConnection().commit(); } // clean out toUpdate toUpdate = null; } public void finish(Context ctx) { } }