2 * Copyright (c) 2014, 2015 Brocade Communications Systems, Inc. and others. All rights reserved.
4 * This program and the accompanying materials are made available under the
5 * terms of the Eclipse Public License v1.0 which accompanies this distribution,
6 * and is available at http://www.eclipse.org/legal/epl-v10.html
9 package org.opendaylight.controller.sample.kitchen.impl;
11 import java.util.List;
12 import java.util.concurrent.Callable;
13 import java.util.concurrent.ExecutionException;
14 import java.util.concurrent.Executors;
15 import java.util.concurrent.Future;
17 import org.opendaylight.controller.config.yang.config.kitchen_service.impl.KitchenServiceRuntimeMXBean;
18 import org.opendaylight.controller.sample.kitchen.api.EggsType;
19 import org.opendaylight.controller.sample.kitchen.api.KitchenService;
20 import org.opendaylight.yang.gen.v1.http.netconfcentral.org.ns.toaster.rev091120.MakeToastInput;
21 import org.opendaylight.yang.gen.v1.http.netconfcentral.org.ns.toaster.rev091120.MakeToastInputBuilder;
22 import org.opendaylight.yang.gen.v1.http.netconfcentral.org.ns.toaster.rev091120.ToastType;
23 import org.opendaylight.yang.gen.v1.http.netconfcentral.org.ns.toaster.rev091120.ToasterListener;
24 import org.opendaylight.yang.gen.v1.http.netconfcentral.org.ns.toaster.rev091120.ToasterOutOfBread;
25 import org.opendaylight.yang.gen.v1.http.netconfcentral.org.ns.toaster.rev091120.ToasterRestocked;
26 import org.opendaylight.yang.gen.v1.http.netconfcentral.org.ns.toaster.rev091120.ToasterService;
27 import org.opendaylight.yang.gen.v1.http.netconfcentral.org.ns.toaster.rev091120.WheatBread;
28 import org.opendaylight.yangtools.yang.common.RpcError;
29 import org.opendaylight.yangtools.yang.common.RpcResult;
30 import org.opendaylight.yangtools.yang.common.RpcError.ErrorType;
31 import org.opendaylight.yangtools.yang.common.RpcResultBuilder;
32 import org.slf4j.Logger;
33 import org.slf4j.LoggerFactory;
35 import com.google.common.collect.ImmutableList;
36 import com.google.common.collect.ImmutableList.Builder;
37 import com.google.common.util.concurrent.AsyncFunction;
38 import com.google.common.util.concurrent.Futures;
39 import com.google.common.util.concurrent.JdkFutureAdapters;
40 import com.google.common.util.concurrent.ListenableFuture;
41 import com.google.common.util.concurrent.ListeningExecutorService;
42 import com.google.common.util.concurrent.MoreExecutors;
44 public class KitchenServiceImpl implements KitchenService, KitchenServiceRuntimeMXBean, ToasterListener {
46 private static final Logger log = LoggerFactory.getLogger( KitchenServiceImpl.class );
48 private final ToasterService toaster;
50 private final ListeningExecutorService executor =
51 MoreExecutors.listeningDecorator( Executors.newCachedThreadPool() );
53 private volatile boolean toasterOutOfBread;
55 public KitchenServiceImpl(ToasterService toaster) {
56 this.toaster = toaster;
60 public Future<RpcResult<Void>> makeBreakfast( EggsType eggsType, Class<? extends ToastType> toastType,
63 // Call makeToast and use JdkFutureAdapters to convert the Future to a ListenableFuture,
64 // The OpendaylightToaster impl already returns a ListenableFuture so the conversion is
67 ListenableFuture<RpcResult<Void>> makeToastFuture = JdkFutureAdapters.listenInPoolThread(
68 makeToast( toastType, toastDoneness ), executor );
70 ListenableFuture<RpcResult<Void>> makeEggsFuture = makeEggs( eggsType );
72 // Combine the 2 ListenableFutures into 1 containing a list of RpcResults.
74 ListenableFuture<List<RpcResult<Void>>> combinedFutures =
75 Futures.allAsList( ImmutableList.of( makeToastFuture, makeEggsFuture ) );
77 // Then transform the RpcResults into 1.
79 return Futures.transform( combinedFutures,
80 new AsyncFunction<List<RpcResult<Void>>,RpcResult<Void>>() {
82 public ListenableFuture<RpcResult<Void>> apply( List<RpcResult<Void>> results )
84 boolean atLeastOneSucceeded = false;
85 Builder<RpcError> errorList = ImmutableList.builder();
86 for( RpcResult<Void> result: results ) {
87 if( result.isSuccessful() ) {
88 atLeastOneSucceeded = true;
91 if( result.getErrors() != null ) {
92 errorList.addAll( result.getErrors() );
96 return Futures.immediateFuture(
97 RpcResultBuilder.<Void> status( atLeastOneSucceeded )
98 .withRpcErrors( errorList.build() ).build() );
103 private ListenableFuture<RpcResult<Void>> makeEggs( EggsType eggsType ) {
105 return executor.submit( new Callable<RpcResult<Void>>() {
108 public RpcResult<Void> call() throws Exception {
110 // We don't actually do anything here - just return a successful result.
111 return RpcResultBuilder.<Void> success().build();
116 private Future<RpcResult<Void>> makeToast( Class<? extends ToastType> toastType,
117 int toastDoneness ) {
119 if( toasterOutOfBread )
121 log.info( "We're out of toast but we can make eggs" );
122 return Futures.immediateFuture( RpcResultBuilder.<Void> success()
123 .withWarning( ErrorType.APPLICATION, "partial-operation",
124 "Toaster is out of bread but we can make you eggs" ).build() );
127 // Access the ToasterService to make the toast.
129 MakeToastInput toastInput = new MakeToastInputBuilder()
130 .setToasterDoneness( (long) toastDoneness )
131 .setToasterToastType( toastType )
134 return toaster.makeToast( toastInput );
138 public Boolean makeScrambledWithWheat() {
140 // This call has to block since we must return a result to the JMX client.
141 RpcResult<Void> result = makeBreakfast( EggsType.SCRAMBLED, WheatBread.class, 2 ).get();
142 if( result.isSuccessful() ) {
143 log.info( "makeBreakfast succeeded" );
145 log.warn( "makeBreakfast failed: " + result.getErrors() );
148 return result.isSuccessful();
150 } catch( InterruptedException | ExecutionException e ) {
151 log.warn( "An error occurred while maing breakfast: " + e );
154 return Boolean.FALSE;
158 * Implemented from the ToasterListener interface.
161 public void onToasterOutOfBread( ToasterOutOfBread notification ) {
162 log.info( "ToasterOutOfBread notification" );
163 toasterOutOfBread = true;
167 * Implemented from the ToasterListener interface.
170 public void onToasterRestocked( ToasterRestocked notification ) {
171 log.info( "ToasterRestocked notification - amountOfBread: " + notification.getAmountOfBread() );
172 toasterOutOfBread = false;