/*
 * Copyright 2017, TeamDev Ltd. 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.server;

import io.spine.server.BoundedContext;
import io.spine.server.CommandService;
import io.spine.server.QueryService;
import io.spine.server.transport.GrpcContainer;

import java.io.IOException;

import static io.spine.server.event.EventStore.log;

/**
 * Sample gRPC server implementation.
 *
 * @author Illia Shepilov
 */
public class Server {

    private final int port;
    private final GrpcContainer grpcContainer;
    private final BoundedContext boundedContext;

    public Server(int port, BoundedContext boundedContext) {
        this.port = port;
        this.boundedContext = boundedContext;

        final CommandService commandService = initCommandService();
        final QueryService queryService = initQueryService();
        this.grpcContainer = initGrpcContainer(commandService, queryService);
    }

    private QueryService initQueryService() {
        final QueryService result = QueryService.newBuilder()
                                                .add(boundedContext)
                                                .build();
        return result;
    }

    private CommandService initCommandService() {
        final CommandService result = CommandService.newBuilder()
                                                    .add(boundedContext)
                                                    .build();
        return result;
    }

    private GrpcContainer initGrpcContainer(CommandService commandService,
                                            QueryService queryService) {
        final GrpcContainer result = GrpcContainer.newBuilder()
                                                  .addService(commandService)
                                                  .addService(queryService)
                                                  .setPort(port)
                                                  .build();
        return result;
    }

    /**
     * Starts the service.
     *
     * @throws IOException if unable to bind
     */
    public void start() throws IOException {
        startServer();
        log().info("Server started, listening to commands on the port {}.", port);
        awaitTermination();
    }

    private void startServer() throws IOException {
        grpcContainer.start();
        grpcContainer.addShutdownHook();
    }

    /**
     * Waits for the service to become terminated.
     */
    private void awaitTermination() {
        grpcContainer.awaitTermination();
    }

    /**
     * Initiates a shutdown of this {@code Server} instance.
     */
    public void shutdown() {
        grpcContainer.shutdown();
    }
}

@@ -1161,32 +1161,76 @@
 r.QueryService;%0A
+import io.spine.server.SubscriptionService;%0A
 import io.spine.
@@ -1843,76 +1843,501 @@
     
-this.grpcContainer = initGrpcContainer(commandService, queryService)
+final SubscriptionService subscriptionService = initSubscriptionService();%0A        this.grpcContainer = initGrpcContainer(commandService, queryService, subscriptionService);%0A    %7D%0A%0A    private SubscriptionService initSubscriptionService() %7B%0A        final SubscriptionService result = SubscriptionService.newBuilder()%0A                                                              .add(boundedContext)%0A                                                              .build();%0A        return result
 ;%0A  
@@ -3031,16 +3031,101 @@
 yService
+,%0A                                            SubscriptionService subscriptionService
 ) %7B%0A    
@@ -3330,32 +3330,115 @@
 e(queryService)%0A
+                                                  .addService(subscriptionService)%0A
                 

Deploy Subscription Service as well.