Modernize bmp-impl
[bgpcep.git] / bmp / bmp-impl / src / main / java / org / opendaylight / protocol / bmp / impl / app / TableContext.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.bmp.impl.app;
9
10 import static com.google.common.base.Preconditions.checkState;
11 import static java.util.Objects.requireNonNull;
12 import static org.opendaylight.protocol.bmp.impl.app.TablesUtil.BMP_ATTRIBUTES_QNAME;
13 import static org.opendaylight.protocol.bmp.impl.app.TablesUtil.BMP_ROUTES_QNAME;
14
15 import java.util.Map;
16 import org.opendaylight.mdsal.binding.dom.codec.api.BindingCodecTree;
17 import org.opendaylight.mdsal.binding.dom.codec.api.BindingCodecTreeNode;
18 import org.opendaylight.mdsal.binding.dom.codec.api.BindingDataObjectCodecTreeNode;
19 import org.opendaylight.mdsal.binding.dom.codec.api.BindingNormalizedNodeCachingCodec;
20 import org.opendaylight.mdsal.common.api.LogicalDatastoreType;
21 import org.opendaylight.mdsal.dom.api.DOMDataTreeWriteTransaction;
22 import org.opendaylight.protocol.bgp.rib.spi.RIBSupport;
23 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.message.rev200120.Update;
24 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.message.rev200120.path.attributes.Attributes;
25 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.message.rev200120.path.attributes.AttributesBuilder;
26 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.multiprotocol.rev180329.AttributesReach;
27 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.multiprotocol.rev180329.AttributesUnreach;
28 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.multiprotocol.rev180329.attributes.reach.MpReachNlri;
29 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.multiprotocol.rev180329.attributes.unreach.MpUnreachNlri;
30 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.rib.rev180329.rib.tables.Routes;
31 import org.opendaylight.yangtools.yang.common.QName;
32 import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier;
33 import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier.NodeIdentifier;
34 import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier.NodeIdentifierWithPredicates;
35 import org.opendaylight.yangtools.yang.data.api.schema.ContainerNode;
36 import org.opendaylight.yangtools.yang.data.spi.node.ImmutableNodes;
37
38 // This class is NOT thread-safe
39 final class TableContext {
40
41     private static final ContainerNode EMPTY_TABLE_ATTRIBUTES = ImmutableNodes.newContainerBuilder()
42         .withNodeIdentifier(NodeIdentifier.create(BMP_ATTRIBUTES_QNAME))
43         .build();
44     private static final NodeIdentifier BGP_ROUTES_NODE_ID = new NodeIdentifier(BMP_ROUTES_QNAME);
45
46     private final YangInstanceIdentifier tableId;
47     private final RIBSupport<?, ?> tableSupport;
48     private final BindingNormalizedNodeCachingCodec<Attributes> attributesCodec;
49     private final BindingNormalizedNodeCachingCodec<MpReachNlri> reachNlriCodec;
50     private final BindingNormalizedNodeCachingCodec<MpUnreachNlri> unreachNlriCodec;
51
52     @SuppressWarnings({ "unchecked", "rawtypes" })
53     TableContext(final RIBSupport tableSupport, final YangInstanceIdentifier tableId, final BindingCodecTree tree) {
54         this.tableSupport = requireNonNull(tableSupport);
55         this.tableId = requireNonNull(tableId);
56         final BindingCodecTreeNode tableCodecContext = tree.getSubtreeCodec(tableId);
57
58         checkState(tableCodecContext instanceof BindingDataObjectCodecTreeNode);
59         final BindingDataObjectCodecTreeNode<?> routeListCodec = ((BindingDataObjectCodecTreeNode)tableCodecContext)
60             .getStreamChild(Routes.class)
61             .getStreamChild(this.tableSupport.routesCaseClass())
62             .getStreamChild(this.tableSupport.routesContainerClass())
63             .getStreamDataObject(this.tableSupport.routesListClass());
64
65         attributesCodec = routeListCodec.getStreamDataObject(Attributes.class)
66                 .createCachingCodec(this.tableSupport.cacheableAttributeObjects());
67
68         final var updateAttributesCodec = tree.getStreamChild(Update.class)
69                 .getStreamDataObject(Attributes.class);
70         reachNlriCodec = updateAttributesCodec.getStreamChild(AttributesReach.class)
71             .getStreamDataObject(MpReachNlri.class)
72             .createCachingCodec(this.tableSupport.cacheableNlriObjects());
73         unreachNlriCodec = updateAttributesCodec.getStreamChild(AttributesUnreach.class)
74             .getStreamDataObject(MpUnreachNlri.class)
75             .createCachingCodec(this.tableSupport.cacheableNlriObjects());
76     }
77
78     YangInstanceIdentifier getTableId() {
79         return tableId;
80     }
81
82     void createTable(final DOMDataTreeWriteTransaction tx) {
83         final var tb = ImmutableNodes.newMapEntryBuilder()
84             .withNodeIdentifier((NodeIdentifierWithPredicates) tableId.getLastPathArgument())
85             .withChild(EMPTY_TABLE_ATTRIBUTES);
86
87         // tableId is keyed, but that fact is not directly visible from YangInstanceIdentifier, see BUG-2796
88         final var tableKey = (NodeIdentifierWithPredicates) tableId.getLastPathArgument();
89         for (final Map.Entry<QName, Object> e : tableKey.entrySet()) {
90             tb.withChild(ImmutableNodes.leafNode(e.getKey(), e.getValue()));
91         }
92
93         tx.put(LogicalDatastoreType.OPERATIONAL, tableId,
94             tb.withChild(ImmutableNodes.newChoiceBuilder()
95                 .withNodeIdentifier(new NodeIdentifier(TablesUtil.BMP_ROUTES_QNAME))
96                 .build())
97             .build());
98     }
99
100     void writeRoutes(final DOMDataTreeWriteTransaction tx, final MpReachNlri nlri, final Attributes attributes) {
101         final ContainerNode domNlri = serializeReachNlri(nlri);
102         final ContainerNode routeAttributes = serializeAttributes(attributes);
103         tableSupport.putRoutes(tx, tableId, domNlri, routeAttributes, BGP_ROUTES_NODE_ID);
104     }
105
106     void removeRoutes(final DOMDataTreeWriteTransaction tx, final MpUnreachNlri nlri) {
107         tableSupport.deleteRoutes(tx, tableId, serializeUnreachNlri(nlri), BGP_ROUTES_NODE_ID);
108     }
109
110     private ContainerNode serializeUnreachNlri(final MpUnreachNlri nlri) {
111         checkState(unreachNlriCodec != null, "MpUnReachNlri codec not available");
112         return (ContainerNode) unreachNlriCodec.serialize(nlri);
113     }
114
115     private ContainerNode serializeReachNlri(final MpReachNlri nlri) {
116         checkState(reachNlriCodec != null, "MpReachNlri codec not available");
117         return (ContainerNode) reachNlriCodec.serialize(nlri);
118     }
119
120     private ContainerNode serializeAttributes(final Attributes pathAttr) {
121         checkState(attributesCodec != null, "Attributes codec not available");
122         final AttributesBuilder a = new AttributesBuilder(pathAttr);
123         a.removeAugmentation(AttributesReach.class);
124         a.removeAugmentation(AttributesUnreach.class);
125         return (ContainerNode) attributesCodec.serialize(a.build());
126     }
127 }