2 * Copyright (c) 2016 Cisco 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.openflowplugin.impl.util;
11 import com.google.common.annotations.VisibleForTesting;
12 import com.google.common.base.Function;
13 import com.google.common.base.Preconditions;
14 import com.google.common.collect.Iterables;
15 import java.util.ArrayList;
16 import java.util.Collection;
17 import java.util.Collections;
18 import java.util.Iterator;
19 import java.util.List;
20 import javax.annotation.Nullable;
21 import org.apache.commons.lang3.tuple.Pair;
22 import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.inventory.rev130819.FlowCapableNode;
23 import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.inventory.rev130819.meters.Meter;
24 import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.inventory.rev130819.meters.MeterKey;
25 import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.nodes.Node;
26 import org.opendaylight.yang.gen.v1.urn.opendaylight.meter.types.rev130918.MeterId;
27 import org.opendaylight.yang.gen.v1.urn.opendaylight.meter.types.rev130918.MeterRef;
28 import org.opendaylight.yang.gen.v1.urn.opendaylight.meters.service.rev160316.AddMetersBatchOutput;
29 import org.opendaylight.yang.gen.v1.urn.opendaylight.meters.service.rev160316.AddMetersBatchOutputBuilder;
30 import org.opendaylight.yang.gen.v1.urn.opendaylight.meters.service.rev160316.BatchMeterOutputListGrouping;
31 import org.opendaylight.yang.gen.v1.urn.opendaylight.meters.service.rev160316.RemoveMetersBatchOutput;
32 import org.opendaylight.yang.gen.v1.urn.opendaylight.meters.service.rev160316.RemoveMetersBatchOutputBuilder;
33 import org.opendaylight.yang.gen.v1.urn.opendaylight.meters.service.rev160316.UpdateMetersBatchOutput;
34 import org.opendaylight.yang.gen.v1.urn.opendaylight.meters.service.rev160316.UpdateMetersBatchOutputBuilder;
35 import org.opendaylight.yang.gen.v1.urn.opendaylight.meters.service.rev160316.batch.meter.output.list.grouping.BatchFailedMetersOutput;
36 import org.opendaylight.yang.gen.v1.urn.opendaylight.meters.service.rev160316.batch.meter.output.list.grouping.BatchFailedMetersOutputBuilder;
37 import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
38 import org.opendaylight.yangtools.yang.binding.KeyedInstanceIdentifier;
39 import org.opendaylight.yangtools.yang.common.RpcError;
40 import org.opendaylight.yangtools.yang.common.RpcResult;
41 import org.opendaylight.yangtools.yang.common.RpcResultBuilder;
44 * provides meter util methods
46 public final class MeterUtil {
48 private static final RpcResultBuilder<List<BatchFailedMetersOutput>> SUCCESSFUL_METER_OUTPUT_RPC_RESULT =
49 RpcResultBuilder.success(Collections.<BatchFailedMetersOutput>emptyList());
51 public static final Function<RpcResult<List<BatchFailedMetersOutput>>, RpcResult<AddMetersBatchOutput>> METER_ADD_TRANSFORM =
52 new Function<RpcResult<List<BatchFailedMetersOutput>>, RpcResult<AddMetersBatchOutput>>() {
55 public RpcResult<AddMetersBatchOutput> apply(@Nullable final RpcResult<List<BatchFailedMetersOutput>> batchMetersCumulatedResult) {
56 final AddMetersBatchOutput batchOutput = new AddMetersBatchOutputBuilder()
57 .setBatchFailedMetersOutput(batchMetersCumulatedResult.getResult()).build();
59 final RpcResultBuilder<AddMetersBatchOutput> resultBld =
60 createCumulativeRpcResult(batchMetersCumulatedResult, batchOutput);
61 return resultBld.build();
64 public static final Function<Pair<RpcResult<AddMetersBatchOutput>, RpcResult<Void>>, RpcResult<AddMetersBatchOutput>>
65 METER_ADD_COMPOSING_TRANSFORM = createComposingFunction();
67 public static final Function<RpcResult<List<BatchFailedMetersOutput>>, RpcResult<RemoveMetersBatchOutput>> METER_REMOVE_TRANSFORM =
68 new Function<RpcResult<List<BatchFailedMetersOutput>>, RpcResult<RemoveMetersBatchOutput>>() {
71 public RpcResult<RemoveMetersBatchOutput> apply(@Nullable final RpcResult<List<BatchFailedMetersOutput>> batchMetersCumulatedResult) {
72 final RemoveMetersBatchOutput batchOutput = new RemoveMetersBatchOutputBuilder()
73 .setBatchFailedMetersOutput(batchMetersCumulatedResult.getResult()).build();
75 final RpcResultBuilder<RemoveMetersBatchOutput> resultBld =
76 createCumulativeRpcResult(batchMetersCumulatedResult, batchOutput);
77 return resultBld.build();
80 public static final Function<Pair<RpcResult<RemoveMetersBatchOutput>, RpcResult<Void>>, RpcResult<RemoveMetersBatchOutput>>
81 METER_REMOVE_COMPOSING_TRANSFORM = createComposingFunction();
83 public static final Function<RpcResult<List<BatchFailedMetersOutput>>, RpcResult<UpdateMetersBatchOutput>> METER_UPDATE_TRANSFORM =
84 new Function<RpcResult<List<BatchFailedMetersOutput>>, RpcResult<UpdateMetersBatchOutput>>() {
87 public RpcResult<UpdateMetersBatchOutput> apply(@Nullable final RpcResult<List<BatchFailedMetersOutput>> batchMetersCumulatedResult) {
88 final UpdateMetersBatchOutput batchOutput = new UpdateMetersBatchOutputBuilder()
89 .setBatchFailedMetersOutput(batchMetersCumulatedResult.getResult()).build();
91 final RpcResultBuilder<UpdateMetersBatchOutput> resultBld =
92 createCumulativeRpcResult(batchMetersCumulatedResult, batchOutput);
93 return resultBld.build();
96 public static final Function<Pair<RpcResult<UpdateMetersBatchOutput>, RpcResult<Void>>, RpcResult<UpdateMetersBatchOutput>>
97 METER_UPDATE_COMPOSING_TRANSFORM = createComposingFunction();
100 throw new IllegalStateException("This class should not be instantiated.");
106 * @return instance identifier assembled for given node and meter
108 public static MeterRef buildMeterPath(final InstanceIdentifier<Node> nodePath, final MeterId meterId) {
109 final KeyedInstanceIdentifier<Meter, MeterKey> meterPath = nodePath
110 .augmentation(FlowCapableNode.class)
111 .child(Meter.class, new MeterKey(meterId));
113 return new MeterRef(meterPath);
116 public static <O> Function<List<RpcResult<O>>, RpcResult<List<BatchFailedMetersOutput>>> createCumulativeFunction(
117 final Iterable<? extends org.opendaylight.yang.gen.v1.urn.opendaylight.meter.types.rev130918.Meter> inputBatchMeters) {
118 return createCumulativeFunction(inputBatchMeters, Iterables.size(inputBatchMeters));
121 public static <O> Function<List<RpcResult<O>>, RpcResult<List<BatchFailedMetersOutput>>> createCumulativeFunction(
122 final Iterable<? extends org.opendaylight.yang.gen.v1.urn.opendaylight.meter.types.rev130918.Meter> inputBatchMeters,
123 final int sizeOfInputBatch) {
124 return new Function<List<RpcResult<O>>, RpcResult<List<BatchFailedMetersOutput>>>() {
127 public RpcResult<List<BatchFailedMetersOutput>> apply(@Nullable final List<RpcResult<O>> innerInput) {
128 final int sizeOfFutures = innerInput.size();
129 Preconditions.checkArgument(sizeOfFutures == sizeOfInputBatch,
130 "wrong amount of returned futures: {} <> {}", sizeOfFutures, sizeOfInputBatch);
132 final List<BatchFailedMetersOutput> batchMeters = new ArrayList<>();
133 final Iterator<? extends org.opendaylight.yang.gen.v1.urn.opendaylight.meter.types.rev130918.Meter>
134 batchMeterIterator = inputBatchMeters.iterator();
136 Collection<RpcError> meterErrors = new ArrayList<>(sizeOfFutures);
139 for (RpcResult<O> meterModOutput : innerInput) {
140 final MeterId meterId = batchMeterIterator.next().getMeterId();
142 if (!meterModOutput.isSuccessful()) {
143 batchMeters.add(new BatchFailedMetersOutputBuilder()
144 .setBatchOrder(batchOrder)
147 meterErrors.addAll(meterModOutput.getErrors());
152 final RpcResultBuilder<List<BatchFailedMetersOutput>> resultBuilder;
153 if (!meterErrors.isEmpty()) {
154 resultBuilder = RpcResultBuilder.<List<BatchFailedMetersOutput>>failed()
155 .withRpcErrors(meterErrors).withResult(batchMeters);
157 resultBuilder = SUCCESSFUL_METER_OUTPUT_RPC_RESULT;
159 return resultBuilder.build();
165 * Factory method: create {@link Function} which attaches barrier response to given {@link RpcResult}<T>
166 * and changes success flag if needed.
168 * Original rpcResult is the {@link Pair#getLeft()} and barrier result is the {@link Pair#getRight()}.
170 * @param <T> type of rpcResult value
171 * @return reusable static function
174 static <T extends BatchMeterOutputListGrouping>
175 Function<Pair<RpcResult<T>, RpcResult<Void>>, RpcResult<T>> createComposingFunction() {
176 return new Function<Pair<RpcResult<T>, RpcResult<Void>>, RpcResult<T>>() {
179 public RpcResult<T> apply(@Nullable final Pair<RpcResult<T>, RpcResult<Void>> input) {
180 final RpcResultBuilder<T> resultBld;
181 if (input.getLeft().isSuccessful() && input.getRight().isSuccessful()) {
182 resultBld = RpcResultBuilder.success();
184 resultBld = RpcResultBuilder.failed();
187 final ArrayList<RpcError> rpcErrors = new ArrayList<>(input.getLeft().getErrors());
188 rpcErrors.addAll(input.getRight().getErrors());
189 resultBld.withRpcErrors(rpcErrors);
191 resultBld.withResult(input.getLeft().getResult());
193 return resultBld.build();
199 * Wrap given list of problematic group-ids into {@link RpcResult} of given type.
201 * @param batchMetersCumulativeResult list of ids failed groups
203 * @param <T> group operation type
204 * @return batch group operation output of given type containing list of group-ids and corresponding success flag
206 private static <T extends BatchMeterOutputListGrouping>
207 RpcResultBuilder<T> createCumulativeRpcResult(final @Nullable RpcResult<List<BatchFailedMetersOutput>> batchMetersCumulativeResult,
208 final T batchOutput) {
209 final RpcResultBuilder<T> resultBld;
210 if (batchMetersCumulativeResult.isSuccessful()) {
211 resultBld = RpcResultBuilder.success(batchOutput);
213 resultBld = RpcResultBuilder.failed();
214 resultBld.withResult(batchOutput)
215 .withRpcErrors(batchMetersCumulativeResult.getErrors());