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