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 com.google.common.collect.ImmutableList;
12 import com.google.common.collect.ImmutableList.Builder;
13 import com.google.common.util.concurrent.AsyncFunction;
14 import com.google.common.util.concurrent.Futures;
15 import com.google.common.util.concurrent.JdkFutureAdapters;
16 import com.google.common.util.concurrent.ListenableFuture;
17 import com.google.common.util.concurrent.ListeningExecutorService;
18 import com.google.common.util.concurrent.MoreExecutors;
19 import java.util.List;
20 import java.util.concurrent.Callable;
21 import java.util.concurrent.ExecutionException;
22 import java.util.concurrent.Executors;
23 import java.util.concurrent.Future;
24 import org.opendaylight.controller.md.sal.common.util.jmx.AbstractMXBean;
25 import org.opendaylight.controller.sample.kitchen.api.EggsType;
26 import org.opendaylight.controller.sample.kitchen.api.KitchenService;
27 import org.opendaylight.controller.sample.kitchen.api.KitchenServiceRuntimeMXBean;
28 import org.opendaylight.yang.gen.v1.http.netconfcentral.org.ns.toaster.rev091120.MakeToastInput;
29 import org.opendaylight.yang.gen.v1.http.netconfcentral.org.ns.toaster.rev091120.MakeToastInputBuilder;
30 import org.opendaylight.yang.gen.v1.http.netconfcentral.org.ns.toaster.rev091120.ToastType;
31 import org.opendaylight.yang.gen.v1.http.netconfcentral.org.ns.toaster.rev091120.ToasterListener;
32 import org.opendaylight.yang.gen.v1.http.netconfcentral.org.ns.toaster.rev091120.ToasterOutOfBread;
33 import org.opendaylight.yang.gen.v1.http.netconfcentral.org.ns.toaster.rev091120.ToasterRestocked;
34 import org.opendaylight.yang.gen.v1.http.netconfcentral.org.ns.toaster.rev091120.ToasterService;
35 import org.opendaylight.yang.gen.v1.http.netconfcentral.org.ns.toaster.rev091120.WheatBread;
36 import org.opendaylight.yangtools.yang.common.RpcError;
37 import org.opendaylight.yangtools.yang.common.RpcError.ErrorType;
38 import org.opendaylight.yangtools.yang.common.RpcResult;
39 import org.opendaylight.yangtools.yang.common.RpcResultBuilder;
40 import org.slf4j.Logger;
41 import org.slf4j.LoggerFactory;
43 public class KitchenServiceImpl extends AbstractMXBean
44 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 super("KitchenService", "toaster-consumer", null);
57 this.toaster = toaster;
61 public Future<RpcResult<Void>> makeBreakfast( EggsType eggsType, Class<? extends ToastType> toastType,
64 // Call makeToast and use JdkFutureAdapters to convert the Future to a ListenableFuture,
65 // The OpendaylightToaster impl already returns a ListenableFuture so the conversion is
68 ListenableFuture<RpcResult<Void>> makeToastFuture = JdkFutureAdapters.listenInPoolThread(
69 makeToast( toastType, toastDoneness ), executor );
71 ListenableFuture<RpcResult<Void>> makeEggsFuture = makeEggs( eggsType );
73 // Combine the 2 ListenableFutures into 1 containing a list of RpcResults.
75 ListenableFuture<List<RpcResult<Void>>> combinedFutures =
76 Futures.allAsList( ImmutableList.of( makeToastFuture, makeEggsFuture ) );
78 // Then transform the RpcResults into 1.
80 return Futures.transform( combinedFutures,
81 new AsyncFunction<List<RpcResult<Void>>,RpcResult<Void>>() {
83 public ListenableFuture<RpcResult<Void>> apply( List<RpcResult<Void>> results )
85 boolean atLeastOneSucceeded = false;
86 Builder<RpcError> errorList = ImmutableList.builder();
87 for( RpcResult<Void> result: results ) {
88 if( result.isSuccessful() ) {
89 atLeastOneSucceeded = true;
92 if( result.getErrors() != null ) {
93 errorList.addAll( result.getErrors() );
97 return Futures.immediateFuture(
98 RpcResultBuilder.<Void> status( atLeastOneSucceeded )
99 .withRpcErrors( errorList.build() ).build() );
104 private ListenableFuture<RpcResult<Void>> makeEggs( EggsType eggsType ) {
106 return executor.submit( new Callable<RpcResult<Void>>() {
109 public RpcResult<Void> call() throws Exception {
111 // We don't actually do anything here - just return a successful result.
112 return RpcResultBuilder.<Void> success().build();
117 private Future<RpcResult<Void>> makeToast( Class<? extends ToastType> toastType,
118 int toastDoneness ) {
120 if( toasterOutOfBread )
122 log.info( "We're out of toast but we can make eggs" );
123 return Futures.immediateFuture( RpcResultBuilder.<Void> success()
124 .withWarning( ErrorType.APPLICATION, "partial-operation",
125 "Toaster is out of bread but we can make you eggs" ).build() );
128 // Access the ToasterService to make the toast.
130 MakeToastInput toastInput = new MakeToastInputBuilder()
131 .setToasterDoneness( (long) toastDoneness )
132 .setToasterToastType( toastType )
135 return toaster.makeToast( toastInput );
139 public Boolean makeScrambledWithWheat() {
141 // This call has to block since we must return a result to the JMX client.
142 RpcResult<Void> result = makeBreakfast( EggsType.SCRAMBLED, WheatBread.class, 2 ).get();
143 if( result.isSuccessful() ) {
144 log.info( "makeBreakfast succeeded" );
146 log.warn( "makeBreakfast failed: " + result.getErrors() );
149 return result.isSuccessful();
151 } catch( InterruptedException | ExecutionException e ) {
152 log.warn( "An error occurred while maing breakfast: " + e );
155 return Boolean.FALSE;
159 * Implemented from the ToasterListener interface.
162 public void onToasterOutOfBread( ToasterOutOfBread notification ) {
163 log.info( "ToasterOutOfBread notification" );
164 toasterOutOfBread = true;
168 * Implemented from the ToasterListener interface.
171 public void onToasterRestocked( ToasterRestocked notification ) {
172 log.info( "ToasterRestocked notification - amountOfBread: " + notification.getAmountOfBread() );
173 toasterOutOfBread = false;