/* * Licensed to DuraSpace under one or more contributor license agreements. * See the NOTICE file distributed with this work for additional information * regarding copyright ownership. * * DuraSpace licenses this file to you under the Apache License, * Version 2.0 (the "License"); you may not use this file except in * compliance with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.fcrepo.kernel.modeshape.observer.eventmappings; import static org.fcrepo.kernel.modeshape.utils.UncheckedFunction.uncheck; import static org.fcrepo.kernel.modeshape.observer.FedoraEventImpl.from; import static org.fcrepo.kernel.modeshape.observer.FedoraEventImpl.getResourceTypes; import static org.slf4j.LoggerFactory.getLogger; import static java.util.stream.Collectors.groupingBy; import static java.util.stream.Collectors.toSet; import static java.util.stream.Stream.empty; import static java.util.stream.Stream.of; import java.util.List; import java.util.function.Function; import java.util.stream.Stream; import javax.jcr.observation.Event; import org.fcrepo.kernel.api.observer.FedoraEvent; import org.fcrepo.kernel.modeshape.observer.FedoraEventImpl; import org.slf4j.Logger; /** * Maps all JCR {@link Event}s concerning one JCR node to one {@link FedoraEvent}. Adds the types of those JCR events * together to calculate the final type of the emitted FedoraEvent. * * @author ajs6f * @author acoburn * @since Feb 27, 2014 */ public class AllNodeEventsOneEvent implements InternalExternalEventMapper { private final static Logger LOGGER = getLogger(AllNodeEventsOneEvent.class); /** * Extracts an identifier from a JCR {@link Event} by building an id from nodepath and user to collapse multiple * events from repository mutations */ private static final Function<Event, String> EXTRACT_NODE_ID = uncheck(ev -> { final FedoraEvent event = from(ev); final String id = event.getPath() + "-" + event.getUserID(); LOGGER.debug("Sorting an event by identifier: {}", id); return id; }); @Override public Stream<FedoraEvent> apply(final Stream<Event> events) { // first, index all the events by path-userID and then flatMap over that list of values // each of which returns either a singleton Stream or an empty Stream. The final result // will be a concatenated Stream of FedoraEvent objects. return events.collect(groupingBy(EXTRACT_NODE_ID)).entrySet().stream().flatMap(entry -> { final List<Event> evts = entry.getValue(); if (!evts.isEmpty()) { // build a FedoraEvent from the first JCR Event final FedoraEvent fedoraEvent = from(evts.get(0)); evts.stream().skip(1).forEach(evt -> { // add types to the FedoraEvent from the subsequent JCR Events fedoraEvent.getTypes().add(FedoraEventImpl.valueOf(evt.getType())); fedoraEvent.getResourceTypes().addAll(getResourceTypes(evt).collect(toSet())); }); return of(fedoraEvent); } return empty(); }); } }