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.group.types.rev131018.GroupId;
24 import org.opendaylight.yang.gen.v1.urn.opendaylight.group.types.rev131018.GroupRef;
25 import org.opendaylight.yang.gen.v1.urn.opendaylight.group.types.rev131018.groups.Group;
26 import org.opendaylight.yang.gen.v1.urn.opendaylight.group.types.rev131018.groups.GroupKey;
27 import org.opendaylight.yang.gen.v1.urn.opendaylight.groups.service.rev160315.AddGroupsBatchOutput;
28 import org.opendaylight.yang.gen.v1.urn.opendaylight.groups.service.rev160315.AddGroupsBatchOutputBuilder;
29 import org.opendaylight.yang.gen.v1.urn.opendaylight.groups.service.rev160315.BatchGroupOutputListGrouping;
30 import org.opendaylight.yang.gen.v1.urn.opendaylight.groups.service.rev160315.RemoveGroupsBatchOutput;
31 import org.opendaylight.yang.gen.v1.urn.opendaylight.groups.service.rev160315.RemoveGroupsBatchOutputBuilder;
32 import org.opendaylight.yang.gen.v1.urn.opendaylight.groups.service.rev160315.UpdateGroupsBatchOutput;
33 import org.opendaylight.yang.gen.v1.urn.opendaylight.groups.service.rev160315.UpdateGroupsBatchOutputBuilder;
34 import org.opendaylight.yang.gen.v1.urn.opendaylight.groups.service.rev160315.batch.group.output.list.grouping.BatchFailedGroupsOutput;
35 import org.opendaylight.yang.gen.v1.urn.opendaylight.groups.service.rev160315.batch.group.output.list.grouping.BatchFailedGroupsOutputBuilder;
36 import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.nodes.Node;
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 group util methods
46 public final class GroupUtil {
48 private static final RpcResultBuilder<List<BatchFailedGroupsOutput>> SUCCESSFUL_GROUP_OUTPUT_RPC_RESULT =
49 RpcResultBuilder.success(Collections.<BatchFailedGroupsOutput>emptyList());
51 public static final Function<RpcResult<List<BatchFailedGroupsOutput>>, RpcResult<AddGroupsBatchOutput>> GROUP_ADD_TRANSFORM =
52 new Function<RpcResult<List<BatchFailedGroupsOutput>>, RpcResult<AddGroupsBatchOutput>>() {
55 public RpcResult<AddGroupsBatchOutput> apply(@Nullable final RpcResult<List<BatchFailedGroupsOutput>> batchGroupsCumulatedResult) {
56 final AddGroupsBatchOutput batchOutput = new AddGroupsBatchOutputBuilder()
57 .setBatchFailedGroupsOutput(batchGroupsCumulatedResult.getResult()).build();
59 final RpcResultBuilder<AddGroupsBatchOutput> resultBld =
60 createCumulativeRpcResult(batchGroupsCumulatedResult, batchOutput);
61 return resultBld.build();
64 public static final Function<Pair<RpcResult<AddGroupsBatchOutput>, RpcResult<Void>>, RpcResult<AddGroupsBatchOutput>>
65 GROUP_ADD_COMPOSING_TRANSFORM = createComposingFunction();
67 public static final Function<RpcResult<List<BatchFailedGroupsOutput>>, RpcResult<RemoveGroupsBatchOutput>> GROUP_REMOVE_TRANSFORM =
68 new Function<RpcResult<List<BatchFailedGroupsOutput>>, RpcResult<RemoveGroupsBatchOutput>>() {
71 public RpcResult<RemoveGroupsBatchOutput> apply(@Nullable final RpcResult<List<BatchFailedGroupsOutput>> batchGroupsCumulatedResult) {
72 final RemoveGroupsBatchOutput batchOutput = new RemoveGroupsBatchOutputBuilder()
73 .setBatchFailedGroupsOutput(batchGroupsCumulatedResult.getResult()).build();
75 final RpcResultBuilder<RemoveGroupsBatchOutput> resultBld =
76 createCumulativeRpcResult(batchGroupsCumulatedResult, batchOutput);
77 return resultBld.build();
80 public static final Function<Pair<RpcResult<RemoveGroupsBatchOutput>, RpcResult<Void>>, RpcResult<RemoveGroupsBatchOutput>>
81 GROUP_REMOVE_COMPOSING_TRANSFORM = createComposingFunction();
83 public static final Function<RpcResult<List<BatchFailedGroupsOutput>>, RpcResult<UpdateGroupsBatchOutput>> GROUP_UPDATE_TRANSFORM =
84 new Function<RpcResult<List<BatchFailedGroupsOutput>>, RpcResult<UpdateGroupsBatchOutput>>() {
87 public RpcResult<UpdateGroupsBatchOutput> apply(@Nullable final RpcResult<List<BatchFailedGroupsOutput>> batchGroupsCumulatedResult) {
88 final UpdateGroupsBatchOutput batchOutput = new UpdateGroupsBatchOutputBuilder()
89 .setBatchFailedGroupsOutput(batchGroupsCumulatedResult.getResult()).build();
91 final RpcResultBuilder<UpdateGroupsBatchOutput> resultBld =
92 createCumulativeRpcResult(batchGroupsCumulatedResult, batchOutput);
93 return resultBld.build();
96 public static final Function<Pair<RpcResult<UpdateGroupsBatchOutput>, RpcResult<Void>>, RpcResult<UpdateGroupsBatchOutput>>
97 GROUP_UPDATE_COMPOSING_TRANSFORM = createComposingFunction();
100 throw new IllegalStateException("This class should not be instantiated.");
106 * @return instance identifier assembled for given node and group
108 public static GroupRef buildGroupPath(final InstanceIdentifier<Node> nodePath, final GroupId groupId) {
109 final KeyedInstanceIdentifier<Group, GroupKey> groupPath = nodePath
110 .augmentation(FlowCapableNode.class)
111 .child(Group.class, new GroupKey(groupId));
113 return new GroupRef(groupPath);
116 public static <O> Function<List<RpcResult<O>>, RpcResult<List<BatchFailedGroupsOutput>>> createCumulatingFunction(
117 final Iterable<? extends org.opendaylight.yang.gen.v1.urn.opendaylight.group.types.rev131018.Group> inputBatchGroups) {
118 return createCumulatingFunction(inputBatchGroups, Iterables.size(inputBatchGroups));
121 public static <O> Function<List<RpcResult<O>>, RpcResult<List<BatchFailedGroupsOutput>>> createCumulatingFunction(
122 final Iterable<? extends org.opendaylight.yang.gen.v1.urn.opendaylight.group.types.rev131018.Group> inputBatchGroups,
123 final int sizeOfInputBatch) {
124 return new Function<List<RpcResult<O>>, RpcResult<List<BatchFailedGroupsOutput>>>() {
127 public RpcResult<List<BatchFailedGroupsOutput>> 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<BatchFailedGroupsOutput> batchGroups = new ArrayList<>();
133 final Iterator<? extends org.opendaylight.yang.gen.v1.urn.opendaylight.group.types.rev131018.Group>
134 batchGroupIterator = inputBatchGroups.iterator();
136 Collection<RpcError> groupErrors = new ArrayList<>(sizeOfFutures);
139 for (RpcResult<O> groupModOutput : innerInput) {
140 final GroupId groupId = batchGroupIterator.next().getGroupId();
142 if (!groupModOutput.isSuccessful()) {
143 batchGroups.add(new BatchFailedGroupsOutputBuilder()
145 .setBatchOrder(batchOrder)
147 groupErrors.addAll(groupModOutput.getErrors());
152 final RpcResultBuilder<List<BatchFailedGroupsOutput>> resultBuilder;
153 if (!groupErrors.isEmpty()) {
154 resultBuilder = RpcResultBuilder.<List<BatchFailedGroupsOutput>>failed()
155 .withRpcErrors(groupErrors).withResult(batchGroups);
157 resultBuilder = SUCCESSFUL_GROUP_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 BatchGroupOutputListGrouping>
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 batchGroupsCumulativeResult 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 BatchGroupOutputListGrouping>
207 RpcResultBuilder<T> createCumulativeRpcResult(final @Nullable RpcResult<List<BatchFailedGroupsOutput>> batchGroupsCumulativeResult,
208 final T batchOutput) {
209 final RpcResultBuilder<T> resultBld;
210 if (batchGroupsCumulativeResult.isSuccessful()) {
211 resultBld = RpcResultBuilder.success(batchOutput);
213 resultBld = RpcResultBuilder.failed();
214 resultBld.withResult(batchOutput)
215 .withRpcErrors(batchGroupsCumulativeResult.getErrors());