Merge "BUG-49 : added tests & removed warnings: bgp-parser-spi"
[bgpcep.git] / bgp / parser-spi / src / main / java / org / opendaylight / protocol / bgp / parser / spi / pojo / SimpleAttributeRegistry.java
1 /*
2  * Copyright (c) 2013 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.parser.spi.pojo;
9
10 import org.opendaylight.protocol.bgp.parser.BGPDocumentedException;
11 import org.opendaylight.protocol.bgp.parser.BGPError;
12 import org.opendaylight.protocol.bgp.parser.BGPParsingException;
13 import org.opendaylight.protocol.bgp.parser.spi.AttributeParser;
14 import org.opendaylight.protocol.bgp.parser.spi.AttributeRegistry;
15 import org.opendaylight.protocol.bgp.parser.spi.AttributeSerializer;
16 import org.opendaylight.protocol.concepts.HandlerRegistry;
17 import org.opendaylight.protocol.util.ByteArray;
18 import org.opendaylight.protocol.util.Util;
19 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.message.rev130918.update.PathAttributes;
20 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.message.rev130918.update.PathAttributesBuilder;
21 import org.opendaylight.yangtools.yang.binding.DataContainer;
22 import org.opendaylight.yangtools.yang.binding.DataObject;
23
24 import com.google.common.base.Preconditions;
25 import com.google.common.primitives.UnsignedBytes;
26
27 final class SimpleAttributeRegistry implements AttributeRegistry {
28         private final HandlerRegistry<DataContainer, AttributeParser, AttributeSerializer> handlers = new HandlerRegistry<>();
29
30         AutoCloseable registerAttributeParser(final int attributeType, final AttributeParser parser) {
31                 Preconditions.checkArgument(attributeType >= 0 && attributeType <= Util.UNSIGNED_BYTE_MAX_VALUE);
32                 return this.handlers.registerParser(attributeType, parser);
33         }
34
35         AutoCloseable registerAttributeSerializer(final Class<? extends DataObject> paramClass, final AttributeSerializer serializer) {
36                 return this.handlers.registerSerializer(paramClass, serializer);
37         }
38
39         private int parseAttribute(final byte[] bytes, final int offset, final PathAttributesBuilder builder) throws BGPDocumentedException,
40                         BGPParsingException {
41                 // FIXME: validate minimum length
42                 final boolean[] flags = ByteArray.parseBits(bytes[offset]);
43                 final int type = UnsignedBytes.toInt(bytes[offset + 1]);
44                 final int hdrlen;
45                 final int len;
46                 if (flags[3]) {
47                         len = UnsignedBytes.toInt(bytes[offset + 2]) * 256 + UnsignedBytes.toInt(bytes[offset + 3]);
48                         hdrlen = 4;
49                 } else {
50                         len = UnsignedBytes.toInt(bytes[offset + 2]);
51                         hdrlen = 3;
52                 }
53
54                 final AttributeParser parser = this.handlers.getParser(type);
55                 if (parser == null) {
56                         if (!flags[0]) {
57                                 throw new BGPDocumentedException("Well known attribute not recognized.", BGPError.WELL_KNOWN_ATTR_NOT_RECOGNIZED);
58                         }
59                 } else {
60                         parser.parseAttribute(ByteArray.subByte(bytes, offset + hdrlen, len), builder);
61                 }
62
63                 return hdrlen + len;
64         }
65
66         @Override
67         public PathAttributes parseAttributes(final byte[] bytes) throws BGPDocumentedException, BGPParsingException {
68                 int byteOffset = 0;
69                 final PathAttributesBuilder builder = new PathAttributesBuilder();
70                 while (byteOffset < bytes.length) {
71                         byteOffset += parseAttribute(bytes, byteOffset, builder);
72                 }
73                 return builder.build();
74         }
75
76         @Override
77         public byte[] serializeAttribute(final DataObject attribute) {
78                 final AttributeSerializer serializer = this.handlers.getSerializer(attribute.getImplementedInterface());
79                 if (serializer == null) {
80                         return null;
81                 }
82
83                 return serializer.serializeAttribute(attribute);
84         }
85 }