/** * $Id: StatisticsLoggingConsumer.java 4440 2009-10-10 19:03:27Z mdiggory $ * $URL: https://scm.dspace.org/svn/repo/dspace/tags/dspace-1.6.2/dspace-stats/src/main/java/org/dspace/statistics/StatisticsLoggingConsumer.java $ * ************************************************************************* * Copyright (c) 2002-2009, DuraSpace. All rights reserved * Licensed under the DuraSpace Foundation License. * * A copy of the DuraSpace License has been included in this * distribution and is available at: http://scm.dspace.org/svn/repo/licenses/LICENSE.txt */ package org.dspace.statistics; import java.sql.SQLException; import java.util.ArrayList; import java.util.HashSet; import java.util.List; import java.util.Map; import java.util.Set; import org.dspace.content.Collection; import org.dspace.content.Community; 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; /** * StatisticsLogging Consumer for SolrLogger which captures Create, Update * and Delete Events on DSpace Objects. * * All usage-events will be updated to capture changes to e.g. * the owning collection * * @author kevinvandevelde at atmire.com * @author ben at atmrie.com */ public class StatisticsLoggingConsumer implements Consumer { private Set<String> toRemoveQueries = null; public void initialize() throws Exception { } // TODO: checkout whether moving of collections, communities and bitstreams works // TODO: use async threaded consumer as this might require some processing time // TODO: we might be able to improve the performance: changing the collection will trigger 4 update commands public void consume(Context ctx, Event event) throws Exception { if (toRemoveQueries == null) { toRemoveQueries = new HashSet<String>(); } int dsoId = event.getSubjectID(); int dsoType = event.getSubjectType(); int eventType = event.getEventType(); // Check if we are deleting something if (eventType == Event.DELETE) { // First make sure we delete everything for this dso String query = "id:" + dsoId + " AND type:" + dsoType; toRemoveQueries.add(query); } else if (eventType == Event.MODIFY && dsoType == Constants.ITEM) { // We have a modified item check for a withdraw/reinstate } else if (eventType == Event.MODIFY_METADATA && event.getSubjectType() == Constants.ITEM) { Item item = Item.find(ctx, event.getSubjectID()); String updateQuery = "id:" + item.getID() + " AND type:" + item.getType(); Map<String, List<String>> indexedValues = SolrLogger.queryField( updateQuery, null, null); // Get all the metadata Map metadataStorageInfo = SolrLogger.getMetadataStorageInfo(); List<String> storageFieldList = new ArrayList<String>(); List<List<Object>> storageValuesList = new ArrayList<List<Object>>(); for (Object storageField : metadataStorageInfo.keySet()) { String[] metadataFieldInfo = String.valueOf( metadataStorageInfo.get(storageField)).split("\\."); List<Object> values = new ArrayList<Object>(); List<Object> valuesLow = new ArrayList<Object>(); for (int i = 0; i < item.getMetadata(metadataFieldInfo[0], metadataFieldInfo[1], metadataFieldInfo[2], Item.ANY).length; i++) { values.add(item.getMetadata(metadataFieldInfo[0], metadataFieldInfo[1], metadataFieldInfo[2], Item.ANY)[i].value); valuesLow.add(item.getMetadata(metadataFieldInfo[0], metadataFieldInfo[1], metadataFieldInfo[2], Item.ANY)[i].value.toLowerCase()); } List<String> indexedVals = indexedValues.get("" + storageField); boolean update = true; if (values.containsAll(indexedVals) && values.size() == indexedVals.size()) update = false; if (update) { storageFieldList.add((String) storageField); storageFieldList.add(storageField + "_search"); storageValuesList.add(values); storageValuesList.add(valuesLow); } } SolrLogger.update(updateQuery, "replace", storageFieldList, storageValuesList); } if (eventType == Event.ADD && dsoType == Constants.COLLECTION && event.getObject(ctx) instanceof Item) { // We are mapping a new item make sure that the owning collection is // updated Item newItem = (Item) event.getObject(ctx); String updateQuery = "id: " + newItem.getID() + " AND type:" + newItem.getType(); List<String> fieldNames = new ArrayList<String>(); List<List<Object>> valuesList = new ArrayList<List<Object>>(); fieldNames.add("owningColl"); fieldNames.add("owningComm"); List<Object> valsList = new ArrayList<Object>(); valsList.add(dsoId); valuesList.add(valsList); valsList = new ArrayList<Object>(); valsList.addAll(findOwningCommunities(ctx, dsoId)); valuesList.add(valsList); // Now make sure we also update the communities SolrLogger.update(updateQuery, "addOne", fieldNames, valuesList); } else if (eventType == Event.REMOVE && dsoType == Constants.COLLECTION && event.getObject(ctx) instanceof Item) { // Unmapping items Item newItem = (Item) event.getObject(ctx); String updateQuery = "id: " + newItem.getID() + " AND type:" + newItem.getType(); List<String> fieldNames = new ArrayList<String>(); List<List<Object>> valuesList = new ArrayList<List<Object>>(); fieldNames.add("owningColl"); fieldNames.add("owningComm"); List<Object> valsList = new ArrayList<Object>(); valsList.add(dsoId); valuesList.add(valsList); valsList = new ArrayList<Object>(); valsList.addAll(findOwningCommunities(ctx, dsoId)); valuesList.add(valsList); SolrLogger.update(updateQuery, "remOne", fieldNames, valuesList); } } private List<Object> findOwningCommunities(Context context, int collId) throws SQLException { Collection coll = Collection.find(context, collId); List<Object> owningComms = new ArrayList<Object>(); for (int i = 0; i < coll.getCommunities().length; i++) { Community community = coll.getCommunities()[i]; findComms(community, owningComms); } return owningComms; } private void findComms(Community comm, List<Object> parentComms) throws SQLException { if (comm == null) return; if (!parentComms.contains(comm.getID())) parentComms.add(comm.getID()); findComms(comm.getParentCommunity(), parentComms); } public void end(Context ctx) throws Exception { if (toRemoveQueries != null) { for (String query : toRemoveQueries) { SolrLogger.removeIndex(query); } } // clean out toRemoveQueries toRemoveQueries = null; } public void finish(Context ctx) throws Exception { } }