1 package org.opendaylight.controller.sample.kitchen.impl;
4 import java.util.concurrent.Callable;
5 import java.util.concurrent.ExecutionException;
6 import java.util.concurrent.Executors;
7 import java.util.concurrent.Future;
9 import org.opendaylight.controller.config.yang.config.kitchen_service.impl.KitchenServiceRuntimeMXBean;
10 import org.opendaylight.controller.sample.kitchen.api.EggsType;
11 import org.opendaylight.controller.sample.kitchen.api.KitchenService;
12 import org.opendaylight.yang.gen.v1.http.netconfcentral.org.ns.toaster.rev091120.MakeToastInput;
13 import org.opendaylight.yang.gen.v1.http.netconfcentral.org.ns.toaster.rev091120.MakeToastInputBuilder;
14 import org.opendaylight.yang.gen.v1.http.netconfcentral.org.ns.toaster.rev091120.ToastType;
15 import org.opendaylight.yang.gen.v1.http.netconfcentral.org.ns.toaster.rev091120.ToasterListener;
16 import org.opendaylight.yang.gen.v1.http.netconfcentral.org.ns.toaster.rev091120.ToasterOutOfBread;
17 import org.opendaylight.yang.gen.v1.http.netconfcentral.org.ns.toaster.rev091120.ToasterRestocked;
18 import org.opendaylight.yang.gen.v1.http.netconfcentral.org.ns.toaster.rev091120.ToasterService;
19 import org.opendaylight.yang.gen.v1.http.netconfcentral.org.ns.toaster.rev091120.WheatBread;
20 import org.opendaylight.yangtools.yang.common.RpcError;
21 import org.opendaylight.yangtools.yang.common.RpcResult;
22 import org.opendaylight.yangtools.yang.common.RpcError.ErrorType;
23 import org.opendaylight.yangtools.yang.common.RpcResultBuilder;
24 import org.slf4j.Logger;
25 import org.slf4j.LoggerFactory;
27 import com.google.common.collect.ImmutableList;
28 import com.google.common.collect.ImmutableList.Builder;
29 import com.google.common.util.concurrent.AsyncFunction;
30 import com.google.common.util.concurrent.Futures;
31 import com.google.common.util.concurrent.JdkFutureAdapters;
32 import com.google.common.util.concurrent.ListenableFuture;
33 import com.google.common.util.concurrent.ListeningExecutorService;
34 import com.google.common.util.concurrent.MoreExecutors;
36 public class KitchenServiceImpl implements KitchenService, KitchenServiceRuntimeMXBean, ToasterListener {
38 private static final Logger log = LoggerFactory.getLogger( KitchenServiceImpl.class );
40 private final ToasterService toaster;
42 private final ListeningExecutorService executor =
43 MoreExecutors.listeningDecorator( Executors.newCachedThreadPool() );
45 private volatile boolean toasterOutOfBread;
47 public KitchenServiceImpl(ToasterService toaster) {
48 this.toaster = toaster;
52 public Future<RpcResult<Void>> makeBreakfast( EggsType eggsType, Class<? extends ToastType> toastType,
55 // Call makeToast and use JdkFutureAdapters to convert the Future to a ListenableFuture,
56 // The OpendaylightToaster impl already returns a ListenableFuture so the conversion is
59 ListenableFuture<RpcResult<Void>> makeToastFuture = JdkFutureAdapters.listenInPoolThread(
60 makeToast( toastType, toastDoneness ), executor );
62 ListenableFuture<RpcResult<Void>> makeEggsFuture = makeEggs( eggsType );
64 // Combine the 2 ListenableFutures into 1 containing a list of RpcResults.
66 ListenableFuture<List<RpcResult<Void>>> combinedFutures =
67 Futures.allAsList( ImmutableList.of( makeToastFuture, makeEggsFuture ) );
69 // Then transform the RpcResults into 1.
71 return Futures.transform( combinedFutures,
72 new AsyncFunction<List<RpcResult<Void>>,RpcResult<Void>>() {
74 public ListenableFuture<RpcResult<Void>> apply( List<RpcResult<Void>> results )
76 boolean atLeastOneSucceeded = false;
77 Builder<RpcError> errorList = ImmutableList.builder();
78 for( RpcResult<Void> result: results ) {
79 if( result.isSuccessful() ) {
80 atLeastOneSucceeded = true;
83 if( result.getErrors() != null ) {
84 errorList.addAll( result.getErrors() );
88 return Futures.immediateFuture(
89 RpcResultBuilder.<Void> status( atLeastOneSucceeded )
90 .withRpcErrors( errorList.build() ).build() );
95 private ListenableFuture<RpcResult<Void>> makeEggs( EggsType eggsType ) {
97 return executor.submit( new Callable<RpcResult<Void>>() {
100 public RpcResult<Void> call() throws Exception {
102 // We don't actually do anything here - just return a successful result.
103 return RpcResultBuilder.<Void> success().build();
108 private Future<RpcResult<Void>> makeToast( Class<? extends ToastType> toastType,
109 int toastDoneness ) {
111 if( toasterOutOfBread )
113 log.info( "We're out of toast but we can make eggs" );
114 return Futures.immediateFuture( RpcResultBuilder.<Void> success()
115 .withWarning( ErrorType.APPLICATION, "partial-operation",
116 "Toaster is out of bread but we can make you eggs" ).build() );
119 // Access the ToasterService to make the toast.
121 MakeToastInput toastInput = new MakeToastInputBuilder()
122 .setToasterDoneness( (long) toastDoneness )
123 .setToasterToastType( toastType )
126 return toaster.makeToast( toastInput );
130 public Boolean makeScrambledWithWheat() {
132 // This call has to block since we must return a result to the JMX client.
133 RpcResult<Void> result = makeBreakfast( EggsType.SCRAMBLED, WheatBread.class, 2 ).get();
134 if( result.isSuccessful() ) {
135 log.info( "makeBreakfast succeeded" );
137 log.warn( "makeBreakfast failed: " + result.getErrors() );
140 return result.isSuccessful();
142 } catch( InterruptedException | ExecutionException e ) {
143 log.warn( "An error occurred while maing breakfast: " + e );
146 return Boolean.FALSE;
150 * Implemented from the ToasterListener interface.
153 public void onToasterOutOfBread( ToasterOutOfBread notification ) {
154 log.info( "ToasterOutOfBread notification" );
155 toasterOutOfBread = true;
159 * Implemented from the ToasterListener interface.
162 public void onToasterRestocked( ToasterRestocked notification ) {
163 log.info( "ToasterRestocked notification - amountOfBread: " + notification.getAmountOfBread() );
164 toasterOutOfBread = false;