Merge "Bug 5974: He plugin: Don't invalidate session context that is not valid."
[openflowplugin.git] / openflowplugin-impl / src / main / java / org / opendaylight / openflowplugin / impl / statistics / services / direct / AbstractDirectStatisticsService.java
1 /*
2  * Copyright (c) 2015 Cisco 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.openflowplugin.impl.statistics.services.direct;
10
11 import com.google.common.base.Function;
12 import com.google.common.base.Preconditions;
13 import com.google.common.util.concurrent.AsyncFunction;
14 import com.google.common.util.concurrent.Futures;
15 import com.google.common.util.concurrent.ListenableFuture;
16 import java.util.List;
17 import java.util.concurrent.Future;
18 import javax.annotation.Nullable;
19 import org.opendaylight.openflowplugin.api.openflow.device.DeviceContext;
20 import org.opendaylight.openflowplugin.api.openflow.device.RequestContextStack;
21 import org.opendaylight.openflowplugin.api.openflow.device.Xid;
22 import org.opendaylight.openflowplugin.api.openflow.md.util.OpenflowVersion;
23 import org.opendaylight.openflowplugin.impl.services.AbstractMultipartService;
24 import org.opendaylight.openflowplugin.impl.services.RequestInputUtils;
25 import org.opendaylight.yang.gen.v1.urn.opendaylight.direct.statistics.rev160511.StoreStatsGrouping;
26 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.common.types.rev130731.MultipartType;
27 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.protocol.rev130731.MultipartReply;
28 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.protocol.rev130731.OfHeader;
29 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.protocol.rev130731.multipart.request.MultipartRequestBody;
30 import org.opendaylight.yangtools.yang.common.RpcResult;
31 import org.opendaylight.yangtools.yang.common.RpcResultBuilder;
32
33 /**
34  * The abstract direct statistics service.
35  * This abstract service provides wrappers and tools for all other derived statistics services.
36  *
37  * @param <I> the input type parameter
38  * @param <O> the output type parameter
39  */
40 public abstract class AbstractDirectStatisticsService<I extends StoreStatsGrouping, O> extends AbstractMultipartService<I> {
41
42     private final Function<RpcResult<List<MultipartReply>>, RpcResult<O>> resultTransformFunction =
43             new Function<RpcResult<List<MultipartReply>>, RpcResult<O>>() {
44                 @Nullable
45                 @Override
46                 public RpcResult<O> apply(@Nullable RpcResult<List<MultipartReply>> input) {
47                     Preconditions.checkNotNull(input);
48                     final O reply = buildReply(input.getResult(), input.isSuccessful());
49                     return RpcResultBuilder.success(reply).build();
50                 }
51             };
52
53     private final AsyncFunction<RpcResult<O>, RpcResult<O>> resultStoreFunction =
54             new AsyncFunction<RpcResult<O>, RpcResult<O>>() {
55                 @Nullable
56                 @Override
57                 public ListenableFuture<RpcResult<O>> apply(@Nullable RpcResult<O> input) throws Exception {
58                     Preconditions.checkNotNull(input);
59
60                     if (input.isSuccessful()) {
61                         storeStatistics(input.getResult());
62                         getTxFacade().submitTransaction(); // TODO: If submitTransaction will ever return future, chain it
63                     }
64
65                     return Futures.immediateFuture(input);
66                 }
67             };
68
69     private final MultipartType multipartType;
70     private final OpenflowVersion ofVersion = OpenflowVersion.get(getVersion());
71
72     /**
73      * Instantiates a new Abstract direct statistics service.
74      *
75      * @param multipartType       the multipart type
76      * @param requestContextStack the request context stack
77      * @param deviceContext       the device context
78      */
79     protected AbstractDirectStatisticsService(MultipartType multipartType, RequestContextStack requestContextStack, DeviceContext deviceContext) {
80         super(requestContextStack, deviceContext);
81         this.multipartType = multipartType;
82     }
83
84     /**
85      * Handle input and reply future.
86      *
87      * @param input the input
88      * @return the future
89      */
90     public Future<RpcResult<O>> handleAndReply(final I input) {
91         final ListenableFuture<RpcResult<List<MultipartReply>>> rpcReply = handleServiceCall(input);
92         ListenableFuture<RpcResult<O>> rpcResult = Futures.transform(rpcReply, resultTransformFunction);
93
94         if (Boolean.TRUE.equals(input.isStoreStats())) {
95             rpcResult = Futures.transform(rpcResult, resultStoreFunction);
96         }
97
98         return rpcResult;
99     }
100
101     @Override
102     protected OfHeader buildRequest(Xid xid, I input) throws Exception {
103         return RequestInputUtils.createMultipartHeader(multipartType, xid.getValue(), getVersion())
104                 .setMultipartRequestBody(buildRequestBody(input))
105                 .build();
106     }
107
108     /**
109      * Gets openflow version.
110      *
111      * @return the openflow version
112      */
113     protected OpenflowVersion getOfVersion() {
114         return ofVersion;
115     }
116
117     /**
118      * Build multipart request body.
119      *
120      * @param input the input
121      * @return the multipart request body
122      */
123     protected abstract MultipartRequestBody buildRequestBody(I input);
124
125     /**
126      * Build output from multipart reply input.
127      *
128      * @param input the input
129      * @return the output
130      */
131     protected abstract O buildReply(List<MultipartReply> input, boolean success);
132
133     /**
134      * Store statistics.
135      * TODO: Remove dependency on deviceContext from derived methods
136      * TODO: Return future, so we will be able to chain it
137      *
138      * @param output the output
139      * @throws Exception the exception
140      */
141     protected abstract void storeStatistics(O output) throws Exception;
142 }