Deprecated Rpcs and RpcErrors helper classes
[controller.git] / opendaylight / md-sal / samples / toaster-consumer / src / main / java / org / opendaylight / controller / sample / kitchen / impl / KitchenServiceImpl.java
1 package org.opendaylight.controller.sample.kitchen.impl;
2
3 import java.util.List;
4 import java.util.concurrent.Callable;
5 import java.util.concurrent.ExecutionException;
6 import java.util.concurrent.Executors;
7 import java.util.concurrent.Future;
8
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;
26
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;
35
36 public class KitchenServiceImpl implements KitchenService, KitchenServiceRuntimeMXBean, ToasterListener {
37
38     private static final Logger log = LoggerFactory.getLogger( KitchenServiceImpl.class );
39
40     private final ToasterService toaster;
41
42     private final ListeningExecutorService executor =
43                                    MoreExecutors.listeningDecorator( Executors.newCachedThreadPool() );
44
45     private volatile boolean toasterOutOfBread;
46
47     public KitchenServiceImpl(ToasterService toaster) {
48         this.toaster = toaster;
49     }
50
51     @Override
52     public Future<RpcResult<Void>> makeBreakfast( EggsType eggsType, Class<? extends ToastType> toastType,
53                                                   int toastDoneness ) {
54
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
57         // actually a no-op.
58
59         ListenableFuture<RpcResult<Void>> makeToastFuture = JdkFutureAdapters.listenInPoolThread(
60                 makeToast( toastType, toastDoneness ), executor );
61
62         ListenableFuture<RpcResult<Void>> makeEggsFuture = makeEggs( eggsType );
63
64         // Combine the 2 ListenableFutures into 1 containing a list of RpcResults.
65
66         ListenableFuture<List<RpcResult<Void>>> combinedFutures =
67                 Futures.allAsList( ImmutableList.of( makeToastFuture, makeEggsFuture ) );
68
69         // Then transform the RpcResults into 1.
70
71         return Futures.transform( combinedFutures,
72             new AsyncFunction<List<RpcResult<Void>>,RpcResult<Void>>() {
73                 @Override
74                 public ListenableFuture<RpcResult<Void>> apply( List<RpcResult<Void>> results )
75                                                                                  throws Exception {
76                     boolean atLeastOneSucceeded = false;
77                     Builder<RpcError> errorList = ImmutableList.builder();
78                     for( RpcResult<Void> result: results ) {
79                         if( result.isSuccessful() ) {
80                             atLeastOneSucceeded = true;
81                         }
82
83                         if( result.getErrors() != null ) {
84                             errorList.addAll( result.getErrors() );
85                         }
86                     }
87
88                     return Futures.immediateFuture(
89                               RpcResultBuilder.<Void> status( atLeastOneSucceeded )
90                                               .withRpcErrors( errorList.build() ).build() );
91                 }
92         } );
93     }
94
95     private ListenableFuture<RpcResult<Void>> makeEggs( EggsType eggsType ) {
96
97         return executor.submit( new Callable<RpcResult<Void>>() {
98
99             @Override
100             public RpcResult<Void> call() throws Exception {
101
102                 // We don't actually do anything here - just return a successful result.
103                 return RpcResultBuilder.<Void> success().build();
104             }
105         } );
106     }
107
108     private Future<RpcResult<Void>> makeToast( Class<? extends ToastType> toastType,
109                                                int toastDoneness ) {
110
111         if( toasterOutOfBread )
112         {
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() );
117         }
118
119         // Access the ToasterService to make the toast.
120
121         MakeToastInput toastInput = new MakeToastInputBuilder()
122             .setToasterDoneness( (long) toastDoneness )
123             .setToasterToastType( toastType )
124             .build();
125
126         return toaster.makeToast( toastInput );
127     }
128
129     @Override
130     public Boolean makeScrambledWithWheat() {
131         try {
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" );
136             } else {
137                 log.warn( "makeBreakfast failed: " + result.getErrors() );
138             }
139
140             return result.isSuccessful();
141
142         } catch( InterruptedException | ExecutionException e ) {
143             log.warn( "An error occurred while maing breakfast: " + e );
144         }
145
146         return Boolean.FALSE;
147     }
148
149     /**
150      * Implemented from the ToasterListener interface.
151      */
152     @Override
153     public void onToasterOutOfBread( ToasterOutOfBread notification ) {
154         log.info( "ToasterOutOfBread notification" );
155         toasterOutOfBread = true;
156     }
157
158     /**
159      * Implemented from the ToasterListener interface.
160      */
161     @Override
162     public void onToasterRestocked( ToasterRestocked notification ) {
163         log.info( "ToasterRestocked notification - amountOfBread: " + notification.getAmountOfBread() );
164         toasterOutOfBread = false;
165     }
166 }