Remove duplicated code for rib support
[bgpcep.git] / bgp / rib-impl / src / main / java / org / opendaylight / protocol / bgp / rib / impl / AbstractIPRIBSupport.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 package org.opendaylight.protocol.bgp.rib.impl;
9
10 import com.google.common.base.Optional;
11 import com.google.common.base.Preconditions;
12 import com.google.common.collect.ImmutableCollection;
13 import com.google.common.collect.ImmutableSet;
14 import javax.annotation.Nonnull;
15 import org.opendaylight.controller.md.sal.dom.api.DOMDataWriteTransaction;
16 import org.opendaylight.protocol.bgp.rib.spi.AbstractRIBSupport;
17 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.rib.rev130925.Route;
18 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.rib.rev130925.rib.tables.Routes;
19 import org.opendaylight.yangtools.yang.binding.DataObject;
20 import org.opendaylight.yangtools.yang.common.QName;
21 import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier;
22 import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier.NodeIdentifier;
23 import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier.NodeIdentifierWithPredicates;
24 import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier.PathArgument;
25 import org.opendaylight.yangtools.yang.data.api.schema.ContainerNode;
26 import org.opendaylight.yangtools.yang.data.api.schema.DataContainerChild;
27 import org.opendaylight.yangtools.yang.data.api.schema.LeafNode;
28 import org.opendaylight.yangtools.yang.data.api.schema.UnkeyedListEntryNode;
29 import org.opendaylight.yangtools.yang.data.api.schema.UnkeyedListNode;
30 import org.slf4j.Logger;
31 import org.slf4j.LoggerFactory;
32
33 /**
34  * Common {@link org.opendaylight.protocol.bgp.rib.spi.RIBSupport} class for IPv4 and IPv6 addresses.
35  */
36 abstract class AbstractIPRIBSupport extends AbstractRIBSupport {
37     private static final Logger LOG = LoggerFactory.getLogger(AbstractIPRIBSupport.class);
38
39     protected AbstractIPRIBSupport(final Class<? extends Routes> cazeClass,
40         final Class<? extends DataObject> containerClass, final Class<? extends Route> listClass) {
41         super(cazeClass, containerClass, listClass);
42     }
43
44     /**
45      * Return the NodeIdentifier corresponding to the list containing individual routes.
46      *
47      * @return The NodeIdentifier for individual route list.
48      */
49     @Nonnull protected abstract NodeIdentifier routeIdentifier();
50
51     /**
52      * Return the NodeIdentifier corresponding to the list containing individual routes.
53      *
54      * @return The NodeIdentifier for individual route list.
55      */
56     @Nonnull protected abstract NodeIdentifier nlriRoutesListIdentifier();
57
58
59     @Nonnull protected abstract NodeIdentifier routeKeyLeafIdentifier();
60
61     @Nonnull protected abstract QName keyLeafQName();
62
63     @Nonnull protected abstract QName routeQName();
64
65
66     @Override
67     public final ImmutableCollection<Class<? extends DataObject>> cacheableAttributeObjects() {
68         return ImmutableSet.of();
69     }
70
71     @Override
72     public final boolean isComplexRoute() {
73         return false;
74     }
75
76     private void processDestination(final DOMDataWriteTransaction tx, final YangInstanceIdentifier routesPath,
77             final ContainerNode destination, final ContainerNode attributes, final ApplyRoute function) {
78         if (destination != null) {
79             final Optional<DataContainerChild<? extends PathArgument, ?>> maybeRoutes = destination.getChild(nlriRoutesListIdentifier());
80             if (maybeRoutes.isPresent()) {
81                 final DataContainerChild<? extends PathArgument, ?> routes = maybeRoutes.get();
82                 if (routes instanceof UnkeyedListNode) {
83                     // Instance identifier to table/(choice routes)/(map of route)
84                     // FIXME: cache on per-table basis (in TableContext, for example)
85                     final YangInstanceIdentifier base = routesPath.node(routesContainerIdentifier()).node(routeIdentifier());
86                     for (final UnkeyedListEntryNode e : ((UnkeyedListNode)routes).getValue()) {
87                         final NodeIdentifierWithPredicates routeKey = createRouteKey(e);
88                         function.apply(tx, base, routeKey,  e, attributes);
89                     }
90                 } else {
91                     LOG.warn("Routes {} are not a map", routes);
92                 }
93             }
94         }
95     }
96
97     private NodeIdentifierWithPredicates createRouteKey(final UnkeyedListEntryNode e) {
98         final Optional<DataContainerChild<? extends PathArgument, ?>> maybeKeyLeaf = e.getChild(routeKeyLeafIdentifier());
99         Preconditions.checkState(maybeKeyLeaf.isPresent());
100
101         // FIXME: a cache here would mean we instantiate the same identifier for each route
102         //        making comparison quicker.
103         final Object keyValue = ((LeafNode<?>) maybeKeyLeaf.get()).getValue();
104         return new NodeIdentifierWithPredicates(routeQName(), keyLeafQName(), keyValue);
105     }
106
107
108     @Override
109     protected void putDestinationRoutes(final DOMDataWriteTransaction tx, final YangInstanceIdentifier tablePath, final ContainerNode destination,
110             final ContainerNode attributes, final NodeIdentifier routesNodeId) {
111         processDestination(tx, tablePath.node(routesNodeId), destination, attributes, this.putRoute);
112     }
113
114     @Override
115     protected void deleteDestinationRoutes(final DOMDataWriteTransaction tx, final YangInstanceIdentifier tablePath,
116             final ContainerNode destination, final NodeIdentifier routesNodeId) {
117         processDestination(tx, tablePath.node(routesNodeId), destination, null, DELETE_ROUTE);
118     }
119 }