/*
 * Copyright 2018, TeamDev. All rights reserved.
 *
 * Redistribution and use in source and/or binary forms, with or without
 * modification, must retain the above copyright notice and the following
 * disclaimer.
 *
 * 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
 * OWNER 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 io.spine.server.entity;

import com.google.common.collect.ImmutableCollection;
import io.spine.annotation.SPI;
import io.spine.core.Event;

import java.util.Collection;
import java.util.Optional;

import static com.google.common.collect.ImmutableList.toImmutableList;

/**
 * A filter accepting {@link Event}s posted by a {@link Repository}.
 *
 * <p>A filter may {@linkplain #allowAll() allow any event}, reject certain types of events, or
 * change the event content.
 *
 * @author Dmytro Dashenkov
 * @apiNote This type is a {@link FunctionalInterface}, so that an event filter may be defined
 *          with a lambda expression.
 * @see EventWhiteList
 * @see EventBlackList
 * @see EventFieldFilter
 * @see CompositeEventFilter
 */
@SPI
@FunctionalInterface
public interface EventFilter {

    /**
     * Obtains an {@code EventFilter} which always returns the input event without any change.
     *
     * <p>The method acts as if
     * <pre>
     *     {@code
     *     static EventFilter allowAll() {
     *         return Optional::of;
     *     }
     *     }
     * </pre>
     *
     * @return a filter which allows any event to be published
     */
    static EventFilter allowAll() {
        return NoOpEventFilter.INSTANCE;
    }

    /**
     * Applies this filter to the given {@link Event}.
     *
     * @param event
     *         the event to apply the filter to
     * @return processed event or {@link Optional#empty()} if the event should not be posted
     * @apiNote This method may never return a present value or return a value not derived from
     *          the input event. See the implementations for the details for each case.
     */
    Optional<Event> filter(Event event);

    /**
     * Applies this filter to the given {@link Event}s in bulk.
     *
     * @param events
     *         the events to apply the filter to
     * @return non-empty filtering results for the given events
     * @apiNote This method should have the same behaviour in any descendant. Override this method
     *          <b>only</b> for performance improvement.
     */
    default ImmutableCollection<Event> filter(Collection<Event> events) {
        ImmutableCollection<Event> filteredEvents = events.stream()
                                                          .map(this::filter)
                                                          .filter(Optional::isPresent)
                                                          .map(Optional::get)
                                                          .collect(toImmutableList());
        return filteredEvents;
    }
}

@@ -1652,108 +1652,8 @@
 on.%0A
- * @see EventWhiteList%0A * @see EventBlackList%0A * @see EventFieldFilter%0A * @see CompositeEventFilter%0A
  */%0A

Remove implementation links from `EventFilter`.