1 package org.opendaylight.controller.sample.kitchen.impl;
3 import java.util.Arrays;
4 import java.util.Collections;
6 import java.util.concurrent.Callable;
7 import java.util.concurrent.ExecutionException;
8 import java.util.concurrent.Executors;
9 import java.util.concurrent.Future;
10 import org.opendaylight.controller.config.yang.config.kitchen_service.impl.KitchenServiceRuntimeMXBean;
11 import org.opendaylight.controller.sal.common.util.RpcErrors;
12 import org.opendaylight.controller.sal.common.util.Rpcs;
13 import org.opendaylight.controller.sample.kitchen.api.EggsType;
14 import org.opendaylight.controller.sample.kitchen.api.KitchenService;
15 import org.opendaylight.yang.gen.v1.http.netconfcentral.org.ns.toaster.rev091120.MakeToastInput;
16 import org.opendaylight.yang.gen.v1.http.netconfcentral.org.ns.toaster.rev091120.MakeToastInputBuilder;
17 import org.opendaylight.yang.gen.v1.http.netconfcentral.org.ns.toaster.rev091120.ToastType;
18 import org.opendaylight.yang.gen.v1.http.netconfcentral.org.ns.toaster.rev091120.ToasterListener;
19 import org.opendaylight.yang.gen.v1.http.netconfcentral.org.ns.toaster.rev091120.ToasterOutOfBread;
20 import org.opendaylight.yang.gen.v1.http.netconfcentral.org.ns.toaster.rev091120.ToasterRestocked;
21 import org.opendaylight.yang.gen.v1.http.netconfcentral.org.ns.toaster.rev091120.ToasterService;
22 import org.opendaylight.yang.gen.v1.http.netconfcentral.org.ns.toaster.rev091120.WheatBread;
23 import org.opendaylight.yangtools.yang.common.RpcError.ErrorSeverity;
24 import org.opendaylight.yangtools.yang.common.RpcError;
25 import org.opendaylight.yangtools.yang.common.RpcResult;
26 import org.opendaylight.yangtools.yang.common.RpcError.ErrorType;
27 import org.slf4j.Logger;
28 import org.slf4j.LoggerFactory;
30 import com.google.common.collect.ImmutableList;
31 import com.google.common.collect.ImmutableList.Builder;
32 import com.google.common.util.concurrent.AsyncFunction;
33 import com.google.common.util.concurrent.Futures;
34 import com.google.common.util.concurrent.JdkFutureAdapters;
35 import com.google.common.util.concurrent.ListenableFuture;
36 import com.google.common.util.concurrent.ListeningExecutorService;
37 import com.google.common.util.concurrent.MoreExecutors;
39 public class KitchenServiceImpl implements KitchenService, KitchenServiceRuntimeMXBean, ToasterListener {
41 private static final Logger log = LoggerFactory.getLogger( KitchenServiceImpl.class );
43 private final ToasterService toaster;
45 private final ListeningExecutorService executor =
46 MoreExecutors.listeningDecorator( Executors.newCachedThreadPool() );
48 private volatile boolean toasterOutOfBread;
50 public KitchenServiceImpl(ToasterService toaster) {
51 this.toaster = toaster;
55 public Future<RpcResult<Void>> makeBreakfast( EggsType eggsType, Class<? extends ToastType> toastType,
58 // Call makeToast and use JdkFutureAdapters to convert the Future to a ListenableFuture,
59 // The OpendaylightToaster impl already returns a ListenableFuture so the conversion is
62 ListenableFuture<RpcResult<Void>> makeToastFuture = JdkFutureAdapters.listenInPoolThread(
63 makeToast( toastType, toastDoneness ), executor );
65 ListenableFuture<RpcResult<Void>> makeEggsFuture = makeEggs( eggsType );
67 // Combine the 2 ListenableFutures into 1 containing a list of RpcResults.
69 ListenableFuture<List<RpcResult<Void>>> combinedFutures =
70 Futures.allAsList( ImmutableList.of( makeToastFuture, makeEggsFuture ) );
72 // Then transform the RpcResults into 1.
74 return Futures.transform( combinedFutures,
75 new AsyncFunction<List<RpcResult<Void>>,RpcResult<Void>>() {
77 public ListenableFuture<RpcResult<Void>> apply( List<RpcResult<Void>> results )
79 boolean atLeastOneSucceeded = false;
80 Builder<RpcError> errorList = ImmutableList.builder();
81 for( RpcResult<Void> result: results ) {
82 if( result.isSuccessful() ) {
83 atLeastOneSucceeded = true;
86 if( result.getErrors() != null ) {
87 errorList.addAll( result.getErrors() );
91 return Futures.immediateFuture(
92 Rpcs.<Void> getRpcResult( atLeastOneSucceeded, errorList.build() ) );
97 private ListenableFuture<RpcResult<Void>> makeEggs( EggsType eggsType ) {
99 return executor.submit( new Callable<RpcResult<Void>>() {
102 public RpcResult<Void> call() throws Exception {
104 // We don't actually do anything here - just return a successful result.
105 return Rpcs.<Void> getRpcResult( true, Collections.<RpcError>emptyList() );
110 private Future<RpcResult<Void>> makeToast( Class<? extends ToastType> toastType,
111 int toastDoneness ) {
113 if( toasterOutOfBread )
115 log.info( "We're out of toast but we can make eggs" );
116 return Futures.immediateFuture( Rpcs.<Void> getRpcResult( true,
117 Arrays.asList( RpcErrors.getRpcError( "", "partial-operation", null,
118 ErrorSeverity.WARNING,
119 "Toaster is out of bread but we can make you eggs",
120 ErrorType.APPLICATION, null ) ) ) );
123 // Access the ToasterService to make the toast.
125 MakeToastInput toastInput = new MakeToastInputBuilder()
126 .setToasterDoneness( (long) toastDoneness )
127 .setToasterToastType( toastType )
130 return toaster.makeToast( toastInput );
134 public Boolean makeScrambledWithWheat() {
136 // This call has to block since we must return a result to the JMX client.
137 RpcResult<Void> result = makeBreakfast( EggsType.SCRAMBLED, WheatBread.class, 2 ).get();
138 if( result.isSuccessful() ) {
139 log.info( "makeBreakfast succeeded" );
141 log.warn( "makeBreakfast failed: " + result.getErrors() );
144 return result.isSuccessful();
146 } catch( InterruptedException | ExecutionException e ) {
147 log.warn( "An error occurred while maing breakfast: " + e );
150 return Boolean.FALSE;
154 * Implemented from the ToasterListener interface.
157 public void onToasterOutOfBread( ToasterOutOfBread notification ) {
158 log.info( "ToasterOutOfBread notification" );
159 toasterOutOfBread = true;
163 * Implemented from the ToasterListener interface.
166 public void onToasterRestocked( ToasterRestocked notification ) {
167 log.info( "ToasterRestocked notification - amountOfBread: " + notification.getAmountOfBread() );
168 toasterOutOfBread = false;