org.opendaylight.controller.sample.kitchen.impl.KitchenServiceImpl.java Source code

Java tutorial

Introduction

Here is the source code for org.opendaylight.controller.sample.kitchen.impl.KitchenServiceImpl.java

Source

/*
 * Copyright (c) 2014, 2015 Brocade Communications Systems, Inc. and others.  All rights reserved.
 *
 * This program and the accompanying materials are made available under the
 * terms of the Eclipse Public License v1.0 which accompanies this distribution,
 * and is available at http://www.eclipse.org/legal/epl-v10.html
 */

package org.opendaylight.controller.sample.kitchen.impl;

import com.google.common.collect.ImmutableList;
import com.google.common.collect.ImmutableList.Builder;
import com.google.common.util.concurrent.AsyncFunction;
import com.google.common.util.concurrent.Futures;
import com.google.common.util.concurrent.JdkFutureAdapters;
import com.google.common.util.concurrent.ListenableFuture;
import com.google.common.util.concurrent.ListeningExecutorService;
import com.google.common.util.concurrent.MoreExecutors;
import java.util.List;
import java.util.concurrent.Callable;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.Executors;
import java.util.concurrent.Future;
import org.opendaylight.controller.md.sal.common.util.jmx.AbstractMXBean;
import org.opendaylight.controller.sample.kitchen.api.EggsType;
import org.opendaylight.controller.sample.kitchen.api.KitchenService;
import org.opendaylight.controller.sample.kitchen.api.KitchenServiceRuntimeMXBean;
import org.opendaylight.yang.gen.v1.http.netconfcentral.org.ns.toaster.rev091120.MakeToastInput;
import org.opendaylight.yang.gen.v1.http.netconfcentral.org.ns.toaster.rev091120.MakeToastInputBuilder;
import org.opendaylight.yang.gen.v1.http.netconfcentral.org.ns.toaster.rev091120.ToastType;
import org.opendaylight.yang.gen.v1.http.netconfcentral.org.ns.toaster.rev091120.ToasterListener;
import org.opendaylight.yang.gen.v1.http.netconfcentral.org.ns.toaster.rev091120.ToasterOutOfBread;
import org.opendaylight.yang.gen.v1.http.netconfcentral.org.ns.toaster.rev091120.ToasterRestocked;
import org.opendaylight.yang.gen.v1.http.netconfcentral.org.ns.toaster.rev091120.ToasterService;
import org.opendaylight.yang.gen.v1.http.netconfcentral.org.ns.toaster.rev091120.WheatBread;
import org.opendaylight.yangtools.yang.common.RpcError;
import org.opendaylight.yangtools.yang.common.RpcError.ErrorType;
import org.opendaylight.yangtools.yang.common.RpcResult;
import org.opendaylight.yangtools.yang.common.RpcResultBuilder;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

public class KitchenServiceImpl extends AbstractMXBean
        implements KitchenService, KitchenServiceRuntimeMXBean, ToasterListener {

    private static final Logger log = LoggerFactory.getLogger(KitchenServiceImpl.class);

    private final ToasterService toaster;

    private final ListeningExecutorService executor = MoreExecutors
            .listeningDecorator(Executors.newCachedThreadPool());

    private volatile boolean toasterOutOfBread;

    public KitchenServiceImpl(ToasterService toaster) {
        super("KitchenService", "toaster-consumer", null);
        this.toaster = toaster;
    }

    @Override
    public Future<RpcResult<Void>> makeBreakfast(EggsType eggsType, Class<? extends ToastType> toastType,
            int toastDoneness) {

        // Call makeToast and use JdkFutureAdapters to convert the Future to a ListenableFuture,
        // The OpendaylightToaster impl already returns a ListenableFuture so the conversion is
        // actually a no-op.

        ListenableFuture<RpcResult<Void>> makeToastFuture = JdkFutureAdapters
                .listenInPoolThread(makeToast(toastType, toastDoneness), executor);

        ListenableFuture<RpcResult<Void>> makeEggsFuture = makeEggs(eggsType);

        // Combine the 2 ListenableFutures into 1 containing a list of RpcResults.

        ListenableFuture<List<RpcResult<Void>>> combinedFutures = Futures
                .allAsList(ImmutableList.of(makeToastFuture, makeEggsFuture));

        // Then transform the RpcResults into 1.

        return Futures.transform(combinedFutures, new AsyncFunction<List<RpcResult<Void>>, RpcResult<Void>>() {
            @Override
            public ListenableFuture<RpcResult<Void>> apply(List<RpcResult<Void>> results) throws Exception {
                boolean atLeastOneSucceeded = false;
                Builder<RpcError> errorList = ImmutableList.builder();
                for (RpcResult<Void> result : results) {
                    if (result.isSuccessful()) {
                        atLeastOneSucceeded = true;
                    }

                    if (result.getErrors() != null) {
                        errorList.addAll(result.getErrors());
                    }
                }

                return Futures.immediateFuture(RpcResultBuilder.<Void>status(atLeastOneSucceeded)
                        .withRpcErrors(errorList.build()).build());
            }
        });
    }

    private ListenableFuture<RpcResult<Void>> makeEggs(EggsType eggsType) {

        return executor.submit(new Callable<RpcResult<Void>>() {

            @Override
            public RpcResult<Void> call() throws Exception {

                // We don't actually do anything here - just return a successful result.
                return RpcResultBuilder.<Void>success().build();
            }
        });
    }

    private Future<RpcResult<Void>> makeToast(Class<? extends ToastType> toastType, int toastDoneness) {

        if (toasterOutOfBread) {
            log.info("We're out of toast but we can make eggs");
            return Futures.immediateFuture(RpcResultBuilder.<Void>success().withWarning(ErrorType.APPLICATION,
                    "partial-operation", "Toaster is out of bread but we can make you eggs").build());
        }

        // Access the ToasterService to make the toast.

        MakeToastInput toastInput = new MakeToastInputBuilder().setToasterDoneness((long) toastDoneness)
                .setToasterToastType(toastType).build();

        return toaster.makeToast(toastInput);
    }

    @Override
    public Boolean makeScrambledWithWheat() {
        try {
            // This call has to block since we must return a result to the JMX client.
            RpcResult<Void> result = makeBreakfast(EggsType.SCRAMBLED, WheatBread.class, 2).get();
            if (result.isSuccessful()) {
                log.info("makeBreakfast succeeded");
            } else {
                log.warn("makeBreakfast failed: " + result.getErrors());
            }

            return result.isSuccessful();

        } catch (InterruptedException | ExecutionException e) {
            log.warn("An error occurred while maing breakfast: " + e);
        }

        return Boolean.FALSE;
    }

    /**
     * Implemented from the ToasterListener interface.
     */
    @Override
    public void onToasterOutOfBread(ToasterOutOfBread notification) {
        log.info("ToasterOutOfBread notification");
        toasterOutOfBread = true;
    }

    /**
     * Implemented from the ToasterListener interface.
     */
    @Override
    public void onToasterRestocked(ToasterRestocked notification) {
        log.info("ToasterRestocked notification - amountOfBread: " + notification.getAmountOfBread());
        toasterOutOfBread = false;
    }
}