b98fef9804a8348dc6f914d1699cb210cdc2542e
[bgpcep.git] / bgp / parser-spi / src / main / java / org / opendaylight / protocol / bgp / parser / spi / PathIdUtil.java
1 /*
2  * Copyright (c) 2016 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
9 package org.opendaylight.protocol.bgp.parser.spi;
10
11 import com.google.common.base.Preconditions;
12 import com.google.common.collect.ImmutableMap;
13 import io.netty.buffer.ByteBuf;
14 import java.util.Optional;
15 import org.opendaylight.protocol.util.ByteBufWriteUtil;
16 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.message.rev171207.PathId;
17 import org.opendaylight.yangtools.yang.common.QName;
18 import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier.NodeIdentifier;
19 import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier.NodeIdentifierWithPredicates;
20 import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier.PathArgument;
21 import org.opendaylight.yangtools.yang.data.api.schema.DataContainerChild;
22 import org.opendaylight.yangtools.yang.data.api.schema.DataContainerNode;
23 import org.opendaylight.yangtools.yang.data.api.schema.NormalizedNode;
24 import org.opendaylight.yangtools.yang.data.api.schema.NormalizedNodes;
25
26 public final class PathIdUtil {
27     public static final long NON_PATH_ID_VALUE = 0;
28     public static final PathId NON_PATH_ID = new PathId(NON_PATH_ID_VALUE);
29
30     private PathIdUtil() {
31         throw new UnsupportedOperationException();
32     }
33
34     /**
35      * Writes path-id value into the buffer when
36      * the path-id is not null or does not equal to zero.
37      *
38      * @param pathId The NLRI Path Identifier.
39      * @param buffer The ByteBuf where path-id value can be written.
40      */
41     public static void writePathId(final PathId pathId, final ByteBuf buffer) {
42         if (pathId != null && pathId.getValue() != 0) {
43             ByteBufWriteUtil.writeUnsignedInt(pathId.getValue(), buffer);
44         }
45     }
46
47     /**
48      * Reads Path Identifier (4 bytes) from buffer.
49      *
50      * @param buffer Input buffer.
51      * @return Decoded PathId.
52      */
53     public static PathId readPathId(final ByteBuf buffer) {
54         Preconditions.checkArgument(buffer != null && buffer.isReadable(ByteBufWriteUtil.INT_BYTES_LENGTH));
55         return new PathId(buffer.readUnsignedInt());
56     }
57
58     /**
59      * Extract PathId from route change received
60      *
61      * @param data    Data containing the path Id
62      * @param pathNii Path Id NodeIdentifier specific per each Rib support
63      * @return The path identifier from data change
64      */
65     public static Long extractPathId(final NormalizedNode<?, ?> data, final NodeIdentifier pathNii) {
66         return (Long) NormalizedNodes.findNode(data, pathNii).map(NormalizedNode::getValue).orElse(null);
67     }
68
69     /**
70      * Get route key object ( prefgit stat  ix / key-value/ .. ).
71      *
72      * @param routeId       PathArgument containing the key
73      * @param routeKeyQname routeKey Qname
74      * @return key
75      */
76     public static Object getObjectKey(final NodeIdentifierWithPredicates routeId, final QName routeKeyQname) {
77         return routeId.getKeyValues().get(routeKeyQname);
78     }
79
80     public static NodeIdentifierWithPredicates createNodeIdentifierWithPredicates(final QName routeQname,
81             final QName pathidQname, final Object pathId,
82             final QName routeKeyQname, final Object keyObject) {
83         final ImmutableMap<QName, Object> keyValues = ImmutableMap.of(pathidQname, pathId, routeKeyQname, keyObject);
84         return new NodeIdentifierWithPredicates(routeQname, keyValues);
85     }
86
87     /**
88      * Build Path Id.
89      *
90      * @param routesCont route container
91      * @param pathIdNii  path Id node Identifier
92      * @return PathId or null in case is not the container
93      */
94     public static PathId buildPathId(final DataContainerNode<? extends PathArgument> routesCont,
95             final NodeIdentifier pathIdNii) {
96         final Long pathIdVal = PathIdUtil.extractPathId(routesCont, pathIdNii);
97         return pathIdVal == null ? null : new PathId(pathIdVal);
98     }
99
100     /**
101      * Build Route Key for supporting mp.
102      * Key is composed by 2 elements (route-key + path Id).
103      *
104      * @param routeQname      route Qname
105      * @param routeKeyQname   route key Qname
106      * @param pathIdQname     path Id Qname
107      * @param routeKeyValue   route key value
108      * @param maybePathIdLeaf path id container, it might me supported or not, in that case default 0 value will
109      *                        be
110      *                        assigned
111      * @return Route Key Nid
112      */
113     public static NodeIdentifierWithPredicates createNidKey(final QName routeQname, final QName routeKeyQname,
114             final QName pathIdQname, final Object routeKeyValue,
115             final Optional<DataContainerChild<? extends PathArgument, ?>> maybePathIdLeaf) {
116         // FIXME: a cache here would mean we instantiate the same identifier for each route making comparison quicker.
117         final Object pathId = maybePathIdLeaf.isPresent() ? maybePathIdLeaf.get().getValue() : NON_PATH_ID_VALUE;
118         return createNodeIdentifierWithPredicates(routeQname, pathIdQname, pathId, routeKeyQname, routeKeyValue);
119     }
120 }