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