/* * Copyright (c) 2016 Cisco Systems, Inc. and others. All rights reserved. * * This program and the accompanying materials are made available under the * terms of the Eclipse Public License v1.0 which accompanies this distribution, * and is available at http://www.eclipse.org/legal/epl-v10.html */ package org.opendaylight.openflowplugin.impl.services.batch; import com.google.common.annotations.VisibleForTesting; import com.google.common.base.Function; import com.google.common.util.concurrent.Futures; import com.google.common.util.concurrent.JdkFutureAdapters; import com.google.common.util.concurrent.ListenableFuture; import java.util.ArrayList; import java.util.List; import java.util.concurrent.Future; import javax.annotation.Nullable; import org.opendaylight.yang.gen.v1.urn.opendaylight.flat.batch.service.rev160321.ProcessFlatBatchOutput; import org.opendaylight.yang.gen.v1.urn.opendaylight.flat.batch.service.rev160321.ProcessFlatBatchOutputBuilder; import org.opendaylight.yang.gen.v1.urn.opendaylight.flat.batch.service.rev160321.process.flat.batch.input.batch.batch.choice.flat.batch.add.meter._case.FlatBatchAddMeter; import org.opendaylight.yang.gen.v1.urn.opendaylight.flat.batch.service.rev160321.process.flat.batch.input.batch.batch.choice.flat.batch.remove.meter._case.FlatBatchRemoveMeter; import org.opendaylight.yang.gen.v1.urn.opendaylight.flat.batch.service.rev160321.process.flat.batch.input.batch.batch.choice.flat.batch.update.meter._case.FlatBatchUpdateMeter; import org.opendaylight.yang.gen.v1.urn.opendaylight.flat.batch.service.rev160321.process.flat.batch.output.BatchFailure; import org.opendaylight.yang.gen.v1.urn.opendaylight.flat.batch.service.rev160321.process.flat.batch.output.BatchFailureBuilder; import org.opendaylight.yang.gen.v1.urn.opendaylight.flat.batch.service.rev160321.process.flat.batch.output.batch.failure.batch.item.id.choice.FlatBatchFailureMeterIdCaseBuilder; import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.NodeRef; import org.opendaylight.yang.gen.v1.urn.opendaylight.meters.service.rev160316.AddMetersBatchInput; import org.opendaylight.yang.gen.v1.urn.opendaylight.meters.service.rev160316.AddMetersBatchInputBuilder; import org.opendaylight.yang.gen.v1.urn.opendaylight.meters.service.rev160316.BatchMeterOutputListGrouping; import org.opendaylight.yang.gen.v1.urn.opendaylight.meters.service.rev160316.RemoveMetersBatchInput; import org.opendaylight.yang.gen.v1.urn.opendaylight.meters.service.rev160316.RemoveMetersBatchInputBuilder; import org.opendaylight.yang.gen.v1.urn.opendaylight.meters.service.rev160316.UpdateMetersBatchInput; import org.opendaylight.yang.gen.v1.urn.opendaylight.meters.service.rev160316.UpdateMetersBatchInputBuilder; import org.opendaylight.yang.gen.v1.urn.opendaylight.meters.service.rev160316.add.meters.batch.input.BatchAddMeters; import org.opendaylight.yang.gen.v1.urn.opendaylight.meters.service.rev160316.add.meters.batch.input.BatchAddMetersBuilder; import org.opendaylight.yang.gen.v1.urn.opendaylight.meters.service.rev160316.batch.meter.output.list.grouping.BatchFailedMetersOutput; import org.opendaylight.yang.gen.v1.urn.opendaylight.meters.service.rev160316.remove.meters.batch.input.BatchRemoveMeters; import org.opendaylight.yang.gen.v1.urn.opendaylight.meters.service.rev160316.remove.meters.batch.input.BatchRemoveMetersBuilder; import org.opendaylight.yang.gen.v1.urn.opendaylight.meters.service.rev160316.update.meters.batch.input.BatchUpdateMeters; import org.opendaylight.yang.gen.v1.urn.opendaylight.meters.service.rev160316.update.meters.batch.input.BatchUpdateMetersBuilder; import org.opendaylight.yangtools.yang.common.RpcResult; import org.opendaylight.yangtools.yang.common.RpcResultBuilder; /** * Transform between FlatBatch API and meter batch API. */ public class FlatBatchMeterAdapters { private FlatBatchMeterAdapters() { throw new IllegalStateException("This class should not be instantiated."); } /** * @param planStep batch step containing changes of the same type * @param node pointer for RPC routing * @return input suitable for {@link org.opendaylight.yang.gen.v1.urn.opendaylight.meters.service.rev160316.SalMetersBatchService#addMetersBatch(AddMetersBatchInput)} */ public static AddMetersBatchInput adaptFlatBatchAddMeter(final BatchPlanStep planStep, final NodeRef node) { final List<BatchAddMeters> batchMeters = new ArrayList<>(); for (FlatBatchAddMeter batchAddMeter : planStep.<FlatBatchAddMeter>getTaskBag()) { final BatchAddMeters addMeters = new BatchAddMetersBuilder(batchAddMeter) .setMeterId(batchAddMeter.getMeterId()) .build(); batchMeters.add(addMeters); } return new AddMetersBatchInputBuilder() .setBarrierAfter(planStep.isBarrierAfter()) .setNode(node) .setBatchAddMeters(batchMeters) .build(); } /** * @param planStep batch step containing changes of the same type * @param node pointer for RPC routing * @return input suitable for {@link org.opendaylight.yang.gen.v1.urn.opendaylight.meters.service.rev160316.SalMetersBatchService#removeMetersBatch(RemoveMetersBatchInput)} */ public static RemoveMetersBatchInput adaptFlatBatchRemoveMeter(final BatchPlanStep planStep, final NodeRef node) { final List<BatchRemoveMeters> batchMeters = new ArrayList<>(); for (FlatBatchRemoveMeter batchRemoveMeter : planStep.<FlatBatchRemoveMeter>getTaskBag()) { final BatchRemoveMeters removeMeters = new BatchRemoveMetersBuilder(batchRemoveMeter) .setMeterId(batchRemoveMeter.getMeterId()) .build(); batchMeters.add(removeMeters); } return new RemoveMetersBatchInputBuilder() .setBarrierAfter(planStep.isBarrierAfter()) .setNode(node) .setBatchRemoveMeters(batchMeters) .build(); } /** * @param planStep batch step containing changes of the same type * @param node pointer for RPC routing * @return input suitable for {@link org.opendaylight.yang.gen.v1.urn.opendaylight.meters.service.rev160316.SalMetersBatchService#updateMetersBatch(UpdateMetersBatchInput)} */ public static UpdateMetersBatchInput adaptFlatBatchUpdateMeter(final BatchPlanStep planStep, final NodeRef node) { final List<BatchUpdateMeters> batchMeters = new ArrayList<>(); for (FlatBatchUpdateMeter batchUpdateMeter : planStep.<FlatBatchUpdateMeter>getTaskBag()) { final BatchUpdateMeters updateMeters = new BatchUpdateMetersBuilder(batchUpdateMeter) .build(); batchMeters.add(updateMeters); } return new UpdateMetersBatchInputBuilder() .setBarrierAfter(planStep.isBarrierAfter()) .setNode(node) .setBatchUpdateMeters(batchMeters) .build(); } /** * @param stepOffset offset of current batch plan step * @return converted {@link ProcessFlatBatchOutput} RPC result */ @VisibleForTesting static <T extends BatchMeterOutputListGrouping> Function<RpcResult<T>, RpcResult<ProcessFlatBatchOutput>> convertBatchMeterResult(final int stepOffset) { return new Function<RpcResult<T>, RpcResult<ProcessFlatBatchOutput>>() { @Nullable @Override public RpcResult<ProcessFlatBatchOutput> apply(@Nullable final RpcResult<T> input) { List<BatchFailure> batchFailures = wrapBatchMeterFailuresForFlat(input, stepOffset); ProcessFlatBatchOutputBuilder outputBuilder = new ProcessFlatBatchOutputBuilder().setBatchFailure(batchFailures); return RpcResultBuilder.<ProcessFlatBatchOutput>status(input.isSuccessful()) .withRpcErrors(input.getErrors()) .withResult(outputBuilder.build()) .build(); } }; } private static <T extends BatchMeterOutputListGrouping> List<BatchFailure> wrapBatchMeterFailuresForFlat( final RpcResult<T> input, final int stepOffset) { final List<BatchFailure> batchFailures = new ArrayList<>(); if (input.getResult().getBatchFailedMetersOutput() != null) { for (BatchFailedMetersOutput stepOutput : input.getResult().getBatchFailedMetersOutput()) { final BatchFailure batchFailure = new BatchFailureBuilder() .setBatchOrder(stepOffset + stepOutput.getBatchOrder()) .setBatchItemIdChoice(new FlatBatchFailureMeterIdCaseBuilder() .setMeterId(stepOutput.getMeterId()) .build()) .build(); batchFailures.add(batchFailure); } } return batchFailures; } /** * shortcut for {@link #convertBatchMeterResult(int)} with conversion {@link ListenableFuture} * * @param <T> exact type of batch flow output * @param resultUpdateMeterFuture batch group rpc-result (add/remove/update) * @param currentOffset offset of current batch plan step with respect to entire chain of steps * @return ListenableFuture with converted result {@link ProcessFlatBatchOutput} */ public static <T extends BatchMeterOutputListGrouping> ListenableFuture<RpcResult<ProcessFlatBatchOutput>> convertMeterBatchFutureForChain(final Future<RpcResult<T>> resultUpdateMeterFuture, final int currentOffset) { return Futures.transform(JdkFutureAdapters.listenInPoolThread(resultUpdateMeterFuture), FlatBatchMeterAdapters.<T>convertBatchMeterResult(currentOffset)); } }