001/* 002 * Copyright 2015 DuraSpace, Inc. 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 */ 016package org.fcrepo.kernel.modeshape.observer.eventmappings; 017 018import static org.fcrepo.kernel.modeshape.utils.UncheckedFunction.uncheck; 019import static org.fcrepo.kernel.modeshape.observer.FedoraEventImpl.from; 020import static org.modeshape.jcr.api.JcrConstants.JCR_CONTENT; 021import static org.slf4j.LoggerFactory.getLogger; 022import static java.util.Arrays.asList; 023import static java.util.stream.Collectors.groupingBy; 024import static java.util.stream.Stream.empty; 025import static java.util.stream.Stream.of; 026import static javax.jcr.observation.Event.PROPERTY_ADDED; 027import static javax.jcr.observation.Event.PROPERTY_CHANGED; 028import static javax.jcr.observation.Event.PROPERTY_REMOVED; 029 030import java.util.List; 031import java.util.function.Function; 032import java.util.stream.Stream; 033 034import javax.jcr.RepositoryException; 035import javax.jcr.observation.Event; 036 037import org.fcrepo.kernel.api.exception.RepositoryRuntimeException; 038import org.fcrepo.kernel.api.observer.FedoraEvent; 039import org.fcrepo.kernel.modeshape.observer.FedoraEventImpl; 040 041import org.slf4j.Logger; 042 043/** 044 * Maps all JCR {@link Event}s concerning one JCR node to one {@link FedoraEvent}. Adds the types of those JCR events 045 * together to calculate the final type of the emitted FedoraEvent. 046 * 047 * @author ajs6f 048 * @author acoburn 049 * @since Feb 27, 2014 050 */ 051public class AllNodeEventsOneEvent implements InternalExternalEventMapper { 052 053 private static final List<Integer> PROPERTY_EVENT_TYPES = asList(PROPERTY_ADDED, PROPERTY_CHANGED, 054 PROPERTY_REMOVED); 055 056 private final static Logger LOGGER = getLogger(AllNodeEventsOneEvent.class); 057 058 /** 059 * Extracts an identifier from a JCR {@link Event} by building an id from nodepath and user to collapse multiple 060 * events from repository mutations 061 */ 062 private static final Function<Event, String> EXTRACT_NODE_ID = uncheck(ev -> { 063 final FedoraEvent event = from(ev); 064 final String id = event.getPath() + "-" + event.getUserID(); 065 LOGGER.debug("Sorting an event by identifier: {}", id); 066 return id; 067 }); 068 069 @Override 070 public Stream<FedoraEvent> apply(final Stream<Event> events) { 071 // first, index all the events by path-userID and then flatMap over that list of values 072 // each of which returns either a singleton Stream or an empty Stream. The final result 073 // will be a concatenated Stream of FedoraEvent objects. 074 return events.collect(groupingBy(EXTRACT_NODE_ID)).entrySet().stream().flatMap(entry -> { 075 final List<Event> evts = entry.getValue(); 076 if (!evts.isEmpty()) { 077 // build a FedoraEvent from the first JCR Event 078 final FedoraEvent fedoraEvent = from(evts.get(0)); 079 evts.stream().forEach(evt -> { 080 // add types to the FedoraEvent from the JCR Event 081 fedoraEvent.addType(FedoraEventImpl.valueOf(evt.getType())); 082 try { 083 // add appropriate properties to the FedoraEvent from the JCR Event 084 if (evt.getPath().contains(JCR_CONTENT)) { 085 fedoraEvent.addProperty("fedora:hasContent"); 086 } 087 if (PROPERTY_EVENT_TYPES.contains(evt.getType())) { 088 final String eventPath = evt.getPath(); 089 fedoraEvent.addProperty(eventPath.substring(eventPath.lastIndexOf('/') + 1)); 090 } else { 091 LOGGER.trace("Not adding non-event property: {}, {}", fedoraEvent, evt); 092 } 093 } catch (final RepositoryException ex) { 094 throw new RepositoryRuntimeException(ex); 095 } 096 }); 097 return of(fedoraEvent); 098 } 099 return empty(); 100 }); 101 } 102}