/*
 * Copyright 2019, 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.examples.todolist.repository;

import com.google.common.collect.ImmutableSet;
import io.spine.examples.todolist.TaskId;
import io.spine.examples.todolist.c.events.TaskCompleted;
import io.spine.examples.todolist.c.events.TaskCreated;
import io.spine.examples.todolist.c.events.TaskDeleted;
import io.spine.examples.todolist.c.events.TaskDescriptionUpdated;
import io.spine.examples.todolist.c.events.TaskDraftCreated;
import io.spine.examples.todolist.c.events.TaskDueDateUpdated;
import io.spine.examples.todolist.c.events.TaskPriorityUpdated;
import io.spine.examples.todolist.c.events.TaskReopened;
import io.spine.examples.todolist.q.projection.TaskView;
import io.spine.examples.todolist.q.projection.TaskViewProjection;
import io.spine.server.projection.ProjectionRepository;

/**
 * Repository for the {@link TaskViewProjection}.
 */
public class TaskViewRepository
        extends ProjectionRepository<TaskId, TaskViewProjection, TaskView> {

    @Override
    public void onRegistered() {
        super.onRegistered();
        reroute();
    }

    private void reroute() {
        eventRouting().route(TaskCreated.class,
                             (message, context) -> ImmutableSet.of(message.getId()));
        eventRouting().route(TaskDeleted.class,
                             (message, context) -> ImmutableSet.of(message.getTaskId()));
        eventRouting().route(TaskCompleted.class,
                             (message, context) -> ImmutableSet.of(message.getTaskId()));
        eventRouting().route(TaskDraftCreated.class,
                             (message, context) -> ImmutableSet.of(message.getId()));
        eventRouting().route(TaskDescriptionUpdated.class,
                             (message, context) -> ImmutableSet.of(message.getTaskId()));
        eventRouting().route(TaskDueDateUpdated.class,
                             (message, context) -> ImmutableSet.of(message.getTaskId()));
        eventRouting().route(TaskReopened.class,
                             (message, context) -> ImmutableSet.of(message.getTaskId()));
        eventRouting().route(TaskPriorityUpdated.class,
                             (message, context) -> ImmutableSet.of(message.getTaskId()));
    }
}

@@ -1101,16 +1101,51 @@
 bleSet;%0A
+import io.spine.base.EventMessage;%0A
 import i
@@ -1178,16 +1178,16 @@
 TaskId;%0A
-
 import i
@@ -1841,16 +1841,53 @@
 itory;%0A%0A
+import java.util.function.Function;%0A%0A
 /**%0A * R
@@ -2190,169 +2190,173 @@
     
-eventRouting().route(TaskCreated.class,%0A                             (message, context) -%3E ImmutableSet.of(message.getId()));%0A        eventRouting().route
+toSingleProjection(TaskCreated.class, TaskCreated::getId);%0A        toSingleProjection(TaskDeleted.class, TaskDeleted::getTaskId);%0A        toSingleProjection
 (Task
-De
+Comp
 lete
@@ -2367,84 +2367,24 @@
 ass,
-%0A                             (message, context) -%3E ImmutableSet.of(message.
+ TaskCompleted::
 getT
@@ -2380,35 +2380,32 @@
 leted::getTaskId
-())
 );%0A        event
@@ -2403,125 +2403,158 @@
     
-eventRouting().route(TaskCompleted.class,%0A                             (message, context) -%3E ImmutableSet.of(message.
+toSingleProjection(TaskDraftCreated.class, TaskDraftCreated::getId);%0A        toSingleProjection(TaskDescriptionUpdated.class, TaskDescriptionUpdated::
 getT
@@ -2550,35 +2550,32 @@
 dated::getTaskId
-())
 );%0A        event
@@ -2573,656 +2573,813 @@
     
-eventRouting().route(TaskDraftCreated.class,%0A                             (message, context) -%3E ImmutableSet.of(message.getId()));%0A        eventRouting().route(TaskDescriptionUpdated.class,
+toSingleProjection(TaskDueDateUpdated.class, TaskDueDateUpdated::getTaskId);%0A        toSingleProjection(TaskReopened.class, TaskReopened::getTaskId);%0A        toSingleProjection(TaskPriorityUpdated.class, TaskPriorityUpdated::getTaskId);
 %0A    
+%7D%0A%0A
     
+/**%0A
      
-                (message, context) -%3E ImmutableSet.of(message.getTaskId()));
+* Reroutes events of the specified class to the projection with ID specified by the second%0A     * parameter.%0A     *%0A     * @param eventClass
 %0A    
+ *
     
-eventRouting().route(TaskDueDateUpdated.class,%0A                             (message, context) -%3E ImmutableSet.of(message.getTaskId()));%0A        eventRouting().route(TaskReopened.class,%0A                             (message, context) -%3E ImmutableSet.of(message.getTaskId()));%0A        eventRouting().route(TaskPriorityUpdated.class,%0A                            
+     class of event to reroute%0A     * @param fn%0A     *         function to obtain a task ID from the specified event type%0A     * @param %3CE%3E%0A     *         type of event to reroute%0A     */%0A    private %3CE extends EventMessage%3E void toSingleProjection(Class%3CE%3E eventClass,%0A                                                             Function%3CE, TaskId%3E fn) %7B%0A        eventRouting().route(eventClass,
  (me
@@ -3417,26 +3417,24 @@
 .of(
-message.getTaskId(
+fn.apply(message
 )));
@@ -3440,10 +3440,11 @@
 ;%0A    %7D%0A
+%0A
 %7D%0A

Refactor event rerouting.